Skip to content

Commit ec18e13

Browse files
authored
Merge pull request #679 from NASA-AMMOS/jr-657
Adds ShapeImage and ShapeIcon fields to display custom marker icons in the legend
2 parents 8f02f68 + cb63ecc commit ec18e13

File tree

3 files changed

+126
-72
lines changed

3 files changed

+126
-72
lines changed

configure/src/metaconfigs/layer-vector-config.json

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -513,12 +513,19 @@
513513
"type": "colorpicker",
514514
"width": 2
515515
},
516+
{
517+
"field": "value",
518+
"name": "Label",
519+
"description": "A label description for this legend entry.",
520+
"type": "text",
521+
"width": 8
522+
},
516523
{
517524
"field": "shape",
518525
"name": "Shape",
519-
"description": "The symbol for which to us for this legend entry. Discreet and continuous describe scales. These scales are broken into groups by a change in shape value. For instance, 'discreet, discreet, discreet, circle, discreet, discreet' represents a discreet scales of three colors, a circle and then a discreet scale of two colors.",
526+
"description": "The symbol for which to use for this legend entry. Discreet and continuous describe scales. These scales are broken into groups by a change in shape value. For instance, 'discreet, discreet, discreet, circle, discreet, discreet' represents a discreet scales of three colors, a circle and then a discreet scale of two colors.",
520527
"type": "dropdown",
521-
"width": 5,
528+
"width": 4,
522529
"options": [
523530
"circle",
524531
"square",
@@ -529,11 +536,18 @@
529536
]
530537
},
531538
{
532-
"field": "value",
533-
"name": "Label",
534-
"description": "A label description for this legend entry.",
539+
"field": "shapeIcon",
540+
"name": "Shape From Icon",
541+
"description": "Shape but taken from the Material Design Icon (mdi) library. Takes priority over the value in the 'shape' field. See <a target='_blank' href='https://pictogrammers.com/library/mdi/'>https://pictogrammers.com/library/mdi/</a>",
535542
"type": "text",
536-
"width": 3
543+
"width": 4
544+
},
545+
{
546+
"field": "shapeImage",
547+
"name": "Shape From Image",
548+
"description": "A URL to a custom image (jpeg|jpg|gif|png|svg|webp) for which to use for this legend entry. If the path is relative, it will be relative to the mission's directory. This field will override values in the Shape and Shape From Icon fields.",
549+
"type": "text",
550+
"width": 4
537551
}
538552
]
539553
}

configure/src/metaconfigs/layer-vectortile-config.json

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -469,12 +469,19 @@
469469
"type": "colorpicker",
470470
"width": 2
471471
},
472+
{
473+
"field": "value",
474+
"name": "Label",
475+
"description": "A label description for this legend entry.",
476+
"type": "text",
477+
"width": 8
478+
},
472479
{
473480
"field": "shape",
474481
"name": "Shape",
475-
"description": "The symbol for which to us for this legend entry. Discreet and continuous describe scales. These scales are broken into groups by a change in shape value. For instance, 'discreet, discreet, discreet, circle, discreet, discreet' represents a discreet scales of three colors, a circle and then a discreet scale of two colors.",
482+
"description": "The symbol for which to use for this legend entry. Discreet and continuous describe scales. These scales are broken into groups by a change in shape value. For instance, 'discreet, discreet, discreet, circle, discreet, discreet' represents a discreet scales of three colors, a circle and then a discreet scale of two colors.",
476483
"type": "dropdown",
477-
"width": 5,
484+
"width": 4,
478485
"options": [
479486
"circle",
480487
"square",
@@ -485,11 +492,18 @@
485492
]
486493
},
487494
{
488-
"field": "value",
489-
"name": "Label",
490-
"description": "A label description for this legend entry.",
495+
"field": "shapeIcon",
496+
"name": "Shape From Icon",
497+
"description": "Shape but taken from the Material Design Icon (mdi) library. Takes priority over the value in the 'shape' field. See <a target='_blank' href='https://pictogrammers.com/library/mdi/'>https://pictogrammers.com/library/mdi/</a>",
491498
"type": "text",
492-
"width": 3
499+
"width": 4
500+
},
501+
{
502+
"field": "shapeImage",
503+
"name": "Shape From Image",
504+
"description": "A URL to a custom image (jpeg|jpg|gif|png|svg|webp) for which to use for this legend entry. If the path is relative, it will be relative to the mission's directory. This field will override values in the Shape and Shape From Icon fields.",
505+
"type": "text",
506+
"width": 4
493507
}
494508
]
495509
}

src/essence/Tools/Legend/LegendTool.js

