aboutsummaryrefslogtreecommitdiff
path: root/src/marker.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/marker.ts')
-rw-r--r--src/marker.ts171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/marker.ts b/src/marker.ts
new file mode 100644
index 0000000..9f59497
--- /dev/null
+++ b/src/marker.ts
@@ -0,0 +1,171 @@
+import { h, s } from 'lib/h'
+import * as Color from 'lib/color'
+import * as ContextMenu from 'lib/contextMenu'
+import * as MarkerForm from 'markerForm'
+import * as Icons from 'lib/icons'
+import * as Modal from 'lib/modal'
+import * as State from 'state'
+const L = window.L
+
+interface CreateParams {
+ id: State.Index,
+ pos: L.Pos,
+ color: string,
+ icon: string,
+ name: string,
+ radius: number,
+ addToMap: (layer: L.Layer | L.FeatureGroup) => void,
+ removeFromMap: (layer: L.Layer | L.FeatureGroup) => void,
+}
+
+export function add({ id, pos, color, icon, name, radius, addToMap, removeFromMap }: CreateParams) {
+ const marker = L.marker(pos, {
+ draggable: true,
+ autoPan: true,
+ icon: divIcon({ icon, color, name }),
+ })
+
+ const circle =
+ radius !== 0
+ ? L.circle(pos, { radius, color, fillColor: color })
+ : undefined
+
+ const layer =
+ circle !== undefined
+ ? L.featureGroup([ marker, circle ])
+ : L.featureGroup([ marker ])
+
+ const onUpdate = () =>
+ Modal.show(MarkerForm.view({
+ onValidate: (color: string, icon: string, name: string, radius: number) => {
+ removeFromMap(layer)
+ add({ id, pos, color, icon, name, radius, addToMap, removeFromMap })
+ State.update(id, { pos, color, icon, name, radius })
+ Modal.hide()
+ },
+ onCancel: () => Modal.hide(),
+ color,
+ icon,
+ name,
+ radius,
+ }))
+
+ marker.addEventListener('contextmenu', e => {
+ ContextMenu.show(
+ e.originalEvent,
+ [ { label: 'Modify',
+ action: onUpdate,
+ }
+ , { label: 'Remove',
+ action: () => {
+ removeFromMap(layer)
+ State.remove(id)
+ }
+ }
+ ]
+ )
+ })
+
+ marker.addEventListener('drag', e => {
+ circle && circle.setLatLng(marker.getLatLng())
+ })
+
+ marker.addEventListener('dragend', e => {
+ const pos = marker.getLatLng()
+ removeFromMap(layer)
+ add({ id, pos, color, icon, name, radius, addToMap, removeFromMap })
+ State.update(id, { pos, color, icon, name, radius })
+ })
+
+ marker.addEventListener('dblclick', onUpdate)
+
+ addToMap(layer)
+}
+
+interface CreateIconParams {
+ icon: string,
+ color: string,
+ name: string,
+}
+
+function divIcon({ icon, color, name }: CreateIconParams): L.Icon {
+ const c = Color.parse(color)
+ const crBlack = Color.contrastRatio({ red: 0, green: 0, blue: 0 }, c)
+ const crWhite = Color.contrastRatio({ red: 255, green: 255, blue: 255 }, c)
+ const textCol = crBlack > crWhite ? 'black' : 'white'
+ const width = 10
+ const height = 15
+ const stroke = 'black'
+ const strokeWidth = 0.6
+ // Triangle
+ const t = [
+ { x: width * 0.15, y: 7.46 },
+ { x: width / 2, y: height },
+ { x: width * 0.85, y: 7.46 }
+ ]
+ return L.divIcon(
+ { className: ''
+ , popupAnchor: [ 0, -34 ]
+ , html:
+ h('div',
+ { className: 'g-Marker' },
+ s('svg',
+ { viewBox: `0 0 ${width} ${height}`,
+ class: 'g-Marker__Base'
+ },
+ s('circle',
+ { cx: width / 2,
+ cy: width / 2,
+ r: (width - 2 * strokeWidth) / 2,
+ stroke,
+ 'stroke-width': strokeWidth,
+ fill: color
+ }
+ ),
+ s('polygon',
+ { points: `${t[0].x},${t[0].y} ${t[1].x},${t[1].y} ${t[2].x},${t[2].y}`,
+ fill: color
+ }
+ ),
+ s('line',
+ { x1: t[0].x,
+ y1: t[0].y,
+ x2: t[1].x,
+ y2: t[1].y,
+ stroke,
+ 'stroke-width': strokeWidth
+ }
+ ),
+ s('line',
+ { x1: t[1].x,
+ y1: t[1].y,
+ x2: t[2].x,
+ y2: t[2].y,
+ stroke,
+ 'stroke-width': strokeWidth
+ }
+ ),
+ ),
+ Icons.get(
+ icon,
+ { class: 'g-Marker__Icon'
+ , style: `fill: ${textCol}; stroke: ${textCol}`
+ }
+ ),
+ h('div',
+ { className: 'g-Marker__Title',
+ style: `color: black; text-shadow: ${textShadow('white', 1, 1)}`
+ },
+ name
+ )
+ )
+ }
+ )
+}
+
+function textShadow(color: string, w: number, blurr: number): string {
+ return [[-w, -w], [-w, 0], [-w, w], [0, -w], [0, w], [w, -w], [w, 0], [w, w]]
+ .map(xs => `${color} ${xs[0]}px ${xs[1]}px ${blurr}px`)
+ .join(', ')
+}
+