UNPKG

mobility-toolbox-js

Version:

Toolbox for JavaScript applications in the domains of mobility and logistics.

201 lines (200 loc) 8.63 kB
import createCanvas from '../utils/createCanvas'; export const rotateCanvas = (canvas, rotation) => { const ctx = canvas.getContext('2d'); ctx === null || ctx === void 0 ? void 0 : ctx.translate(canvas.width / 2, canvas.height / 2); ctx === null || ctx === void 0 ? void 0 : ctx.rotate(rotation); ctx === null || ctx === void 0 ? void 0 : ctx.translate(-canvas.width / 2, -canvas.height / 2); }; const arrowCache = {}; export const getArrowCanvas = (arrowSize, fillColor, pixelRatio = 1) => { const key = `${arrowSize.toString()},${fillColor},${pixelRatio}`; if (!arrowCache[key]) { // Create the arrow canvas const padding = 0 * pixelRatio; const canvas = createCanvas(arrowSize[0] * pixelRatio, arrowSize[1] * pixelRatio); const ctx = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d'); if (canvas && ctx) { ctx.fillStyle = fillColor; ctx.beginPath(); ctx.moveTo(padding, padding); ctx.lineTo(canvas.width - padding, canvas.height / 2); ctx.lineTo(padding, canvas.height - padding); ctx.fill(); ctx.beginPath(); ctx.moveTo(padding, padding); ctx.lineTo(canvas.width - padding, canvas.height / 2); ctx.lineTo(padding, canvas.height - padding); ctx.lineTo(padding, padding); ctx.stroke(); } arrowCache[key] = canvas; } return arrowCache[key]; }; const bufferArrowCache = {}; export const getBufferArrowCanvas = (width, height, fillColor, arrowSize, rotation = 0, pixelRatio = 1, margin = 0) => { if (!arrowSize) { return null; } const bufferKey = `${fillColor},${width},${height},${rotation},${pixelRatio},${margin}.${arrowSize.toString()}`; if (!bufferArrowCache[bufferKey]) { // Create a buffer canvas around the current vehicle to display properly the arrow const arrowCanvas = getArrowCanvas(arrowSize, fillColor, pixelRatio); if (arrowCanvas) { const bufferCanvas = createCanvas(width + arrowCanvas.width * 2 + margin * 2, height + arrowCanvas.height * 2 + margin * 2); if (bufferCanvas) { const bufferCtx = bufferCanvas.getContext('2d'); rotateCanvas(bufferCanvas, -rotation); bufferCtx === null || bufferCtx === void 0 ? void 0 : bufferCtx.drawImage(arrowCanvas, bufferCanvas.width - arrowCanvas.width, bufferCanvas.height / 2 - arrowCanvas.height / 2 - margin / 2, arrowCanvas.width, arrowCanvas.height); } bufferArrowCache[bufferKey] = bufferCanvas; } } return bufferArrowCache[bufferKey]; }; const cacheDelayBg = {}; /** * Draw circle delay background */ export const getDelayBgCanvas = (radius, color, pixelRatio = 1, blurWidth = 1) => { const key = `${radius}, ${color}, ${blurWidth}, ${pixelRatio}`; const padding = 1 * pixelRatio; // must be the same as circle padding const blur = blurWidth * pixelRatio; if (!cacheDelayBg[key]) { const size = radius * 2 + padding * 2 + blur * 2 + padding * 2; const canvas = createCanvas(size, size); const ctx = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d'); if (canvas && ctx) { ctx.beginPath(); ctx.arc(size / 2, size / 2, radius + padding + blur, 0, 2 * Math.PI, false); ctx.fillStyle = color; ctx.filter = `blur(${blur}px)`; ctx.fill(); cacheDelayBg[key] = canvas; } } return cacheDelayBg[key]; }; const cacheCanvasTextSize = {}; export const getCanvasTextSize = (text, font, color, outlineColor, outlineWidth, pixelRatio) => { const key = `${text}, ${font}, ${color}, ${outlineColor}, ${outlineWidth}, ${pixelRatio}`; if (!cacheCanvasTextSize[key]) { const canvas = createCanvas(300 * pixelRatio, 300 * pixelRatio); const ctx = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d'); if (canvas && ctx) { // We calcuate the text size first ctx.font = font; ctx.textBaseline = 'hanging'; ctx.textAlign = 'left'; ctx.fillStyle = color; ctx.strokeStyle = outlineColor; ctx.lineWidth = outlineWidth; ctx.strokeText(text, 0, 0); ctx.fillText(text, 0, 0); const textMetrics = ctx.measureText(text); const size = { height: textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent, width: textMetrics.width, }; cacheCanvasTextSize[key] = size; } } return cacheCanvasTextSize[key]; }; const cacheDelayText = {}; /** * Draw delay text */ export const getDelayTextCanvas = (text, fontSize, font, color, outlineColor = '#000', pixelRatio = 1) => { const key = `${text}, ${font}, ${color}, ${outlineColor}, ${pixelRatio}`; const padding = 2 * pixelRatio; const lineWidth = 1.5 * pixelRatio; if (!cacheDelayText[key]) { const textSize = getCanvasTextSize(text, font, color, outlineColor, lineWidth, pixelRatio); if ((textSize === null || textSize === void 0 ? void 0 : textSize.width) && (textSize === null || textSize === void 0 ? void 0 : textSize.height)) { const canvas = createCanvas(textSize.width + padding * 2, textSize.height + padding * 2); const ctx = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d'); if (canvas && ctx) { // We calcuate the text size first ctx.font = font; ctx.fillStyle = color; ctx.lineWidth = lineWidth; ctx.strokeStyle = outlineColor; ctx.textAlign = 'left'; ctx.textBaseline = 'ideographic'; ctx.strokeText(text, padding, canvas.height - padding); ctx.fillText(text, padding, canvas.height - padding); cacheDelayText[key] = canvas; } } } return cacheDelayText[key]; }; const cacheCircle = {}; /** * Draw colored circle with black border */ export const getCircleCanvas = (radius, color, hasStroke, hasDash, pixelRatio) => { const key = `${radius}, ${color}, ${hasStroke}, ${hasDash}, ${pixelRatio}`; const padding = 1 * pixelRatio; const lineWidth = hasStroke ? 1 * pixelRatio : 0; const lineDash = hasDash ? [5 * pixelRatio, 3 * pixelRatio] : null; if (!cacheCircle[key]) { const canvas = createCanvas(radius * 2 + padding * 2, radius * 2 + padding * 2); if (canvas) { const ctx = canvas.getContext('2d'); if (!ctx) { return null; } ctx.fillStyle = color; ctx.lineWidth = lineWidth; ctx.strokeStyle = '#000000'; ctx.beginPath(); ctx.arc(canvas.width / 2, canvas.height / 2, radius, 0, 2 * Math.PI, false); ctx.fill(); if (lineDash) { ctx.setLineDash(lineDash); } ctx.stroke(); cacheCircle[key] = canvas; } } return cacheCircle[key]; }; const cacheText = {}; /** * Draw text in the circle */ export const getTextCanvas = (text, radius, textSize, fillColor, strokeColor, hasStroke, pixelRatio, font) => { const key = `${text}, ${radius}, ${textSize}, ${fillColor},${strokeColor}, ${hasStroke}, ${pixelRatio}`; if (!cacheText[key]) { const canvas = createCanvas(radius * 2, radius * 2); if (canvas) { const ctx = canvas.getContext('2d'); if (!ctx) { return null; } // Draw a stroke to the text only if a provider provides realtime but we don't use it. if (hasStroke) { ctx.save(); ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; ctx.font = font; ctx.strokeStyle = strokeColor; ctx.strokeText(text, radius, radius); ctx.restore(); } // Draw a text ctx.textBaseline = 'middle'; ctx.textAlign = 'center'; ctx.fillStyle = fillColor; ctx.font = font; ctx.strokeStyle = strokeColor; ctx.strokeText(text, radius, radius); ctx.fillText(text, radius, radius); cacheText[key] = canvas; } } return cacheText[key]; };