Lines changed: 86 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -217,82 +217,108 @@ function drawLegends(tools, _legend, layerUUID, display_name, opacity) {
217217
let lastContinues = []
218218
let lastShape = ''
219219
for (let d in _legend) {
220-
var shape = _legend[d].shape
221-
if (
222-
shape == 'circle' ||
223-
shape == 'square' ||
224-
shape == 'rect' ||
225-
shape == 'triangle'
226-
) {
220+
var shape = _legend[d].shapeImage && _legend[d].shapeImage.trim()
221+
? _legend[d].shapeImage : _legend[d].shapeIcon && _legend[d].shapeIcon.trim()
222+
? _legend[d].shapeIcon : _legend[d].shape
223+
if (shape == 'continuous' || shape == 'discreet') {
224+
if (lastShape != shape) {
225+
if (lastContinues.length > 0) {
226+
pushScale(lastContinues)
227+
lastContinues = []
228+
}
229+
}
230+
lastContinues.push({
231+
color: _legend[d].color,
232+
shape: shape,
233+
value: _legend[d].value,
234+
})
235+
lastShape = shape
236+
} else {
237+
227238
// finalize discreet and continuous
228239
if (lastContinues.length > 0) {
229240
pushScale(lastContinues)
230241
lastContinues = []
231242
}
232-
233243
var r = c
234244
.append('div')
235245
.attr('class', 'row')
236246
.style('display', 'flex')
237247
.style('margin', '0px 0px 8px 9px')
238248

239-
switch (shape) {
240-
case 'circle':
241-
r.append('div')
242-
.attr('class', layerUUID + '_legendshape')
243-
.style('width', '18px')
244-
.style('height', '18px')
245-
.style('background', _legend[d].color)
246-
.style('opacity', opacity)
247-
.style('border', `1px solid ${_legend[d].strokecolor}`)
248-
.style('border-radius', '50%')
249-
break
250-
case 'square':
251-
r.append('div')
252-
.attr('class', layerUUID + '_legendshape')
253-
.style('width', '18px')
254-
.style('height', '18px')
255-
.style('background', _legend[d].color)
256-
.style('opacity', opacity)
257-
.style('border', `1px solid ${_legend[d].strokecolor}`)
258-
break
259-
case 'rect':
260-
r.append('div')
261-
.attr('class', layerUUID + '_legendshape')
262-
.style('width', '18px')
263-
.style('height', '8px')
264-
.style('margin', '5px 0px 5px 0px')
265-
.style('background', _legend[d].color)
249+
if (
250+
shape == 'circle' ||
251+
shape == 'square' ||
252+
shape == 'rect'
253+
) {
254+
switch (shape) {
255+
case 'circle':
256+
r.append('div')
257+
.attr('class', layerUUID + '_legendshape')
258+
.style('width', '18px')
259+
.style('height', '18px')
260+
.style('background', _legend[d].color)
261+
.style('opacity', opacity)
262+
.style('border', `1px solid ${_legend[d].strokecolor}`)
263+
.style('border-radius', '50%')
264+
break
265+
case 'square':
266+
r.append('div')
267+
.attr('class', layerUUID + '_legendshape')
268+
.style('width', '18px')
269+
.style('height', '18px')
270+
.style('background', _legend[d].color)
271+
.style('opacity', opacity)
272+
.style('border', `1px solid ${_legend[d].strokecolor}`)
273+
break
274+
case 'rect':
275+
r.append('div')
276+
.attr('class', layerUUID + '_legendshape')
277+
.style('width', '18px')
278+
.style('height', '8px')
279+
.style('margin', '5px 0px 5px 0px')
280+
.style('background', _legend[d].color)
281+
.style('opacity', opacity)
282+
.style('border', `1px solid ${_legend[d].strokecolor}`)
283+
break
284+
default:
285+
}
286+
} else if (String(shape).toLowerCase().match(/\.(jpeg|jpg|gif|png|svg|webp)$/) != null) {
287+
// Image markers
288+
r.append('div')
289+
.attr('class', layerUUID + '_legendcustom')
290+
.style('width', '24px')
291+
.style('height', '24px')
292+
.style('background', _legend[d].color)
293+
.style('opacity', opacity)
294+
.style('border', `1px solid ${_legend[d].strokecolor}`)
295+
.style('background-image', `url(${shape.startsWith("http")
296+
? shape : L_.missionPath + shape})`)
297+
.style('background-size', 'contain')
298+
.style('background-repeat', 'no-repeat')
299+
} else { // try using shape from Material Design Icon (mdi) library
300+
r.append('div')
301+
.attr('class', layerUUID + '_legendicon')
302+
.style('width', '18px')
303+
.style('height', '18px')
304+
.append('i')
305+
.attr('class', 'mdi mdi-18px mdi-' + shape)
306+
.style('color', _legend[d].color)
266307
.style('opacity', opacity)
267308
.style('border', `1px solid ${_legend[d].strokecolor}`)
268-
break
269-
default:
270309
}
271310

272311
r.append('div')
273-
.style('margin-left', '5px')
274-
.style('height', '100%')
275-
.style('line-height', '19px')
276-
.style('font-size', '14px')
277-
.style('overflow', 'hidden')
278-
.style('white-space', 'nowrap')
279-
.style('max-width', '270px')
280-
.style('text-overflow', 'ellipsis')
281-
.attr('title', _legend[d].value)
282-
.text(_legend[d].value)
283-
} else if (shape == 'continuous' || shape == 'discreet') {
284-
if (lastShape != shape) {
285-
if (lastContinues.length > 0) {
286-
pushScale(lastContinues)
287-
lastContinues = []
288-
}
289-
}
290-
lastContinues.push({
291-
color: _legend[d].color,
292-
shape: shape,
293-
value: _legend[d].value,
294-
})
295-
lastShape = shape
312+
.style('margin-left', '5px')
313+
.style('height', '100%')
314+
.style('line-height', '19px')
315+
.style('font-size', '14px')
316+
.style('overflow', 'hidden')
317+
.style('white-space', 'nowrap')
318+
.style('max-width', '270px')
319+
.style('text-overflow', 'ellipsis')
320+
.attr('title', _legend[d].value)
321+
.text(_legend[d].value)
296322
}
297323
}
298324
if (lastContinues.length > 0) {

0 commit comments

Comments
 (0)