[英]Move an object through set of coordinates on HTML5 Canvas
我想通過 HTML5 Canvas 上的坐標數組(例如:{(300,400), (200,300), (300,200),(400,400)} )移動對象(在本例中為圓) 。 我可以將對象移動到一個坐標,如下所示。 以下代碼在 (100,100) 處繪制一個圓並將其移動到 (300,400)。 我在嘗試擴展時卡住了,以便圓圈一個接一個地穿過一組坐標。
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
//circle object
let circle ={
x:100,
y:100,
radius:10,
dx:1,
dy:1,
color:'blue'
}
//function to draw above circle on canvas
function drawCircle(){
ctx.beginPath();
ctx.arc(circle.x,circle.y,circle.radius,0,Math.PI*2);
ctx.fillStyle=circle.color;
ctx.fill();
ctx.closePath();
}
//Moving to a target coordinate (targetX,targetY)
function goTo(targetX,targetY){
if(Math.abs(circel.x-targetX)<circle.dx && Math.abs(circel.y-targetY)<circle.dy){
circle.dx=0;
circle.dy=0;
circel.x = targetX;
circle.y = targetY;
}
else{
const opp = targetY - circle.y;
const adj = targetX - circle.x;
const angle = Math.atan2(opp,adj)
circel.x += Math.cos(angle)*circle.dx
circle.y += Math.sin(angle)*circle.dy
}
}
function update(){
ctx.clearRect(0,0,canvas.width,canvas.height);
drawCircle()
goTo(300,400)
requestAnimationFrame(update);
}
update()
為了最好地控制動畫,您需要創建可以按時間隨機訪問的路點(關鍵幀)。 這意味着您可以通過設置時間來獲得動畫中的任何位置。
然后,您可以播放和暫停、設置速度、反轉和尋找動畫中的任何位置。
下面的示例使用一組點並添加在請求的時間快速定位關鍵幀並插入位置所需的數據。
藍點將在pathTime
設置的時間內以恆定速度在路徑上移動,在這種情況下為 4 秒。
紅點的位置由滑塊設置。 這是為了說明動畫位置的隨機訪問。
const ctx = canvas.getContext('2d'); const pathTime = 4; // Total time to travel path from start to end in seconds var startTime, animTime = 0, paused = false; requestAnimationFrame(update); const P2 = (x, y) => ({x, y, dx: 0,dy: 0,dist: 0, start: 0, end: 0}); const pathCoords = [ P2(20, 20), P2(100, 50),P2(180, 20), P2(150, 100), P2(180, 180), P2(100, 150), P2(20, 180), P2(50, 100), P2(20, 20), ]; createAnimationPath(pathCoords); const circle ={ draw(rad = 10, color = "blue") { ctx.fillStyle = color; ctx.beginPath(); ctx.arc(this.x, this.y, rad, 0, Math.PI * 2); ctx.fill(); } }; function createAnimationPath(points) { // Set up path for easy random position lookup const segment = (prev, next) => { [prev.dx, prev.dy] = [next.x - prev.x, next.y - prev.y]; prev.dist = Math.hypot(prev.dx, prev.dy); next.end = next.start = prev.end = prev.start + prev.dist; } var i = 1; while (i < points.length) { segment(points[i - 1], points[i++]) } } function getPos(path, pos, res = {}) { pos = (pos % 1) * path[path.length - 1].end; // loop & scale to total length const pathSeg = path.find(p => pos >= p.start && pos <= p.end); const unit = (pos - pathSeg.start) / pathSeg.dist; // unit distance on segment res.x = pathSeg.x + pathSeg.dx * unit; // x, y position on segment res.y = pathSeg.y + pathSeg.dy * unit; return res; } function update(time){ // startTime ??= time; // Throws syntax on iOS startTime = startTime ?? time; // Fix for above ctx.clearRect(0, 0, canvas.width, canvas.height); if (paused) { startTime = time - animTime } else { animTime = time - startTime } getPos(pathCoords, (animTime / 1000) / pathTime, circle).draw(); getPos(pathCoords, timeSlide.value, circle).draw(5, "red"); requestAnimationFrame(update); } pause.addEventListener("click", ()=> { paused = true; pause.classList.add("pause") }); play.addEventListener("click", ()=> { paused = false; pause.classList.remove("pause") }); rewind.addEventListener("click", ()=> { startTime = undefined; animTime = 0 });
div { position:absolute; top: 5px; left: 20px; } #timeSlide {width: 360px} .pause {color:blue} button {height: 30px}
<div><input id="timeSlide" type="range" min="0" max="1" step="0.001" value="0" width= "200"><button id="rewind">Start</button><button id="pause">Pause</button><button id="play">Play</button></div> <canvas id="canvas" width="200" height="200"></canvas>
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); // array of path coords const pathCoords = [ [200,100], [300, 150], [200,190], [400,100], [50,10], [150,10], [0, 50], [500,90], [20,190], [10,180], ]; // current point let currentTarget = pathCoords.shift(); //circle object const circle ={ x:10, y:10, radius:10, dx:2, dy:2, color:'blue' } //function to draw above circle on canvas function drawCircle(){ ctx.beginPath(); ctx.arc(circle.x,circle.y,circle.radius,0,Math.PI*2); ctx.fillStyle=circle.color; ctx.fill(); ctx.closePath(); } //Moving to a target coordinate (targetX,targetY) function goTo(targetX, targetY){ if(Math.abs(circle.x-targetX)<circle.dx && Math.abs(circle.y-targetY)<circle.dy){ // dont stop... //circle.dx = 0; //circle.dy = 0; circle.x = targetX; circle.y = targetY; // go to next point if (pathCoords.length) { currentTarget = pathCoords.shift(); } else { console.log('Path end'); } } else { const opp = targetY - circle.y; const adj = targetX - circle.x; const angle = Math.atan2(opp,adj) circle.x += Math.cos(angle)*circle.dx circle.y += Math.sin(angle)*circle.dy } } function update(){ ctx.clearRect(0,0,canvas.width,canvas.height); drawCircle(); goTo(...currentTarget); requestAnimationFrame(update); } update();
<canvas id=canvas width = 500 height = 200></canvas>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.