diff --git a/images/marker-gold.png b/images/marker-gold.png deleted file mode 100644 index 82dd7c4..0000000 Binary files a/images/marker-gold.png and /dev/null differ diff --git a/images/marker-green.png b/images/marker-green.png deleted file mode 100644 index 653fbf4..0000000 Binary files a/images/marker-green.png and /dev/null differ diff --git a/images/marker-red.png b/images/marker-red.png deleted file mode 100644 index a20eff5..0000000 Binary files a/images/marker-red.png and /dev/null differ diff --git a/images/marker-white.png b/images/marker-white.png deleted file mode 100644 index 6e70481..0000000 Binary files a/images/marker-white.png and /dev/null differ diff --git a/js/config.js b/js/config.js index e285384..ecb69f9 100644 --- a/js/config.js +++ b/js/config.js @@ -293,4 +293,74 @@ export default class uConfig { this.notify('showLatest'); } } + + /** + * @return {string} + */ + get colorNormal() { + return this._colorNormal; + } + + /** + * @param {string} value + */ + set colorNormal(value) { + this._colorNormal = value; + } + + /** + * @return {string} + */ + get colorStart() { + return this._colorStart; + } + + /** + * @param {string} value + */ + set colorStart(value) { + this._colorStart = value; + } + + /** + * @return {string} + */ + get colorStop() { + return this._colorStop; + } + + /** + * @param {string} value + */ + set colorStop(value) { + this._colorStop = value; + } + + /** + * @return {string} + */ + get colorExtra() { + return this._colorExtra; + } + + /** + * @param {string} value + */ + set colorExtra(value) { + this._colorExtra = value; + } + + /** + * @return {string} + */ + get colorHilite() { + return this._colorHilite; + } + + /** + * @param {string} value + */ + set colorHilite(value) { + this._colorHilite = value; + } } diff --git a/js/constants.js b/js/constants.js index 49b9708..ef1407b 100644 --- a/js/constants.js +++ b/js/constants.js @@ -126,6 +126,12 @@ class uConstants { this.config.unit_km = 'nm'; } this.config.showLatest = false; + // marker colors + this.config.colorNormal = '#fff'; + this.config.colorStart = '#55b500'; + this.config.colorStop = '#ff6a00'; + this.config.colorExtra = '#ccc'; + this.config.colorHilite = '#feff6a'; } } } diff --git a/js/mapapi/api_gmaps.js b/js/mapapi/api_gmaps.js index c96abed..7f9fef9 100644 --- a/js/mapapi/api_gmaps.js +++ b/js/mapapi/api_gmaps.js @@ -173,6 +173,19 @@ function clearMap() { popups.length = 0; } +/** + * @param {string} fill Fill color + * @param {boolean} isLarge Is large icon + * @param {boolean} isExtra Is styled with extra mark + * @return {google.maps.Icon} + */ +function getMarkerIcon(fill, isLarge, isExtra) { + return { + anchor: new google.maps.Point(15, 35), + url: uUI.getSvgSrc(fill, isLarge, isExtra) + }; +} + /** * Set marker * @param {uTrack} track @@ -188,17 +201,14 @@ function setMarker(id, track) { title: (new Date(position.timestamp * 1000)).toLocaleString(), map: map }); - if (config.showLatest) { - marker.setIcon('images/marker-red.png'); + const isExtra = position.hasComment() || position.hasImage(); + let icon = getMarkerIcon(isExtra ? config.colorExtra : config.colorNormal, false, isExtra); + if (id === posLen - 1) { + icon = getMarkerIcon(config.colorStop, true, isExtra); } else if (id === 0) { - marker.setIcon('images/marker-green.png'); - } else if (id === posLen - 1) { - marker.setIcon('images/marker-red.png'); - } else if (position.hasComment() || position.hasImage()) { - marker.setIcon('images/marker-gray.png'); - } else { - marker.setIcon('images/marker-white.png'); + icon = getMarkerIcon(config.colorStart, true, isExtra); } + marker.setIcon(icon); // popup const popup = new google.maps.InfoWindow(); @@ -233,7 +243,7 @@ function animateMarker(id) { clearTimeout(timeoutHandle); } const icon = markers[id].getIcon(); - markers[id].setIcon('images/marker-gold.png'); + markers[id].setIcon(getMarkerIcon(config.colorHilite, false, false)); markers[id].setAnimation(google.maps.Animation.BOUNCE); timeoutHandle = setTimeout(() => { markers[id].setIcon(icon); diff --git a/js/mapapi/api_openlayers.js b/js/mapapi/api_openlayers.js index 3c1bcf7..9c9bb46 100644 --- a/js/mapapi/api_openlayers.js +++ b/js/mapapi/api_openlayers.js @@ -160,44 +160,57 @@ function initLayers() { initLayerSwitcher(); } - function initStyles() { olStyles = {}; - const iconRed = new ol.style.Icon({ + const iconStart = new ol.style.Icon({ anchor: [ 0.5, 1 ], - src: 'images/marker-red.png' + src: uUI.getSvgSrc(config.colorStart, true) }); - const iconGreen = new ol.style.Icon({ + const iconStop = new ol.style.Icon({ anchor: [ 0.5, 1 ], - src: 'images/marker-green.png' + src: uUI.getSvgSrc(config.colorStop, true) }); - const iconWhite = new ol.style.Icon({ + const iconStartExtra = new ol.style.Icon({ + anchor: [ 0.5, 1 ], + src: uUI.getSvgSrc(config.colorStart, true, true) + }); + const iconStopExtra = new ol.style.Icon({ + anchor: [ 0.5, 1 ], + src: uUI.getSvgSrc(config.colorStop, true, true) + }); + const iconNormal = new ol.style.Icon({ anchor: [ 0.5, 1 ], opacity: 0.7, - src: 'images/marker-white.png' + src: uUI.getSvgSrc(config.colorNormal, false) }); - const iconGray = new ol.style.Icon({ + const iconExtra = new ol.style.Icon({ anchor: [ 0.5, 1 ], - src: 'images/marker-gray.png' + src: uUI.getSvgSrc(config.colorExtra, false, true) }); - const iconGold = new ol.style.Icon({ + const iconHilite = new ol.style.Icon({ anchor: [ 0.5, 1 ], - src: 'images/marker-gold.png' + src: uUI.getSvgSrc(config.colorHilite, false) }); - olStyles['red'] = new ol.style.Style({ - image: iconRed + olStyles['start'] = new ol.style.Style({ + image: iconStart }); - olStyles['green'] = new ol.style.Style({ - image: iconGreen + olStyles['stop'] = new ol.style.Style({ + image: iconStop }); - olStyles['white'] = new ol.style.Style({ - image: iconWhite + olStyles['startExtra'] = new ol.style.Style({ + image: iconStartExtra }); - olStyles['gray'] = new ol.style.Style({ - image: iconGray + olStyles['stopExtra'] = new ol.style.Style({ + image: iconStopExtra }); - olStyles['gold'] = new ol.style.Style({ - image: iconGold + olStyles['normal'] = new ol.style.Style({ + image: iconNormal + }); + olStyles['extra'] = new ol.style.Style({ + image: iconExtra + }); + olStyles['hilite'] = new ol.style.Style({ + image: iconHilite }); } @@ -411,6 +424,24 @@ function clearMap() { } } +function getMarkerStyle(position, id, posLen) { + let iconStyle = olStyles['normal']; + if (position.hasComment() || position.hasImage()) { + if (id === posLen - 1) { + iconStyle = olStyles['stopExtra']; + } else if (id === 0) { + iconStyle = olStyles['startExtra']; + } else { + iconStyle = olStyles['extra']; + } + } else if (id === posLen - 1) { + iconStyle = olStyles['stop']; + } else if (id === 0) { + iconStyle = olStyles['start']; + } + return iconStyle; +} + /** * Set marker * @param {number} id @@ -424,18 +455,7 @@ function setMarker(id, track) { geometry: new ol.geom.Point(ol.proj.fromLonLat([ position.longitude, position.latitude ])) }); - let iconStyle; - if (config.showLatest) { - iconStyle = olStyles['red']; - } else if (id === 0) { - iconStyle = olStyles['green']; - } else if (id === posLen - 1) { - iconStyle = olStyles['red']; - } else if (position.hasComment() || position.hasImage()) { - iconStyle = olStyles['gray']; - } else { - iconStyle = olStyles['white']; - } + const iconStyle = getMarkerStyle(position, id, posLen); marker.setStyle(iconStyle); marker.setId(id); layerMarkers.getSource().addFeature(marker); @@ -448,7 +468,7 @@ function setMarker(id, track) { function animateMarker(id) { const marker = layerMarkers.getSource().getFeatureById(id); const initStyle = marker.getStyle(); - const iconStyle = olStyles['gold']; + const iconStyle = olStyles['hilite']; marker.setStyle(iconStyle); setTimeout(() => marker.setStyle(initStyle), 2000); } diff --git a/js/ui.js b/js/ui.js index d53742b..3ae4c83 100644 --- a/js/ui.js +++ b/js/ui.js @@ -515,4 +515,45 @@ export default class uUI { static toggleLatest() { config.showLatest = !config.showLatest; } + + /** + * Get SVG marker path + * @param {boolean} isLarge Large marker with hole if true + * @return {string} + */ + static getMarkerPath(isLarge) { + const markerHole = 'M15,34.911c0,0,0.359-3.922,1.807-8.588c0.414-1.337,1.011-2.587,2.495-4.159' + + 'c1.152-1.223,3.073-2.393,3.909-4.447c1.681-6.306-3.676-9.258-8.211-9.258c-4.536,0-9.893,2.952-8.211,9.258' + + 'c0.836,2.055,2.756,3.225,3.91,4.447c1.484,1.572,2.08,2.822,2.495,4.159C14.64,30.989,15,34.911,15,34.911z M18,15.922' + + 'c0,1.705-1.342,3.087-2.999,3.087c-1.657,0-3-1.382-3-3.087c0-1.704,1.343-3.086,3-3.086C16.658,12.836,18,14.218,18,15.922z'; + const marker = 'M14.999,34.911c0,0,0.232-1.275,1.162-4.848c0.268-1.023,0.652-1.98,1.605-3.184' + + 'c0.742-0.937,1.975-1.832,2.514-3.404c1.082-4.828-2.363-7.088-5.281-7.088c-2.915,0-6.361,2.26-5.278,7.088' + + 'c0.538,1.572,1.771,2.468,2.514,3.404c0.953,1.203,1.337,2.16,1.604,3.184C14.77,33.635,14.999,34.911,14.999,34.911z'; + return isLarge ? markerHole : marker; + } + + /** + * Get marker extra mark + * @param {boolean} isLarge + * @return {string} + */ + static getMarkerExtra(isLarge) { + const offset1 = isLarge ? 'M26.074,13.517' : 'M23.328,20.715'; + const offset2 = isLarge ? 'M28.232,10.942' : 'M25.486,18.141'; + return ` + `; + } + + /** + * Get inline SVG source + * @param {string} fill + * @param {boolean=} isLarge + * @param {boolean=} isExtra + * @return {string} + */ + static getSvgSrc(fill, isLarge, isExtra) { + const svg = ` + ${isExtra ? uUI.getMarkerExtra(isLarge) : ''}`; + return `data:image/svg+xml,${encodeURIComponent(svg)}`; + } }