玩玩Canvas高阶贝塞尔曲线动画

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> new document </title>
<style type="text/css">
#canvasId {	border: #6666ff 1px solid; position: absolute; top:60px; left:10px; }
#text {	width: 600px; }
</style>
</head>
<body>
<input type="text" id="text" />
<input type="button" value="播放动画" οnclick="run()" /><br />
说明:鼠标拖拽画布上的点可移动,双击画布空白处增加新的点,双击画布上的点可将其删除
<canvas id="canvasId" width="700" height="600"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvasId");
var cxt = canvas.getContext("2d");
var p = [{x:43,y:131},{x:257,y:307},{x:237,y:27},{x:455,y:210}];
var clearTimer;
var bnp;


function curve(p,lt)//贝塞尔曲线
{
	var sx=0, sy=0, s=p.length-1;
	var q = [];
	for(var i=0, l = p.length-2; i<l; ++i)
	{
		q[i] = {
			x: (p[i+1].x - p[i].x) * s - sx ,
			y: (p[i+1].y - p[i].y) * s - sy
		};
		sx += q[i].x;
		sy += q[i].y;
	}
	q[i] = {
		x: p[i+1].x - p[0].x - sx ,
		y: p[i+1].y - p[0].y - sy
	};
	sx=sy=s=i=l=undefined;
	return function(t)
	{
		t /= lt;
		var x=0, y=0;
		for(var i=q.length-1; i>=0; --i)
		{
			x = (x + q[i].x) * t;
			y = (y + q[i].y) * t;
		}
		return {x: x+p[0].x , y: y+p[0].y};
	};
}

function upg()
{
	cxt.clearRect(0,0,canvas.width,canvas.height);
	cxt.strokeStyle = "#bcbcbc";
	cxt.lineWidth = 1;
	cxt.beginPath();
	for(var i=0, l = p.length; i<l; ++i)
	{
		var u = p[i];
		cxt.lineTo(u.x, u.y);
	}
	cxt.stroke();
	var cur = curve(p,100);
	cxt.strokeStyle = "#ff0000";
	cxt.lineWidth = 3;
	cxt.beginPath();
	for(var i=0; i<=100; i++)
	{
		u = cur(i);
		cxt.lineTo(u.x, u.y);
	}
	cxt.stroke();
	for(var i=0, l = p.length; i<l; ++i)
	{
		u = p[i];
		cxt.fillStyle = u===bnp?"#c8660d":"#5b6ff0";
		cxt.beginPath();
		cxt.arc(u.x, u.y,6,0,2*Math.PI,true);
		cxt.closePath();
		cxt.fill();
	}
}

function run()
{
	clearTimeout(clearTimer);
	var cur = curve(p,100);
	cxt.strokeStyle = "#ff0000";
	cxt.lineWidth = 1;
	cxt.fillStyle = "#7122b7";
	function eyg(t)
	{
		cxt.clearRect(0,0,canvas.width,canvas.height);
		cxt.beginPath();
		for(var i=0; i<=100; i++)
		{
			var u = cur(i);
			cxt.lineTo(u.x, u.y);
		}
		cxt.stroke();
		var u = cur(t);
		cxt.beginPath();
		cxt.arc(u.x, u.y,8,0,2*Math.PI,true);
		cxt.closePath();
		cxt.fill();
		if(++t<=100)
			clearTimer = setTimeout(function(){eyg(t)},50);
		else
			upg();
	}
	eyg(0);
}

function distance(a,b)
{
	var x = b.x-a.x , y = b.y-a.y;
	return Math.sqrt(x*x+y*y);
}

function getXY(e)
{
	return {
		x : e.clientX - canvas.offsetLeft + document.body.scrollLeft,
		y : e.clientY - canvas.offsetTop  + document.body.scrollTop
	}
}

function select(sp)
{
	for(var i=0, l = p.length; i<l; ++i)
		if(distance(sp,p[i])<=6)
			return i;
	return -1;
};

function uptext()
{
	var arr = [];
	for(var i=0, l = p.length; i<l; ++i)
		arr[i] = "{x:"+p[i].x+",y:"+p[i].y+"}";
	document.getElementById("text").value = "["+arr.join(",")+"]";
}

canvas.οnmοusedοwn=function(e)
{
	e = e||event;
	var sp = getXY(e);
	var gr = select(sp);
	bnp = gr!=-1 ? p[gr] : null;
};

canvas.οnmοusemοve=function(e)
{
	if(!bnp) return;
	e = e||event;
	var sp = getXY(e);
	bnp.x = sp.x;
	bnp.y = sp.y;
	uptext();
	upg();
};

canvas.οnmοuseup=function(e)
{
	bnp = null;
};

canvas.οndblclick=function(e)
{
	e = e||event;
	var sp = getXY(e);
	var gr = select(sp);
	if(gr==-1)
		p.push(sp);
	else
	{
		if(p.length>2)
			p.splice(gr,1);
		else
			alert("一条线不能少于 2 个点吧");
	}
	uptext();
	upg();
};

canvas.onselectstart=canvas.οndragstart=function(e){return false;};

uptext();
upg();

</script>
</body>
</html>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天际的海浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值