用HTML5 Canvas模拟用圆规画心形

作为一个产品偏执狂,对H5页面越来越喜欢,很想自己动手试试。恰好前段时间赶上2.14西方情人节,于是和同学JJ讨论了一个作品。用圆规画心形!效果如下:

对于数学过程,可以从“我也试试”按钮中一步一步观看,就不再做数学证明了。那我就回归程序员的角色,谈谈如何用Canvas画出来。

这里有几个重点:动画画圆、如何擦除辅助线,怎样点赞。

  • 擦除辅助线

为了保证兼容性,选用createjs框架作图。createjs是一个Canvas框架,也可以说是一个游戏框架。它提供了一个舞台stage的概念,所有元素都在舞台上呈现。舞台下面还可以有子容器用来承载更复杂但又可以独立的个体,比如一个人,人有手臂,腿等,都可以单独放在一个容器container中,然后再添加进舞台,作为子元素。这样就可以很方便地以元素为单位进行相关操作。比如我这里中途有辅助线,但是完成之后要删除,用createjs框架就可以先创建一个元素,不需要的时候就把这个元素隐藏或者删除,极为方便。这样就解决了如何擦除辅助线的问题了。如果单纯使用原生Canvas api去完成这些工作,那将是一场灾难。

  • 动画画圆

如果单纯用Canvas画一个圆,那很简单,直接用circle等API即可,但是这些API瞬间就把圆画好了,过程看不到,duang,观众一定会骂我。所以要自己写代码动态画路径。

哈哈,要不看看代码吧,这是一个动态画圆的类:

function Circle(x,y,r,container){
createjs.Shape.call(this);
this.beginDraw = false;
this.angle = 0;
this.posX = 0;
this.posY = 0;
this.X = x;//其实这里没必要保存,直接用参数的x,y,r即可
this.Y = y;
this.R = r;
this.center = new createjs.Shape();
this.center.graphics.beginFill(“black”).drawCircle(x,y,2);
this.center.visible = false;
if(container) container.addChild(this.center);
this.radius = new createjs.Shape();
this.radius.x = x;
this.radius.y = y;
this.radius.visible = false;
this.radius.graphics.beginStroke(“blue”).moveTo(0,0).lineTo(r,0);
if(container) container.addChild(this.radius);
this.graphics.beginStroke(“red”).moveTo(x+r,y);
this.addEventListener(“tick”,this);
this.addEventListener(“removed”,this);
this.handleEvent = function(event){
switch(event.type){
case “tick”:

//监听tick事件,在事件响应中画路径,tick事件是createjs设定FPS后定时出发的的事件

if(this.angle <= Math.PI*2 && this.beginDraw) {
this.radius.visible = true;
this.center.visible = true;
this.angle += 0.05;
this.radius.rotation = this.angle /Math.PI * 180;//每画一点,半径先旋转相应的角度
this.posX = this.X + Math.cos(this.angle)*this.R;
this.posY = this.Y + Math.sin(this.angle)*this.R;
this.graphics.lineTo(this.posX,this.posY);//一点一点地描路径
}else if(this.beginDraw){
this.removeEventListener(“tick”);
createjs.Tween.get(this.radius).to({visible:false});
}
break;
case “removed”:if(container) container.removeChild(this.center,this.radius);
break;
}
}
this.teach = function(){//教学过程,清除重画
this.center.rotation = this.radius.rotation = 0;
if(container) container.addChild(this.center,this.radius);
this.graphics.clear();
this.graphics.beginStroke(“red”).moveTo(x+r,y);
this.posX = x;
this.posY = y;
this.angle = 0;
}
}

  • 点赞

画完了之后得到一个心形图形,但按照上面的画法,其实并不是一个完整的路径,所以需要重画一个心形路径,然后填充。这一点可以欺骗用户。

这里不能直接用graphics的beginFill方法,因为这样会在一边画路径一边填充,应该先创建一个Fill对象,在点击时在把这个对象应用到对象当中,代码如下:

var fill = new createjs.Graphics.Fill(“red”);
heart.graphics.append(fill);

在制作过程中遇到一个问题,createjs本身的clik事件不知道为什么没有反应了,最后我是用jquery来实现的。如果有高人请指点!

发表评论

电子邮件地址不会被公开。