commit d199240e69d2638fa84f28db8f42b57c59598b4e
parent 124306bbe3b9fac35f73f41ec2d25dc8b13dab2f
Author: Yureka <yuka@yuka.dev>
Date: Wed, 18 Aug 2021 16:13:12 +0200
parent 124306bbe3b9fac35f73f41ec2d25dc8b13dab2f
Author: Yureka <yuka@yuka.dev>
Date: Wed, 18 Aug 2021 16:13:12 +0200
add canvas animations
1 file changed, 36 insertions(+), 5 deletions(-)
diff --git a/client/src/canvas.js b/client/src/canvas.js @@ -123,6 +123,8 @@ const updateTextCache = () => { } }; +let lastAnimationUpdate = 0, firstDeparture = 0, scaleFactor = 0, lastArrival = 0; +let animationInterval; const renderJourneys = () => { ctx.clearRect(0, 0, canvas.width / dpr, canvas.height / dpr); let x = canvasState.offsetX - canvasState.indexOffset * rectWidthWithPadding, y; @@ -133,13 +135,40 @@ const renderJourneys = () => { if (!visibleJourneys.length) return; - let firstDeparture = visibleJourneys[0].legs[0].plannedDeparture; - let lastArrival = Math.max.apply(Math, + const targetFirstDeparture = Number(visibleJourneys[0].legs[0].plannedDeparture); + const targetLastArrival = Math.max.apply(Math, visibleJourneys.map(journey => journey.legs[journey.legs.length-1].plannedArrival) .concat(visibleJourneys.map(journey => journey.legs[journey.legs.length-1].arrival) )); - let scaleFactor = 1/(lastArrival - firstDeparture) * (canvas.height - 64 * dpr) / dpr; + const now = new Date(); + const factor = Math.min(.3, (now - lastAnimationUpdate) / 20); + if (!lastAnimationUpdate) { + firstDeparture = Number(targetFirstDeparture); + lastArrival = Number(targetLastArrival); + } else { + firstDeparture = firstDeparture + (targetFirstDeparture - firstDeparture) * factor; + lastArrival = lastArrival + (targetLastArrival - lastArrival) * factor; + } + const targetScaleFactor = 1/(lastArrival - firstDeparture) * (canvas.height - 64 * dpr) / dpr; + if (!lastAnimationUpdate) { + scaleFactor = targetScaleFactor; + } else { + scaleFactor = scaleFactor + (targetScaleFactor - scaleFactor) * factor; + } + lastAnimationUpdate = now; + + if (Math.abs(scaleFactor - targetScaleFactor) > 1 + || Math.abs(firstDeparture - targetFirstDeparture) > 1 + || Math.abs(lastArrival - targetLastArrival) > 1 + ) { + if (!animationInterval) animationInterval = setInterval(() => renderJourneys(), 16.6); + } else { + if (animationInterval) { + clearInterval(animationInterval); + animationInterval = null; + } + } let time = canvasState.journeys[0].legs[0].plannedDeparture; @@ -149,7 +178,7 @@ const renderJourneys = () => { let y = (time - firstDeparture) * scaleFactor + 32; ctx.fillText(formatTime(time), (window.innerWidth / dpr) > 600 ? 30 : 10, y); ctx.fillRect(0, y, canvas.width / dpr, 1); - time = new Date(Number(time) + Math.floor(120/scaleFactor)); + time = new Date(Number(time) + 3600000);//Math.floor(120/scaleFactor)); } ctx.fillStyle = '#fa5'; y = (new Date() / 1000 - firstDeparture) * scaleFactor + 32; @@ -287,6 +316,7 @@ const resizeHandler = () => { ctx.save(); ctx.scale(dpr, dpr); + lastAnimationUpdate = 0; renderJourneys(); }; @@ -306,6 +336,7 @@ const mouseUpHandler = (evt) => { } canvasState.dragging = false; + canvasState.isClick = false; }; const mouseDownHandler = (evt) => { @@ -321,7 +352,7 @@ const mouseMoveHandler = (evt) => { evt.preventDefault(); let x = evt.x || evt.changedTouches[0].pageX; canvasState.offsetX = canvasState.dragStartOffset - (canvasState.dragStartMouse - x); - if (Math.abs(canvasState.dragStartMouse - x) < 20) canvasState.isClick = false; + if (Math.abs(canvasState.dragStartMouse - x) > 20) canvasState.isClick = false; renderJourneys(); return true; }