手把手教你canvas动画(汉堡图标动画一)

动画效果如下图:


汉堡图标动画

先附上源码:

html端:

<canvas>你的浏览器暂且不支持canvas</canvas>



css端:

.canvas {

    position: relative;

    left: 50%;

    top: 50px;

    transform: translateX(-300px);

    background-color: #FFF;

    border: 2px solid #AAA;

    border-radius: 5px;

}


js端:


(function() {

var canvas      = document.getElementById('canvasTeach'),

context      = canvas.getContext('2d'),

canvasWidth  = canvas.width,

canvasHeight = canvas.height,

lineLength  = 40,

middleLineX  = canvasHeight/2,

middleLineY  = canvasHeight/2,

velocity    = 0,

a            = 0.05,

circleA      = 0.00124,

circleV      = 0,

circlePI    = 0,

upLine      = canvasHeight/2 - 40,

downLine    = canvasHeight/2 + 40,

Switch      = 0;

context.lineCap  = 'round';

context.lineJoin = 'round';

context.strokeStyle = '#AAA';

window.onload = function() {

drawTheLine();

}

function drawTheLine() {

context.clearRect(0, 0, canvasWidth, canvasHeight);

context.lineCap = 'round';

context.strokeStyle = '#AAA';

context.lineWidth = 10;

context.beginPath();

context.moveTo(canvasWidth/2 - lineLength, canvasHeight/2 - 40);

context.lineTo(canvasWidth/2 + lineLength, upLine);

context.stroke();

context.beginPath();

context.moveTo(canvasWidth/2 - lineLength, canvasHeight/2 + 40);

context.lineTo(canvasWidth/2 + lineLength, downLine);

context.stroke();

context.beginPath();

context.moveTo(canvasWidth/2 - lineLength, middleLineX);

context.lineTo(canvasWidth/2 + lineLength, middleLineY);

context.stroke();

context.beginPath();

context.arc(canvasHeight/2,canvasHeight/2,87,0,-Math.PI*circlePI,true);

context.stroke();

}

context.canvas.onmousedown = function(e) {

if (Switch == 0) {

update();

Switch = 1;

} else {

turnAround();

Switch = 0;

}

}

function update() {

if (middleLineX != canvasHeight/2 - 40) {

middleLineX -= 2;

middleLineY -= 2;

context.clearRect(200, 140, 210, 150);

drawTheLine();

setTimeout(update, 1000/120);

} else {

if (upLine < canvasHeight/2 + 40) {

if (upLine <= canvasHeight/2) {

velocity += a;

circleV  += circleA;

} else {

velocity -= a;

circleV  -= circleA;

}

upLine += velocity;

middleLineY += velocity;

downLine -= velocity;

circlePI += circleV;

drawTheLine();

setTimeout(update, 1000/120);

} else {

return;

}

}

}

function turnAround() {

if (upLine > canvasHeight/2 - 39.9) {

if (upLine >= canvasHeight/2) {

velocity += a;

circleV  += circleA;

} else {

velocity -= a;

circleV  -= circleA;

}

upLine -= velocity;

middleLineY -= velocity;

downLine += velocity;

circlePI -= circleV;

drawTheLine();

setTimeout(turnAround, 1000/120);

} else {

context.clearRect(200, 140, 210, 150);

if (middleLineX < canvasHeight/2) {

middleLineX += 2;

middleLineY += 2;

drawTheLine();

setTimeout(turnAround, 1000/120);

} else {

return;

}

}

}

})();


首先介绍一下这个动画(附图):


动画开始


开始中间的线段先往上


与第一个重合后开始画外面的圆,所有的动画都是先快后慢
最后的效果图



css和html没什么好说的,主要介绍js端的代码:


首先是变量的定义:

canvas变量具体定位到html内对应的画布元素

context为图形上下文,这边选取2d渲染


canvas的对象


由于canvas是一个对象,有这几个对应的属性会用到

canvas.width              //画布宽度

canvas.height            //画布宽度


context图形上下文对象


context有以下有一些对象:

lineCap    //线段连接时的样式(默认butt),这边使用round

lineJoin    //线段连接时的样式(默认Miter),这边使用round

strokeStyle(线段颜色  例:#FFF)


用到的函数


drawTheLine函数(划线函数,时间线发生变化的时候按照规律调用)

update函数(变成叉的时候调用)

turnAround函数(返回成汉堡图标的时候调用)

onmousedown监听下面有一个匿名函数,内的代码代表开关的常用代码,当变成叉时使用update,当返回成汉堡图标的时候调用turnAround


canvas动画核心(帧动画)


介绍一下什么是帧动画:

      和拍电影的原理是一样的,动画都是由图片组成,每秒24张图片在人眼就可以看到流畅的动画了,那帧动画用的就是这个规则,我这边设置的调用比较多,达到每秒120帧,那这个动画在人眼看来就是一个很流畅的动画了。


那说了这么多,如何做到每秒120帧呐?


其实很简单,javascript给我们提供了一些制作帧动画的时间调用函数,这边就介绍两个我认为比较有代表的函数。


setTimeout( function ,ms);    //例子:setTimeout(update, 1000/120);

内置两个参数

第一个就是调用什么函数,可以是自身,可以是其他的函数,具体受自己的控制。

第二个参数是两次调用间隔的时间,每秒调用120次就是这么来的,由于以微秒计算,因此为1000/120

setInterval( function, ms)    //其实和上面的很像,但是这个函数一般作为循环动画使用


第一步:画画


那作为我们的第一步就是画画了!

canvas的画布给我们提供了按照路径画画,因此上下文这个概念变得尤为重要,上下文就代表着上一步是什么,当你需要进行下一步操作的时候,浏览器就会看你的上一步是什么,再根据你上一步运动到的位置连线(可以是直线,可以是曲线,看你具体调用了什么函数),这边有可能形容的有点抽象,我们现在就尝试着画一条直线来解释一下吧!

context.beginPath()    //方法开始一条路径,或重置当前的路径

context.stroke()        //方法会实际地绘制出通过 moveTo() 和 lineTo() 方法定义的路径。默认颜色是黑色

moveTo(width, heigth)//移动到位置

看到这边还是很糊涂啊!什么鬼!这些是什么!你在逗我!

这么说大家就理解了!

把浏览器看作一个画家

画家在画一根线之后就需要先做准备,那就调用beginPath()方法,当作一定的准备之后,他需要移动到某一个位置开始下笔,就会调用moveTo方法,参数分别代表了坐标系的x轴和y轴,然后他画了一条直线到了某个位置,就是lineTo()方法,到这边之后,他发现自己肚子饿了,不想画了,就调用stroke()方法结束这一笔

以上就是画家画一条线的过程,怎么样,是不是形象了很多!


因此,画一条线就变成了:


context.beginPath();

context.moveTo(110, 110);

context.lineTo(190, 110);

context.stroke();


所以下面我们就可以完成三条线的绘制,怎么样,是不是很简单!

下一章介绍动画

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容