gpt4 book ai didi

javascript - 我想沿着特定路径制作对象的动画

转载 作者:行者123 更新时间:2023-12-03 21:38:06 25 4
gpt4 key购买 nike

我必须移动路径上的小矩形。在 Canvas 内单击后,矩形就会移动。

我无法为其设置动画,因为对象只是跳转到所需的点。

请在 Fiddle 上找到代码.

HTML

<canvas id="myCanvas" width=578 height=200></canvas>

CSS

#myCanvas {
width:578px;
height:200px;
border:2px thin;
}

JavaScript

var myRectangle = {
x: 100,
y: 20,
width: 25,
height: 10,
borderWidth: 1
};

$(document).ready(function () {
$('#myCanvas').css("border", "2px solid black");
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var cntxt = canvas.getContext('2d');
drawPath(context);
drawRect(myRectangle, cntxt);

$('#myCanvas').click(function () {
function animate(myRectangle, canvas, cntxt, startTime) {
var time = (new Date()).getTime() - startTime;
var linearSpeed = 10;
var newX = Math.round(Math.sqrt((100 * 100) + (160 * 160)));
if (newX < canvas.width - myRectangle.width - myRectangle.borderWidth / 2) {

myRectangle.x = newX;

}


context.clearRect(0, 0, canvas.width, canvas.height);
drawPath(context);
drawRect(myRectangle, cntxt);

// request new frame
requestAnimFrame(function () {
animate(myRectangle, canvas, cntxt, startTime);
});
}
drawRect(myRectangle, cntxt);
myRectangle.x = 100;
myRectangle.y = 121;
setTimeout(function () {
var startTime = (new Date()).getTime();
animate(myRectangle, canvas, cntxt, startTime);
}, 1000);

});
});

$(document).keypress(function (e) {
if (e.which == 13) {


$('#myCanvas').click();

}
});

function drawRect(myRectangle, cntxt) {

cntxt.beginPath();
cntxt.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);
cntxt.fillStyle = 'cyan';
cntxt.fill();

cntxt.strokeStyle = 'black';
cntxt.stroke();
};

function drawPath(context) {

context.beginPath();
context.moveTo(100, 20);

// line 1
context.lineTo(200, 160);
// quadratic curve
context.quadraticCurveTo(230, 200, 250, 120);

// bezier curve
context.bezierCurveTo(290, -40, 300, 200, 400, 150);

// line 2
context.lineTo(500, 90);
context.lineWidth = 5;
context.strokeStyle = 'blue';
context.stroke();
};

最佳答案

以下是如何沿着特定路径移动对象

enter image description here

动画涉及随时间的移动。因此,对于动画的每个“帧”,您需要知道在何处绘制移动对象(矩形)的 XY 坐标。

此代码接受完成百分比(0.00 到 1.00)并返回 XY 坐标,即沿路径段的百分比。例如:

  • 0.00 将返回直线(或曲线)起点处的 XY。
  • 0.50 将返回直线(或曲线)中间的 XY。
  • 1.00 将返回直线(或曲线)末端的 XY。

下面是获取沿直线指定百分比的 XY 的代码:

// line: percent is 0-1
function getLineXYatPercent(startPt,endPt,percent) {
var dx = endPt.x-startPt.x;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx*percent;
var Y = startPt.y + dy*percent;
return( {x:X,y:Y} );
}

下面是沿二次贝塞尔曲线获取指定百分比的 XY 的代码:

// quadratic bezier: percent is 0-1
function getQuadraticBezierXYatPercent(startPt,controlPt,endPt,percent) {
var x = Math.pow(1-percent,2) * startPt.x + 2 * (1-percent) * percent * controlPt.x + Math.pow(percent,2) * endPt.x;
var y = Math.pow(1-percent,2) * startPt.y + 2 * (1-percent) * percent * controlPt.y + Math.pow(percent,2) * endPt.y;
return( {x:x,y:y} );
}

下面是沿三次贝塞尔曲线获取指定百分比的 XY 的代码:

// cubic bezier percent is 0-1
function getCubicBezierXYatPercent(startPt,controlPt1,controlPt2,endPt,percent){
var x=CubicN(percent,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y=CubicN(percent,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
return({x:x,y:y});
}

// cubic helper formula at percent distance
function CubicN(pct, a,b,c,d) {
var t2 = pct * pct;
var t3 = t2 * pct;
return a + (-a * 3 + pct * (3 * a - a * pct)) * pct
+ (3 * b + pct * (-6 * b + b * 3 * pct)) * pct
+ (c * 3 - c * 3 * pct) * t2
+ d * t3;
}

以下是如何将它们组合在一起以动画化路径的各个部分

// calculate the XY where the tracking will be drawn

if(pathPercent<25){
var line1percent=pathPercent/24;
xy=getLineXYatPercent({x:100,y:20},{x:200,y:160},line1percent);
}
else if(pathPercent<50){
var quadPercent=(pathPercent-25)/24
xy=getQuadraticBezierXYatPercent({x:200,y:160},{x:230,y:200},{x:250,y:120},quadPercent);
}
else if(pathPercent<75){
var cubicPercent=(pathPercent-50)/24
xy=getCubicBezierXYatPercent({x:250,y:120},{x:290,y:-40},{x:300,y:200},{x:400,y:150},cubicPercent);
}
else {
var line2percent=(pathPercent-75)/25
xy=getLineXYatPercent({x:400,y:150},{x:500,y:90},line2percent);
}

// draw the tracking rectangle
drawRect(xy);

这是工作代码和 fiddle :http://jsfiddle.net/m1erickson/LumMX/

<!doctype html>
<html lang="en">
<head>

<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>

<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>

<script>

$(function() {

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

// set starting values
var fps = 60;
var percent=0
var direction=1;

// start the animation
animate();

function animate() {

// set the animation position (0-100)
percent+=direction;
if(percent<0){ percent=0; direction=1; };
if(percent>100){ percent=100; direction=-1; };

draw(percent);

// request another frame
setTimeout(function() {
requestAnimationFrame(animate);
}, 1000 / fps);
}


// draw the current frame based on sliderValue
function draw(sliderValue){

// redraw path
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.lineWidth = 5;

ctx.beginPath();
ctx.moveTo(100, 20);
ctx.lineTo(200, 160);
ctx.strokeStyle = 'red';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(200, 160);
ctx.quadraticCurveTo(230, 200, 250, 120);
ctx.strokeStyle = 'green';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(250,120);
ctx.bezierCurveTo(290, -40, 300, 200, 400, 150);
ctx.strokeStyle = 'blue';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(400, 150);
ctx.lineTo(500, 90);
ctx.strokeStyle = 'gold';
ctx.stroke();

// draw the tracking rectangle
var xy;

if(sliderValue<25){
var percent=sliderValue/24;
xy=getLineXYatPercent({x:100,y:20},{x:200,y:160},percent);
}
else if(sliderValue<50){
var percent=(sliderValue-25)/24
xy=getQuadraticBezierXYatPercent({x:200,y:160},{x:230,y:200},{x:250,y:120},percent);
}
else if(sliderValue<75){
var percent=(sliderValue-50)/24
xy=getCubicBezierXYatPercent({x:250,y:120},{x:290,y:-40},{x:300,y:200},{x:400,y:150},percent);
}
else {
var percent=(sliderValue-75)/25
xy=getLineXYatPercent({x:400,y:150},{x:500,y:90},percent);
}
drawRect(xy,"red");

}


// draw tracking rect at xy
function drawRect(point,color){
ctx.fillStyle="cyan";
ctx.strokeStyle="gray";
ctx.lineWidth=3;
ctx.beginPath();
ctx.rect(point.x-13,point.y-8,25,15);
ctx.fill();
ctx.stroke();
}

// draw tracking dot at xy
function drawDot(point,color){
ctx.fillStyle=color;
ctx.strokeStyle="black";
ctx.lineWidth=3;
ctx.beginPath();
ctx.arc(point.x,point.y,8,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
ctx.stroke();
}

// line: percent is 0-1
function getLineXYatPercent(startPt,endPt,percent) {
var dx = endPt.x-startPt.x;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx*percent;
var Y = startPt.y + dy*percent;
return( {x:X,y:Y} );
}

// quadratic bezier: percent is 0-1
function getQuadraticBezierXYatPercent(startPt,controlPt,endPt,percent) {
var x = Math.pow(1-percent,2) * startPt.x + 2 * (1-percent) * percent * controlPt.x + Math.pow(percent,2) * endPt.x;
var y = Math.pow(1-percent,2) * startPt.y + 2 * (1-percent) * percent * controlPt.y + Math.pow(percent,2) * endPt.y;
return( {x:x,y:y} );
}

// cubic bezier percent is 0-1
function getCubicBezierXYatPercent(startPt,controlPt1,controlPt2,endPt,percent){
var x=CubicN(percent,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y=CubicN(percent,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
return({x:x,y:y});
}

// cubic helper formula at percent distance
function CubicN(pct, a,b,c,d) {
var t2 = pct * pct;
var t3 = t2 * pct;
return a + (-a * 3 + pct * (3 * a - a * pct)) * pct
+ (3 * b + pct * (-6 * b + b * 3 * pct)) * pct
+ (c * 3 - c * 3 * pct) * t2
+ d * t3;
}


}); // end $(function(){});

</script>
</head>
<body>
<canvas id="canvas" width=600 height=300></canvas>
</body>
</html>

关于javascript - 我想沿着特定路径制作对象的动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17083580/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com