Анимация по кривой
Вложений: 2
:help:
Нужно сделать анимацию с точки А в точку Б по времени с сохранением координат. К примеру путь между ними занимает например 20 минут, но после обновления страницы движение не должно начинаться с начала. В базу будет сохраняться время начала и после выводится метка с учетом пройдённого времени. Вообще не представляю как это можно сделать. Помогите пожалуйста. |
Ваша задача показалась мне интересной и я написал... (даже не знаю, как это обозвать) "нечто", что может послужить вам либо основой, либо подтолкнуть вас к решению задачи.
Тоже самое, что и ниже, только на codesandbox. <!DOCTYPE html> <html> <head> <title>Vanila js. Line on canvas with Marker</title> <meta charset="UTF-8" /> <style> #canvas { background: #eee; } </style> </head> <body> <div> <lable> <span>Completeness</span> <div> <span>0%</span> <input type="range" name="completeness" min="0" max="100" step="1" value="0" /> <span>100%</span> </div> </lable> </div> <div id="canvas-container"> <div> <div style="margin-top: 3px; color: gray;"> Try to draw a line on the canvas below </div> <canvas id="canvas"></canvas> </div> <button type="button" id="set-new-route">Set a new route</button> </div> <script> (() => { const getElement = (selector) => { const element = document.querySelector(selector); if (!element) { throw new Error(`Element with selector [${selector}] not found`); } return element; }; const getRoutePoints = (canvas, externalListeners = {}) => { return new Promise((resolve) => { const canvasRect = canvas.getBoundingClientRect(); const getPoint = (e) => ({ x: e.clientX - canvasRect.left, y: e.clientY - canvasRect.top }); let pointsBuffer = []; let shouldRecordPoints = false; const done = () => { for (const eventName of Object.keys(listeners)) { canvas.removeEventListener(eventName, listeners[eventName]); } resolve(pointsBuffer); }; const listeners = { mousedown(e) { if (shouldRecordPoints) { return; } pointsBuffer = []; shouldRecordPoints = true; if (externalListeners.onmousedown) { externalListeners.onmousedown(getPoint(e)); } }, mousemove(e) { if (!shouldRecordPoints) { return; } pointsBuffer.push(getPoint(e)); if (externalListeners.onmousemove) { externalListeners.onmousemove(getPoint(e)); } }, mouseup(e) { if (!shouldRecordPoints) { return; } shouldRecordPoints = false; if (externalListeners.onmouseup) { externalListeners.onmouseup(getPoint(e)); } done(); } }; for (const eventName of Object.keys(listeners)) { canvas.addEventListener(eventName, listeners[eventName]); } }); }; const listenCompletenesChanges = (() => { let listener = null; const node = getElement('[name="completeness"]'); node.addEventListener("input", function () { try { if (listener) { listener(+this.value); } } catch (_) {} }); return (callable) => { try { (listener = callable)(+node.value); } catch (_) {} }; })(); const canvas = getElement("#canvas"); canvas.width = window.innerWidth; const ctx = canvas.getContext("2d"); ctx.lineWidth = 3; ctx.setLineDash([15, 5]); const setNewRouteButton = getElement("#set-new-route"); setNewRouteButton.addEventListener("click", async function () { listenCompletenesChanges(() => {}); // remove last listener setNewRouteButton.disabled = true; const ctx = canvas.getContext("2d"); // clear canvas ctx.beginPath(); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.stroke(); // await route points const points = await getRoutePoints(canvas, { onmousedown({ x, y }) { ctx.moveTo(x, y); ctx.lineTo(x, y); ctx.stroke(); }, onmousemove({ x, y }) { ctx.lineTo(x, y); ctx.stroke(); } }).then((points) => { setNewRouteButton.disabled = false; return points; }); if (!points) { return; } const cache = document.createElement("canvas"); cache.width = canvas.width; cache.height = canvas.height; cache.getContext("2d").drawImage(canvas, 0, 0); listenCompletenesChanges((completeness) => { const ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(cache, 0, 0); const lastCompletedPointIndex = Math.max( 0, Math.min( points.length, Math.round((points.length / 100) * completeness) ) - 1 ); const cursorSize = 10; const halfOfCursorSize = cursorSize / 2; const { x, y } = points[lastCompletedPointIndex]; ctx.save(); ctx.strokeStyle = "green"; ctx.setLineDash([]); ctx.roundRect( x - halfOfCursorSize, y - halfOfCursorSize, cursorSize, cursorSize, halfOfCursorSize ); ctx.stroke(); ctx.restore(); }); }); setNewRouteButton.dispatchEvent(new Event("click")); })(); </script> </body> </html> |
Часовой пояс GMT +3, время: 20:51. |