diff --git a/HISTORY.md b/HISTORY.md index c95704c..efcea12 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +v3.7.0 +=================== +## Enhancement: +* Extend px-map-marker-group component to support numbered marker + v3.6.0 =================== ## New features: diff --git a/css/px-map-styles.html b/css/px-map-styles.html index 5cc2558..54b2283 100644 --- a/css/px-map-styles.html +++ b/css/px-map-styles.html @@ -17,7 +17,7 @@ \ No newline at end of file diff --git a/demo/px-map-marker-group-demo.html b/demo/px-map-marker-group-demo.html index a06eb67..84694b2 100644 --- a/demo/px-map-marker-group-demo.html +++ b/demo/px-map-marker-group-demo.html @@ -186,9 +186,27 @@ "properties": { "title": "Cabrillo National Monument", "marker-icon": { - "icon-base": "static-icon", - "icon-type": "warning", - + "icon-base": "custom-icon", + "icon-type": "px-nav:unconfirmed", + "icon-strokeColor": "blue", + "icon-fillColor": "white", + "icon-content": "1", + "icon-options": { + "strokeColor": "blue", + "fillColor": "white", + } + }, + "marker-popup": { + "popup-base": "data-popup", + "popup-title": "Cabrillo National Monument", + "popup-opened": "true", + "popup-maxWidth": "600", + "popup-minWidth": "500", + "popup-data": { + "LAT": "32.67445793", + "LNG": "-117.24042573", + "STATE": "warning" + } } }, "id": "10001" @@ -205,9 +223,15 @@ "properties": { "title": "Pearl St & Draper Av", "marker-icon": { - "icon-base": "static-icon", - "icon-type": "info", - + "icon-base": "custom-icon", + "icon-type": "px-nav:unconfirmed", + "icon-strokeColor": "blue", + "icon-fillColor": "white", + "icon-content": "2", + "icon-options": { + "strokeColor": "blue", + "fillColor": "white", + } } }, "id": "10003" @@ -566,9 +590,15 @@ "properties": { "title": "Nobel Dr & Lebon Dr", "marker-icon": { - "icon-base": "static-icon", - "icon-type": "unknown", - + "icon-base": "custom-icon", + "icon-type": "px-nav:unconfirmed", + "icon-strokeColor": "blue", + "icon-fillColor": "white", + "icon-content": "px-nav:home", + "icon-options": { + "strokeColor": "blue", + "fillColor": "white", + } } }, "id": "10034" diff --git a/px-map-behavior-icon.es6.js b/px-map-behavior-icon.es6.js index cdbda75..e97e5e6 100644 --- a/px-map-behavior-icon.es6.js +++ b/px-map-behavior-icon.es6.js @@ -23,21 +23,21 @@ ****************************************************************************/ /* Ensures the klass namespace is created */ - window.PxMap = (window.PxMap || {}); + window.PxMap = window.PxMap || {}; /** * * @class PxMap.StaticIcon */ class StaticIcon { - constructor(settings={}) { + constructor(settings = {}) { this.icon = this.createIcon(settings); return this.icon; } - createIcon(settings={}) { + createIcon(settings = {}) { // Extract `type` from settings with defaults - let { type='info', styleScope, color } = settings; + let { type = 'info', styleScope, color } = settings; const className = this._generateStaticIconClasses(type, styleScope); @@ -57,9 +57,9 @@ `; - const iconSize = L.point(23,31); + const iconSize = L.point(23, 31); const iconAnchor = L.point(7.6, 31); - const popupAnchor = L.point(1,-31); + const popupAnchor = L.point(1, -31); // Define the `divIcon` options const options = { @@ -74,7 +74,11 @@ } _generateStaticIconClasses(type, styleScope) { - const classes = ['map-icon', 'map-icon-static', 'map-icon-static--with-badge']; + const classes = [ + 'map-icon', + 'map-icon-static', + 'map-icon-static--with-badge' + ]; if (type && type.length) { classes.push(`map-icon-static--${type}`); } @@ -83,7 +87,7 @@ } return classes.join(' '); } - }; + } /* Bind StaticIcon klass */ PxMap.StaticIcon = StaticIcon; @@ -92,13 +96,21 @@ * @class PxMap.SymbolIcon */ class SymbolIcon { - constructor(settings={}) { + constructor(settings = {}) { this.icon = this.createIcon(settings); return this.icon; } - createIcon(settings={}) { - let { type='info', icon='px-nav:favorite', styleScope, stroke='currentColor', fill='none', strokeWidth='2px', color } = settings; + createIcon(settings = {}) { + let { + type = 'info', + icon = 'px-nav:favorite', + styleScope, + stroke = 'currentColor', + fill = 'none', + strokeWidth = '2px', + color + } = settings; const className = this._generateSymbolIconClasses(type, styleScope); let customStyleBackground = ''; @@ -111,20 +123,23 @@ // Icon/Symbol options const html = ` -
- -
- -
-
- - -
+
+ +
+ + +
+
+ + +
`; - const iconSize = L.point(40,56); + const iconSize = L.point(40, 56); const iconAnchor = L.point(19.6, 57); - const popupAnchor = L.point(1,-58); + const popupAnchor = L.point(1, -58); // Define the `divIcon` options const options = { @@ -139,7 +154,11 @@ } _generateSymbolIconClasses(type, styleScope) { - const classes = ['map-icon', 'map-icon-symbol', 'map-icon-symbol--with-badge']; + const classes = [ + 'map-icon', + 'map-icon-symbol', + 'map-icon-symbol--with-badge' + ]; if (type && type.length) { classes.push(`map-icon-symbol--${type}`); } @@ -148,7 +167,7 @@ } return classes.join(' '); } - }; + } /* Bind SymbolIcon klass */ PxMap.SymbolIcon = SymbolIcon; @@ -157,29 +176,45 @@ * @class PxMap.ClusterIcon */ class ClusterIcon { - constructor(settings={}) { + constructor(settings = {}) { this.icon = this.createIcon(settings); return this.icon; } - createIcon(settings={}) { + createIcon(settings = {}) { // Extract `count`, `countByType`, `colorsByType` - const { count, countByType, colorsByType, containerSize=50, pathSize=10, borderSize=0, className='', styleScope } = settings; + const { + count, + countByType, + colorsByType, + containerSize = 50, + pathSize = 10, + borderSize = 0, + className = '', + styleScope + } = settings; // The chart size is the container size with the border size subtracted out, // so we can draw and transform our SVG in the right dimensions - const chartSize = (containerSize - (borderSize > 0 ? (borderSize*2)-0.5 : 0)); + const chartSize = + containerSize - (borderSize > 0 ? borderSize * 2 - 0.5 : 0); // The icon size is a point representing the size of the icon's outer container const iconSize = L.point(containerSize, containerSize); // Get the SVG for this icon - const svg = this._generateClusterIconSVG(countByType, colorsByType, chartSize, pathSize); + const svg = this._generateClusterIconSVG( + countByType, + colorsByType, + chartSize, + pathSize + ); // Generate the classes and wrapper HTML - const classes = `map-icon-cluster ${className||''} ${styleScope||''}`; + const classes = `map-icon-cluster ${className || ''} ${styleScope || ''}`; const html = ` -
+
${svg}
${count}
@@ -199,20 +234,24 @@ // Combine the `countByType` and `colorsByType` into one array of objects, // each describing a type with its associated count and color const typeKeys = Object.keys(countByType); - const typeObjs = typeKeys.map(type => ({ type: type, count: countByType[type], color: colorsByType[type] })); + const typeObjs = typeKeys.map(type => ({ + type: type, + count: countByType[type], + color: colorsByType[type] + })); // Sort the types from highest->lowest - typeObjs.sort((a,b) => a.count - b.count); + typeObjs.sort((a, b) => a.count - b.count); // Create two parallel arrays of [types] and [colors] const types = []; const colors = []; let i, len, type, total; - for (i=0, len=typeKeys.length; i` tag's `d` attribute. - const arcPathGeneratorFn = Px.d3.arc().outerRadius(radius).innerRadius(innerRadius); + const arcPathGeneratorFn = Px.d3 + .arc() + .outerRadius(radius) + .innerRadius(innerRadius); // Iterate over a list of `arcData` entries and return a block of paths - const pathListTmpl = (paths) => paths.map(pathTmpl).join(''); + const pathListTmpl = paths => paths.map(pathTmpl).join(''); // For each path, generate a `` tag with the correct attributes - const pathTmpl = (pathData, pathIndex) => ``; + const pathTmpl = (pathData, pathIndex) => + ``; return ` - - - ${pathListTmpl(arcData)} - + + + ${pathListTmpl(arcData)} + `; } - }; + } /* Bind ClusterIcon klass */ PxMap.ClusterIcon = ClusterIcon; + + /** + * + * @class PxMap.CustomIcon + */ + class CustomIcon { + constructor(settings = {}) { + this.icon = this.createIcon(settings); + return this.icon; + } + + createIcon(settings = {}) { + // type defaults to type='px-nav:unconfirmed' + let { + type = 'px-nav:unconfirmed', + styleScope, + strokeColor, + fillColor, + content, + options: { + icon, + strokeColor: iconStrokeColor, + fillColor: iconFillColor + } + } = settings; + + let iconVal = ''; + if (content.indexOf('px-') == -1) { + iconVal = `${content} `; + } else { + iconVal = + ``; + } + + // Custom template + const html = ` +
+ + ${iconVal} +
+ `; + + const className = this._generateCustomIconClasses(type, styleScope); + const iconSize = L.point(32, 32); + const iconAnchor = L.point(16, 32); + const popupAnchor = L.point(0, -32); + + // Define the `divIcon` options + const options = { + className, + html, + iconSize, + iconAnchor, + popupAnchor + }; + return L.divIcon(options); + } + + _generateCustomIconClasses(type, styleScope) { + const classes = ['map-icon', 'map-icon-custom']; + if (type && type.length) { + classes.push(`map-icon-custom--${type}`); + } + if (styleScope) { + classes.push(styleScope); + } + return classes.join(' '); + } + } + /* Bind CustomIcon klass */ + PxMap.CustomIcon = CustomIcon; })(); diff --git a/sass/_map-icon-custom.scss b/sass/_map-icon-custom.scss new file mode 100644 index 0000000..e7f267d --- /dev/null +++ b/sass/_map-icon-custom.scss @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, General Electric + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ICON CONTAINER +// $px-map-icon-unknown-color: var(--internal-px-map-icon-unknown-color, $dv-light-gray); +// $px-map-icon-info-color: var(--internal-px-map-icon-info-color, $primary-blue); +// $px-map-icon-warning-color: var(--internal-px-map-icon-warning-color, $alert-orange); +// $px-map-icon-important-color: var(--internal-px-map-icon-important-color, $alert-red); +// $px-map-icon-border-color: var(--internal-px-map-icon-border-color, $white); + +.map-icon-custom { + @extend %map-icon !optional; + width: 50px; + height: 50px; + display: block; + position: absolute; +} + +// ICON BODY +.map-icon-custom__body { + position: absolute; + top: 0; + left: 0; + width: 22px; + height: 22px; + color: var(--internal-px-map-icon-info-color); + font-size: 12px; + text-align: center; + stroke: var(--px-map-icon-unknown-color); + fill: var(--internal-px-map-icon-info-color); + + &.content-icon { + width:15px; + height:15px; + margin: 3px 0 0 3px; + } +} diff --git a/sass/px-map.scss b/sass/px-map.scss index f43f889..bc0ff1f 100644 --- a/sass/px-map.scss +++ b/sass/px-map.scss @@ -146,6 +146,9 @@ $px-map-marker-locate-icon-accuracy-opacity: var(--px-map-marker-locate-i // MAP ICON: SYMBOL @import "_map-icon-symbol.scss"; +// MAP ICON: CUSTOM +@import "_map-icon-custom.scss"; + // MAP ICON: CLUSTER .map-icon-cluster { @extend %map-icon !optional; @@ -442,7 +445,6 @@ $px-map-marker-locate-icon-accuracy-opacity: var(--px-map-marker-locate-i transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in; } - // Trumps @import "px-clearfix-design/_trumps.clearfix.scss"; @import "px-spacing-responsive-design/_trumps.spacing-responsive.scss";