Skip to content

Commit c6badf4

Browse files
committed
feature #2792 [Map] Add option to configure attribution and zoom control (Danny van Wijk)
This PR was merged into the 2.x branch. Discussion ---------- [Map] Add option to configure attribution and zoom control | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes <!-- please update src/**/CHANGELOG.md files --> | Docs? | yes <!-- required for new features --> | Issues | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead --> | License | MIT <!-- Replace this notice by a description of your feature/bugfix. This will help reviewers and should be a good start for the documentation. Additionally (see https://symfony.com/releases): - Always add tests and ensure they pass. - For new features, provide some code snippets to help understand usage. - Features and deprecations must be submitted against branch main. - Update/add documentation as required (we can help!) - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry - Never break backward compatibility (see https://symfony.com/bc). --> Add option to configure attribution and zoom control for leaflet Commits ------- 6851e76 [Map][Leaflet] Add options `attributionControl`, `attributionControlOptions`, `zoomControl` and `zoomControlOptions`
2 parents bb13764 + 6851e76 commit c6badf4

20 files changed

+380
-15
lines changed

src/Map/src/Bridge/Leaflet/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# CHANGELOG
22

3+
## 2.27
4+
5+
- Add `attributionControl` and `attributionControlOptions` to `LeafletOptions`,
6+
to configure [attribution control](https://leafletjs.com/reference.html#map-attributioncontrol) and its options
7+
- Add `zoomControl` and `zoomControlOptions` to `LeafletOptions`,
8+
to configure [zoom control](https://leafletjs.com/reference.html#map-zoomcontrol) and its options
9+
310
## 2.26
411

512
- Using `new LeafletOptions(tileLayer: false)` will now disable the default `TileLayer`.

src/Map/src/Bridge/Leaflet/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ You can use the `LeafletOptions` class to configure your `Map`::
3333

3434
```php
3535
use Symfony\UX\Map\Bridge\Leaflet\LeafletOptions;
36+
use Symfony\UX\Map\Bridge\Leaflet\Option\AttributionControlOptions;
37+
use Symfony\UX\Map\Bridge\Leaflet\Option\ControlPosition;
3638
use Symfony\UX\Map\Bridge\Leaflet\Option\TileLayer;
39+
use Symfony\UX\Map\Bridge\Leaflet\Option\ZoomControlOptions;
3740
use Symfony\UX\Map\Point;
3841
use Symfony\UX\Map\Map;
3942

@@ -50,6 +53,10 @@ $leafletOptions = (new LeafletOptions())
5053
'maxZoom' => 10,
5154
]
5255
))
56+
->attributionControl(false)
57+
->attributionControlOptions(new AttributionControlOptions(ControlPosition::BOTTOM_LEFT))
58+
->zoomControl(false)
59+
->zoomControlOptions(new ZoomControlOptions(ControlPosition::TOP_LEFT))
5360
;
5461

5562
// Add the custom options to the map

src/Map/src/Bridge/Leaflet/assets/dist/map_controller.d.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@ import AbstractMapController from '@symfony/ux-map';
22
import type { Icon, InfoWindowWithoutPositionDefinition, MarkerDefinition, Point, PolygonDefinition, PolylineDefinition } from '@symfony/ux-map';
33
import 'leaflet/dist/leaflet.min.css';
44
import * as L from 'leaflet';
5-
import type { MapOptions as LeafletMapOptions, MarkerOptions, PolylineOptions as PolygonOptions, PolylineOptions, PopupOptions } from 'leaflet';
6-
type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom'> & {
5+
import type { ControlPosition, MapOptions as LeafletMapOptions, MarkerOptions, PolylineOptions as PolygonOptions, PolylineOptions, PopupOptions } from 'leaflet';
6+
type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom' | 'attributionControl' | 'zoomControl'> & {
7+
attributionControlOptions?: {
8+
position: ControlPosition;
9+
prefix: string | false;
10+
};
11+
zoomControlOptions?: {
12+
position: ControlPosition;
13+
zoomInText: string;
14+
zoomInTitle: string;
15+
zoomOutText: string;
16+
zoomOutTitle: string;
17+
};
718
tileLayer: {
819
url: string;
920
attribution: string;

src/Map/src/Bridge/Leaflet/assets/dist/map_controller.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,21 @@ class map_controller extends default_1 {
144144
...options,
145145
center: center === null ? undefined : center,
146146
zoom: zoom === null ? undefined : zoom,
147+
attributionControl: false,
148+
zoomControl: false,
147149
});
148150
if (options.tileLayer) {
149151
L.tileLayer(options.tileLayer.url, {
150152
attribution: options.tileLayer.attribution,
151153
...options.tileLayer.options,
152154
}).addTo(map);
153155
}
156+
if (typeof options.attributionControlOptions !== 'undefined') {
157+
L.control.attribution({ ...options.attributionControlOptions }).addTo(map);
158+
}
159+
if (typeof options.zoomControlOptions !== 'undefined') {
160+
L.control.zoom({ ...options.zoomControlOptions }).addTo(map);
161+
}
154162
return map;
155163
}
156164
doCreateMarker({ definition }) {

src/Map/src/Bridge/Leaflet/assets/src/map_controller.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
import 'leaflet/dist/leaflet.min.css';
1111
import * as L from 'leaflet';
1212
import type {
13+
ControlPosition,
1314
LatLngBoundsExpression,
1415
MapOptions as LeafletMapOptions,
1516
MarkerOptions,
@@ -18,7 +19,15 @@ import type {
1819
PopupOptions,
1920
} from 'leaflet';
2021

21-
type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom'> & {
22+
type MapOptions = Pick<LeafletMapOptions, 'center' | 'zoom' | 'attributionControl' | 'zoomControl'> & {
23+
attributionControlOptions?: { position: ControlPosition; prefix: string | false };
24+
zoomControlOptions?: {
25+
position: ControlPosition;
26+
zoomInText: string;
27+
zoomInTitle: string;
28+
zoomOutText: string;
29+
zoomOutTitle: string;
30+
};
2231
tileLayer: { url: string; attribution: string; options: Record<string, unknown> } | false;
2332
};
2433

@@ -79,6 +88,8 @@ export default class extends AbstractMapController<
7988
...options,
8089
center: center === null ? undefined : center,
8190
zoom: zoom === null ? undefined : zoom,
91+
attributionControl: false,
92+
zoomControl: false,
8293
});
8394

8495
if (options.tileLayer) {
@@ -88,6 +99,14 @@ export default class extends AbstractMapController<
8899
}).addTo(map);
89100
}
90101

102+
if (typeof options.attributionControlOptions !== 'undefined') {
103+
L.control.attribution({ ...options.attributionControlOptions }).addTo(map);
104+
}
105+
106+
if (typeof options.zoomControlOptions !== 'undefined') {
107+
L.control.zoom({ ...options.zoomControlOptions }).addTo(map);
108+
}
109+
91110
return map;
92111
}
93112

src/Map/src/Bridge/Leaflet/src/LeafletOptions.php

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
namespace Symfony\UX\Map\Bridge\Leaflet;
1313

14+
use Symfony\UX\Map\Bridge\Leaflet\Option\AttributionControlOptions;
1415
use Symfony\UX\Map\Bridge\Leaflet\Option\TileLayer;
16+
use Symfony\UX\Map\Bridge\Leaflet\Option\ZoomControlOptions;
1517
use Symfony\UX\Map\MapOptionsInterface;
1618

1719
/**
@@ -24,6 +26,10 @@ public function __construct(
2426
url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
2527
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
2628
),
29+
private bool $attributionControl = true,
30+
private AttributionControlOptions $attributionControlOptions = new AttributionControlOptions(),
31+
private bool $zoomControl = true,
32+
private ZoomControlOptions $zoomControlOptions = new ZoomControlOptions(),
2733
) {
2834
}
2935

@@ -34,23 +40,77 @@ public function tileLayer(TileLayer|false $tileLayer): self
3440
return $this;
3541
}
3642

43+
public function attributionControl(bool $enable = true): self
44+
{
45+
$this->attributionControl = $enable;
46+
47+
return $this;
48+
}
49+
50+
public function attributionControlOptions(AttributionControlOptions $attributionControlOptions): self
51+
{
52+
$this->attributionControl = true;
53+
$this->attributionControlOptions = $attributionControlOptions;
54+
55+
return $this;
56+
}
57+
58+
public function zoomControl(bool $enable = true): self
59+
{
60+
$this->zoomControl = $enable;
61+
62+
return $this;
63+
}
64+
65+
public function zoomControlOptions(ZoomControlOptions $zoomControlOptions): self
66+
{
67+
$this->zoomControl = true;
68+
$this->zoomControlOptions = $zoomControlOptions;
69+
70+
return $this;
71+
}
72+
3773
/**
3874
* @internal
3975
*/
4076
public static function fromArray(array $array): MapOptionsInterface
4177
{
42-
return new self(
43-
tileLayer: $array['tileLayer'] ? TileLayer::fromArray($array['tileLayer']) : false,
44-
);
78+
$array += ['attributionControl' => false, 'zoomControl' => false, 'tileLayer' => false];
79+
80+
if ($array['tileLayer']) {
81+
$array['tileLayer'] = TileLayer::fromArray($array['tileLayer']);
82+
}
83+
84+
if (isset($array['attributionControlOptions'])) {
85+
$array['attributionControl'] = true;
86+
$array['attributionControlOptions'] = AttributionControlOptions::fromArray($array['attributionControlOptions']);
87+
}
88+
89+
if (isset($array['zoomControlOptions'])) {
90+
$array['zoomControl'] = true;
91+
$array['zoomControlOptions'] = ZoomControlOptions::fromArray($array['zoomControlOptions']);
92+
}
93+
94+
return new self(...$array);
4595
}
4696

4797
/**
4898
* @internal
4999
*/
50100
public function toArray(): array
51101
{
52-
return [
102+
$array = [
53103
'tileLayer' => $this->tileLayer ? $this->tileLayer->toArray() : false,
54104
];
105+
106+
if ($this->attributionControl) {
107+
$array['attributionControlOptions'] = $this->attributionControlOptions->toArray();
108+
}
109+
110+
if ($this->zoomControl) {
111+
$array['zoomControlOptions'] = $this->zoomControlOptions->toArray();
112+
}
113+
114+
return $array;
55115
}
56116
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\Map\Bridge\Leaflet\Option;
13+
14+
/**
15+
* Options for the rendering of the attribution control.
16+
*
17+
* @see https://leafletjs.com/reference.html#control-zoom
18+
*/
19+
final class AttributionControlOptions
20+
{
21+
public function __construct(
22+
private readonly ControlPosition $position = ControlPosition::BOTTOM_RIGHT,
23+
private readonly string|false $prefix = 'Leaflet',
24+
) {
25+
}
26+
27+
/**
28+
* @internal
29+
*/
30+
public static function fromArray(array $array): self
31+
{
32+
return new self(
33+
position: ControlPosition::from($array['position']),
34+
prefix: $array['prefix'],
35+
);
36+
}
37+
38+
/**
39+
* @internal
40+
*/
41+
public function toArray(): array
42+
{
43+
return [
44+
'position' => $this->position->value,
45+
'prefix' => $this->prefix,
46+
];
47+
}
48+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\Map\Bridge\Leaflet\Option;
13+
14+
/**
15+
* @see https://leafletjs.com/reference.html#control-position
16+
*/
17+
enum ControlPosition: string
18+
{
19+
case TOP_LEFT = 'topleft';
20+
case TOP_RIGHT = 'topright';
21+
case BOTTOM_LEFT = 'bottomleft';
22+
case BOTTOM_RIGHT = 'bottomright';
23+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\Map\Bridge\Leaflet\Option;
13+
14+
/**
15+
* Options for the rendering of the zoom control.
16+
*
17+
* @see https://leafletjs.com/reference.html#control-zoom
18+
*/
19+
final class ZoomControlOptions
20+
{
21+
public function __construct(
22+
private readonly ControlPosition $position = ControlPosition::TOP_LEFT,
23+
private readonly string $zoomInText = '<span aria-hidden="true">+</span>',
24+
private readonly string $zoomInTitle = 'Zoom in',
25+
private readonly string $zoomOutText = '<span aria-hidden="true">&#x2212;</span>',
26+
private readonly string $zoomOutTitle = 'Zoom out',
27+
) {
28+
}
29+
30+
/**
31+
* @internal
32+
*/
33+
public static function fromArray(array $array): self
34+
{
35+
if (isset($array['position'])) {
36+
$array['position'] = ControlPosition::from($array['position']);
37+
}
38+
39+
return new self(...$array);
40+
}
41+
42+
/**
43+
* @internal
44+
*/
45+
public function toArray(): array
46+
{
47+
return [
48+
'position' => $this->position->value,
49+
'zoomInText' => $this->zoomInText,
50+
'zoomInTitle' => $this->zoomInTitle,
51+
'zoomOutText' => $this->zoomOutText,
52+
'zoomOutTitle' => $this->zoomOutTitle,
53+
];
54+
}
55+
}

0 commit comments

Comments
 (0)