From d86a3ef187359fbe83a5dd950295868c4ef39d09 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sat, 26 Jun 2021 23:17:37 -0700 Subject: Implement marker colors --- modern/package.json | 1 + modern/src/map/Map.js | 16 +++++++++++----- modern/src/map/PositionsMap.js | 14 +++++++++++++- modern/src/map/mapUtil.js | 8 ++++---- modern/src/theme/palette.js | 14 +++++++++----- 5 files changed, 38 insertions(+), 15 deletions(-) (limited to 'modern') diff --git a/modern/package.json b/modern/package.json index 6902d37..b052240 100644 --- a/modern/package.json +++ b/modern/package.json @@ -11,6 +11,7 @@ "@material-ui/lab": "^4.0.0-alpha.56", "@reduxjs/toolkit": "^1.5.1", "@turf/turf": "^5.1.6", + "canvas-tint-image": "^2.0.1", "mapbox-gl": "^1.12.0", "moment": "^2.28.0", "ol": "^6.4.3", diff --git a/modern/src/map/Map.js b/modern/src/map/Map.js index 014268c..a973cf7 100644 --- a/modern/src/map/Map.js +++ b/modern/src/map/Map.js @@ -4,10 +4,11 @@ import mapboxgl from 'mapbox-gl'; import { SwitcherControl } from './switcher/switcher'; import React, { useRef, useLayoutEffect, useEffect, useState } from 'react'; import { deviceCategories } from '../common/deviceCategories'; -import { loadIcon, loadImage } from './mapUtil'; +import { prepareIcon, loadImage } from './mapUtil'; import { styleCarto, styleMapbox, styleOsm } from './mapStyles'; import t from '../common/localization'; import { useAttributePreference } from '../common/preferences'; +import palette from '../theme/palette'; const element = document.createElement('div'); element.style.width = '100%'; @@ -36,12 +37,17 @@ const updateReadyValue = value => { }; const initMap = async () => { + if (ready) return; const background = await loadImage('images/background.svg'); - map.addImage('background', await loadIcon(background), { pixelRatio: window.devicePixelRatio }); + map.addImage('background', await prepareIcon(background), { + pixelRatio: window.devicePixelRatio, + }); await Promise.all(deviceCategories.map(async category => { - if (!map.hasImage(category)) { - const imageData = await loadIcon(background, `images/icon/${category}.svg`); - map.addImage(category, imageData, { pixelRatio: window.devicePixelRatio }); + for (const color of ['green', 'red', 'gray']) { + const icon = await loadImage(`images/icon/${category}.svg`); + map.addImage(`${category}-${color}`, prepareIcon(background, icon, palette.common[color]), { + pixelRatio: window.devicePixelRatio, + }); } })); updateReadyValue(true); diff --git a/modern/src/map/PositionsMap.js b/modern/src/map/PositionsMap.js index 4a590b7..a953ce3 100644 --- a/modern/src/map/PositionsMap.js +++ b/modern/src/map/PositionsMap.js @@ -15,12 +15,24 @@ const PositionsMap = ({ positions }) => { const history = useHistory(); const devices = useSelector(state => state.devices.items); + const deviceColor = device => { + switch (device.status) { + case 'online': + return 'green'; + case 'offline': + return 'red'; + default: + return 'gray'; + } + }; + const createFeature = (devices, position) => { const device = devices[position.deviceId] || null; return { deviceId: position.deviceId, name: device ? device.name : '', category: device && (device.category || 'default'), + color: deviceColor(device), } }; @@ -81,7 +93,7 @@ const PositionsMap = ({ positions }) => { 'source': id, 'filter': ['!', ['has', 'point_count']], 'layout': { - 'icon-image': '{category}', + 'icon-image': '{category}-{color}', 'icon-allow-overlap': true, 'text-field': '{name}', 'text-allow-overlap': true, diff --git a/modern/src/map/mapUtil.js b/modern/src/map/mapUtil.js index 4780940..ef6ff99 100644 --- a/modern/src/map/mapUtil.js +++ b/modern/src/map/mapUtil.js @@ -1,4 +1,5 @@ import wellknown from 'wellknown'; +import canvasTintImage from 'canvas-tint-image'; import circle from '@turf/circle'; export const loadImage = (url) => { @@ -9,7 +10,7 @@ export const loadImage = (url) => { }); }; -export const loadIcon = async (background, url) => { +export const prepareIcon = (background, icon, color) => { const pixelRatio = window.devicePixelRatio; const canvas = document.createElement('canvas'); @@ -21,12 +22,11 @@ export const loadIcon = async (background, url) => { const context = canvas.getContext('2d'); context.drawImage(background, 0, 0, canvas.width, canvas.height); - if (url) { - const image = await loadImage(url); + if (icon) { const iconRatio = 0.5; const imageWidth = canvas.width * iconRatio; const imageHeight = canvas.height * iconRatio; - context.drawImage(image, (canvas.width - imageWidth) / 2, (canvas.height - imageHeight) / 2, imageWidth, imageHeight); + context.drawImage(canvasTintImage(icon, color, 1), (canvas.width - imageWidth) / 2, (canvas.height - imageHeight) / 2, imageWidth, imageHeight); } return context.getImageData(0, 0, canvas.width, canvas.height); diff --git a/modern/src/theme/palette.js b/modern/src/theme/palette.js index 5c93cfd..ac26e57 100644 --- a/modern/src/theme/palette.js +++ b/modern/src/theme/palette.js @@ -1,17 +1,21 @@ +const traccarWhite = '#FFF'; const traccarPurple = '#333366'; const traccarGreen = '#4CAF50'; -const traccarWhite = '#FFF'; +const traccarRed = '#CC2222'; +const traccarGray = '#888888'; export default { common: { purple: traccarPurple, - green: traccarGreen + green: traccarGreen, + red: traccarRed, + gray: traccarGray, }, primary: { - main: traccarPurple + main: traccarPurple, }, secondary: { main: traccarGreen, - contrastText: traccarWhite - } + contrastText: traccarWhite, + }, }; -- cgit v1.2.3