Add custom marker icon images
This commit is contained in:
@@ -12,5 +12,7 @@ trim_trailing_whitespace = true
|
|||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
[*.yml]
|
[*.yml]
|
||||||
indent_style = space
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.js]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -14,6 +14,8 @@ npm-debug.log*
|
|||||||
.eslintcache
|
.eslintcache
|
||||||
.node_repl_history
|
.node_repl_history
|
||||||
|
|
||||||
|
*.js.LICENSE
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
ehthumbs.db
|
ehthumbs.db
|
||||||
|
|||||||
53
README.md
53
README.md
@@ -100,6 +100,40 @@ Open a url when a marker is clicked
|
|||||||
])
|
])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Show a custom marker icon. The URL to the icon image can be absolute or relative.
|
||||||
|
```php
|
||||||
|
@map([
|
||||||
|
'lat' => '48.134664',
|
||||||
|
'lng' => '11.555220',
|
||||||
|
'zoom' => '6',
|
||||||
|
'markers' => [[
|
||||||
|
'title' => 'Go NoWare',
|
||||||
|
'lat' => '48.134664',
|
||||||
|
'lng' => '11.555220',
|
||||||
|
'url' => 'https://gonoware.com',
|
||||||
|
'icon' => 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png',
|
||||||
|
]],
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally you may also specify the icon image size and anchor in pixels. The icon will be aligned so that the anchor point is at the marker's geographical location.
|
||||||
|
```php
|
||||||
|
@map([
|
||||||
|
'lat' => '48.134664',
|
||||||
|
'lng' => '11.555220',
|
||||||
|
'zoom' => '6',
|
||||||
|
'markers' => [[
|
||||||
|
'title' => 'Go NoWare',
|
||||||
|
'lat' => '48.134664',
|
||||||
|
'lng' => '11.555220',
|
||||||
|
'url' => 'https://gonoware.com',
|
||||||
|
'icon' => 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png',
|
||||||
|
'iconSize' => [20, 32],
|
||||||
|
'iconAnchor' => [0, 32],
|
||||||
|
]],
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
## Customization
|
## Customization
|
||||||
|
|
||||||
To adjust the height of the map use CSS:
|
To adjust the height of the map use CSS:
|
||||||
@@ -126,6 +160,25 @@ Fade in by default when using Bootstrap 3.3.7 or 4+. To replicate or modify the
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Advanced Customization
|
||||||
|
The event `LaravelMapInitialized` will be dispatched when a map and its markers were initialized. The DOM element, map,
|
||||||
|
markers and service name can be accessed via the event details.
|
||||||
|
```js
|
||||||
|
window.addEventListener('LaravelMapInitialized', function (event) {
|
||||||
|
var element = event.detail.element;
|
||||||
|
var map = event.detail.map;
|
||||||
|
var markers = event.detail.markers;
|
||||||
|
var service = event.detail.service;
|
||||||
|
console.log(element, map, markers, service);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
Please refer to the respective documentation for advanced customization:
|
||||||
|
* [Google Maps](https://developers.google.com/maps/documentation/javascript/tutorial)
|
||||||
|
* [OpenStreetMap](https://leafletjs.com/reference-1.6.0.html)
|
||||||
|
* [Bing Maps](https://leafletjs.com/reference-1.6.0.html)
|
||||||
|
* [MapQuest](https://leafletjs.com/reference-1.6.0.html)
|
||||||
|
* [Yandex Maps](https://tech.yandex.com/maps/jsapi/)
|
||||||
|
* [MapKit (beta)](https://developer.apple.com/documentation/mapkitjs)
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -9,9 +9,13 @@
|
|||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^6.0.3",
|
||||||
"laravel-mix": "^2.1.14",
|
"laravel-mix": "^5.0.1",
|
||||||
"leaflet-bing-layer": "^3.3.0"
|
"leaflet-bing-layer": "^3.3.1",
|
||||||
|
"resolve-url-loader": "^3.1.0",
|
||||||
|
"sass": "^1.24.2",
|
||||||
|
"sass-loader": "^8.0.0",
|
||||||
|
"vue-template-compiler": "^2.6.11"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 1 version",
|
"last 1 version",
|
||||||
|
|||||||
3
public/js/index.js
vendored
3
public/js/index.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"/js/index.js": "/js/index.js?id=fdadfceebf455b33ea99",
|
"/js/index.js": "/js/index.js?id=d9b7d4fc70fe1bbcdb82",
|
||||||
"/css/index.css": "/css/index.css?id=81569dd7736e102f4342"
|
"/css/index.css": "/css/index.css?id=81569dd7736e102f4342"
|
||||||
}
|
}
|
||||||
|
|||||||
29
resources/js/index.js
vendored
29
resources/js/index.js
vendored
@@ -7,6 +7,7 @@ import mapkit from './services/mapkit';
|
|||||||
|
|
||||||
import parser from './utils/parser';
|
import parser from './utils/parser';
|
||||||
import {isDefined, logError} from './utils/helper';
|
import {isDefined, logError} from './utils/helper';
|
||||||
|
import './utils/customEventPolyfill';
|
||||||
|
|
||||||
const createMap = (element, createMap, createMarker) => {
|
const createMap = (element, createMap, createMarker) => {
|
||||||
if (!isDefined(element)) {
|
if (!isDefined(element)) {
|
||||||
@@ -24,9 +25,12 @@ const createMap = (element, createMap, createMarker) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapData.markers.forEach(markerData => {
|
const markers = mapData.markers.map(markerData => createMarker(map, markerData));
|
||||||
createMarker(map, markerData);
|
|
||||||
})
|
return {
|
||||||
|
map,
|
||||||
|
markers,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const createMapService = service => {
|
const createMapService = service => {
|
||||||
@@ -36,8 +40,23 @@ const createMapService = service => {
|
|||||||
service.createMarker,
|
service.createMarker,
|
||||||
);
|
);
|
||||||
const selector = `[data-map-${service.NAME}]`;
|
const selector = `[data-map-${service.NAME}]`;
|
||||||
const elements = document.querySelectorAll(selector) || [];
|
const elements = Array.prototype.slice.call(document.querySelectorAll(selector) || []);
|
||||||
elements.forEach(createMapService);
|
elements.forEach(element => {
|
||||||
|
const data = createMapService(element);
|
||||||
|
dispatchEvent(service.NAME, element, data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const dispatchEvent = (serviceName, element, data) => {
|
||||||
|
const event = new CustomEvent('LaravelMapInitialized', {
|
||||||
|
detail: {
|
||||||
|
element: element,
|
||||||
|
map: data.map,
|
||||||
|
markers: data.markers || [],
|
||||||
|
service: serviceName,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
window.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.onGoogleMapsReady = () => createMapService(google);
|
window.onGoogleMapsReady = () => createMapService(google);
|
||||||
|
|||||||
20
resources/js/services/bing.js
vendored
20
resources/js/services/bing.js
vendored
@@ -1,5 +1,6 @@
|
|||||||
import {fadeElementIn, isDefined, logError, openUrl} from '../utils/helper';
|
import {fadeElementIn, isDefined, logError, openUrl} from '../utils/helper';
|
||||||
import 'leaflet-bing-layer';
|
import 'leaflet-bing-layer';
|
||||||
|
import {createMarker} from '../utils/leaflet';
|
||||||
|
|
||||||
// TODO: locales/culture
|
// TODO: locales/culture
|
||||||
|
|
||||||
@@ -28,22 +29,5 @@ export default {
|
|||||||
|
|
||||||
return map;
|
return map;
|
||||||
},
|
},
|
||||||
createMarker(map, markerData) {
|
createMarker,
|
||||||
const {title, lat, lng, url} = markerData;
|
|
||||||
|
|
||||||
const marker = window.L.marker([lat, lng], {
|
|
||||||
title,
|
|
||||||
keyboard: false,
|
|
||||||
draggable: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (url) {
|
|
||||||
marker.on('click', event => {
|
|
||||||
event.originalEvent.preventDefault();
|
|
||||||
openUrl(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
marker.addTo(map);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|||||||
25
resources/js/services/google.js
vendored
25
resources/js/services/google.js
vendored
@@ -27,22 +27,35 @@ export default {
|
|||||||
return map;
|
return map;
|
||||||
},
|
},
|
||||||
createMarker(map, markerData) {
|
createMarker(map, markerData) {
|
||||||
const {title, lat, lng, url} = markerData;
|
const {title, lat, lng, url, icon, iconSize, iconAnchor} = markerData;
|
||||||
|
|
||||||
const marker = new window.google.maps.Marker({
|
const markerOptions = {
|
||||||
position: new window.google.maps.LatLng(lat, lng),
|
position: new window.google.maps.LatLng(lat, lng),
|
||||||
map,
|
map,
|
||||||
title,
|
title,
|
||||||
draggable: false,
|
draggable: false,
|
||||||
// icon: {
|
};
|
||||||
// url: markerConfig.mapMarkerImg,
|
|
||||||
// },
|
if (icon) {
|
||||||
});
|
markerOptions.icon = {
|
||||||
|
url: icon,
|
||||||
|
};
|
||||||
|
if (iconSize) {
|
||||||
|
markerOptions.icon.size = new window.google.maps.Size(...iconSize);
|
||||||
|
}
|
||||||
|
if (iconAnchor) {
|
||||||
|
markerOptions.icon.anchor = new window.google.maps.Point(...iconAnchor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const marker = new window.google.maps.Marker(markerOptions);
|
||||||
|
|
||||||
if (url) {
|
if (url) {
|
||||||
marker.addListener('click', () => {
|
marker.addListener('click', () => {
|
||||||
openUrl(url);
|
openUrl(url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return marker;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
30
resources/js/services/mapkit.js
vendored
30
resources/js/services/mapkit.js
vendored
@@ -41,13 +41,35 @@ export default {
|
|||||||
return map;
|
return map;
|
||||||
},
|
},
|
||||||
createMarker(map, markerData) {
|
createMarker(map, markerData) {
|
||||||
const {title, lat, lng, url} = markerData;
|
const {title, lat, lng, url, icon} = markerData;
|
||||||
|
|
||||||
const coordinate = new window.mapkit.Coordinate(lat, lng);
|
const coordinate = new window.mapkit.Coordinate(lat, lng);
|
||||||
const marker = new window.mapkit.MarkerAnnotation(coordinate, {
|
|
||||||
title,
|
const markerAnnotationOptions = {title};
|
||||||
});
|
|
||||||
|
if (url) {
|
||||||
|
markerAnnotationOptions.callout = {
|
||||||
|
calloutRightAccessoryForAnnotation: function() {
|
||||||
|
const accessoryViewRight = document.createElement('a');
|
||||||
|
accessoryViewRight.className = 'right-accessory-view';
|
||||||
|
accessoryViewRight.href = url;
|
||||||
|
accessoryViewRight.target = '_blank';
|
||||||
|
accessoryViewRight.appendChild(document.createTextNode('ⓘ'));
|
||||||
|
return accessoryViewRight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
markerAnnotationOptions.glyphImage = {
|
||||||
|
1: icon,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const marker = new window.mapkit.MarkerAnnotation(coordinate, markerAnnotationOptions);
|
||||||
|
|
||||||
map.showItems([marker]); // TODO: map auto resize bugging if multiple markers
|
map.showItems([marker]); // TODO: map auto resize bugging if multiple markers
|
||||||
|
|
||||||
|
return marker;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
20
resources/js/services/mapquest.js
vendored
20
resources/js/services/mapquest.js
vendored
@@ -1,4 +1,5 @@
|
|||||||
import {fadeElementIn, isDefined, logError, openUrl} from '../utils/helper';
|
import {fadeElementIn, isDefined, logError, openUrl} from '../utils/helper';
|
||||||
|
import {createMarker} from '../utils/leaflet';
|
||||||
|
|
||||||
// TODO maybe add this https://github.com/elmarquis/Leaflet.GestureHandling/
|
// TODO maybe add this https://github.com/elmarquis/Leaflet.GestureHandling/
|
||||||
|
|
||||||
@@ -34,22 +35,5 @@ export default {
|
|||||||
|
|
||||||
return map;
|
return map;
|
||||||
},
|
},
|
||||||
createMarker(map, markerData) {
|
createMarker,
|
||||||
const {title, lat, lng, url} = markerData;
|
|
||||||
|
|
||||||
const marker = window.L.marker([lat, lng], {
|
|
||||||
title,
|
|
||||||
keyboard: false,
|
|
||||||
draggable: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (url) {
|
|
||||||
marker.on('click', event => {
|
|
||||||
event.originalEvent.preventDefault();
|
|
||||||
openUrl(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
marker.addTo(map);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|||||||
20
resources/js/services/osm.js
vendored
20
resources/js/services/osm.js
vendored
@@ -1,4 +1,5 @@
|
|||||||
import {fadeElementIn, isDefined, logError, openUrl} from '../utils/helper';
|
import {fadeElementIn, isDefined, logError, openUrl} from '../utils/helper';
|
||||||
|
import {createMarker} from '../utils/leaflet';
|
||||||
|
|
||||||
// TODO maybe add this https://github.com/elmarquis/Leaflet.GestureHandling/
|
// TODO maybe add this https://github.com/elmarquis/Leaflet.GestureHandling/
|
||||||
|
|
||||||
@@ -31,22 +32,5 @@ export default {
|
|||||||
|
|
||||||
return map;
|
return map;
|
||||||
},
|
},
|
||||||
createMarker(map, markerData) {
|
createMarker,
|
||||||
const {title, lat, lng, url} = markerData;
|
|
||||||
|
|
||||||
const marker = window.L.marker([lat, lng], {
|
|
||||||
title,
|
|
||||||
keyboard: false,
|
|
||||||
draggable: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (url) {
|
|
||||||
marker.on('click', event => {
|
|
||||||
event.originalEvent.preventDefault();
|
|
||||||
openUrl(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
marker.addTo(map);
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|||||||
23
resources/js/services/yandex.js
vendored
23
resources/js/services/yandex.js
vendored
@@ -21,11 +21,26 @@ export default {
|
|||||||
return map;
|
return map;
|
||||||
},
|
},
|
||||||
createMarker(map, markerData) {
|
createMarker(map, markerData) {
|
||||||
const {title, lat, lng, url} = markerData;
|
const {title, lat, lng, url, icon, iconSize, iconAnchor} = markerData;
|
||||||
|
|
||||||
const marker = new window.ymaps.Placemark([lat, lng], {
|
const placemarkProperties = {
|
||||||
hintContent: title,
|
hintContent: title,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const placemarkOptions = {};
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
placemarkOptions.iconLayout = 'default#imageWithContent';
|
||||||
|
placemarkOptions.iconImageHref = icon;
|
||||||
|
if (iconSize) {
|
||||||
|
placemarkOptions.iconImageSize = iconSize;
|
||||||
|
}
|
||||||
|
if (iconAnchor) {
|
||||||
|
placemarkOptions.iconImageOffset = iconAnchor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const marker = new window.ymaps.Placemark([lat, lng], placemarkProperties, placemarkOptions);
|
||||||
|
|
||||||
// if (url) {
|
// if (url) {
|
||||||
// marker.addListener('click', () => {
|
// marker.addListener('click', () => {
|
||||||
@@ -34,5 +49,7 @@ export default {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
map.geoObjects.add(marker);
|
map.geoObjects.add(marker);
|
||||||
|
|
||||||
|
return marker;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
15
resources/js/utils/customEventPolyfill.js
vendored
Normal file
15
resources/js/utils/customEventPolyfill.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
(function () {
|
||||||
|
if (window.CustomEvent) return false;
|
||||||
|
function CustomEvent(event, params) {
|
||||||
|
params = params || {
|
||||||
|
bubbles: false, cancelable: false, detail: undefined
|
||||||
|
};
|
||||||
|
var evt = document.createEvent( 'CustomEvent' );
|
||||||
|
evt.initCustomEvent(
|
||||||
|
event, params.bubbles, params.cancelable, params.detail
|
||||||
|
);
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
CustomEvent.prototype = window.Event.prototype;
|
||||||
|
window.CustomEvent = CustomEvent;
|
||||||
|
})();
|
||||||
37
resources/js/utils/leaflet.js
vendored
Normal file
37
resources/js/utils/leaflet.js
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import {openUrl} from './helper';
|
||||||
|
|
||||||
|
export function createMarker(map, markerData) {
|
||||||
|
const {title, lat, lng, url, icon, iconSize, iconAnchor} = markerData;
|
||||||
|
|
||||||
|
const markerOptions = {
|
||||||
|
title,
|
||||||
|
keyboard: false,
|
||||||
|
draggable: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
const iconOptions = {
|
||||||
|
iconUrl: icon,
|
||||||
|
};
|
||||||
|
if (iconSize) {
|
||||||
|
iconOptions.iconSize = iconSize;
|
||||||
|
}
|
||||||
|
if (iconAnchor) {
|
||||||
|
iconOptions.iconAnchor = iconAnchor;
|
||||||
|
}
|
||||||
|
markerOptions.icon = window.L.icon(iconOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
const marker = window.L.marker([lat, lng], markerOptions);
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
marker.on('click', event => {
|
||||||
|
event.originalEvent.preventDefault();
|
||||||
|
openUrl(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
marker.addTo(map);
|
||||||
|
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
5
resources/js/utils/parser.js
vendored
5
resources/js/utils/parser.js
vendored
@@ -23,13 +23,16 @@ const parseMarkers = element => {
|
|||||||
return markers.map(marker => {
|
return markers.map(marker => {
|
||||||
const lat = parseFloat(marker.lat);
|
const lat = parseFloat(marker.lat);
|
||||||
const lng = parseFloat(marker.lng);
|
const lng = parseFloat(marker.lng);
|
||||||
const {title, url} = marker;
|
const {title, url, icon, iconSize, iconAnchor} = marker;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title,
|
title,
|
||||||
lat,
|
lat,
|
||||||
lng,
|
lng,
|
||||||
url,
|
url,
|
||||||
|
icon,
|
||||||
|
iconSize,
|
||||||
|
iconAnchor,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
2
webpack.mix.js
vendored
2
webpack.mix.js
vendored
@@ -3,7 +3,7 @@ const mix = require('laravel-mix');
|
|||||||
mix.setPublicPath('public')
|
mix.setPublicPath('public')
|
||||||
.setResourceRoot('../')
|
.setResourceRoot('../')
|
||||||
.js('resources/js/index.js', 'js')
|
.js('resources/js/index.js', 'js')
|
||||||
.sass('resources/sass/index.scss', 'css', {precision: 8})
|
.sass('resources/sass/index.scss', 'css')
|
||||||
.copy('resources/img/*.png', 'public/img')
|
.copy('resources/img/*.png', 'public/img')
|
||||||
.version('img');
|
.version('img');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user