炫酷的canvas

最近做的项目里面有涉及到canvas,虽然之前有学习过canvas,不过好久没使用,慢慢有些生疏了。下面就来说说canvas的一些基本功能,以及最后完成的一个炫酷小demo,虽然难度不大,不过比较有趣,既熟悉了canvas,又得到了很多乐趣,何乐而不为呢。

首先我们需要在html里面写一对canvas标签,id为canvas

<canvas id="canvas" style="display:block;margin:50px auto;">
    当前浏览器不支持Canvas,请更换浏览器再打开
</canvas>
canvas标签内的文字,在支持canvas画布的浏览器中不会显示,如果浏览器不支持canvas,就会做出简单的提示,当然我们也可以在js中进行判断。另外,canvas的宽和高最好不要在css中进行设置,可以写成内联样式,也可以在js中进行定义,这里我们在js中定义。

有了canvas标签,我们就可以在js中获取canvas和context对象了,代码如下

var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
这样我们就可以通过context对象,在canvas画布上进行图像绘制了。

下面来说说我们的炫酷小demo,是一个通过canvas绘制的小球组成的倒计时时钟,还有一些动画效果

首先我们创建一个名为click.js的文件,在html先引入click.js文件,该文件为一个三维数组,用一个数组来存放几个二维数字矩阵,这几个矩阵对应数字0到9,还有一个冒号,如下

//绘制数字的三维数组矩阵,
var digit=[
    [
        [0,0,1,1,1,0,0],
        [0,1,1,0,1,1,0],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [0,1,1,0,1,1,0],
        [0,0,1,1,1,0,0]
    ],//0的二维数组点阵
    [
        [0,0,0,1,1,0,0],
        [0,1,1,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [1,1,1,1,1,1,1]
    ],//1
    [
        [0,1,1,1,1,1,0],
        [1,1,0,0,0,1,1],
        [0,0,0,0,0,1,1],
        [0,0,0,0,1,1,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,1,1,0,0,0],
        [0,1,1,0,0,0,0],
        [1,1,0,0,0,1,1],
        [1,1,1,1,1,1,1]
    ],//2
    [
        [1,1,1,1,1,1,1],
        [0,0,0,0,0,1,1],
        [0,0,0,0,1,1,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,0,0,1,1,0],
        [0,0,0,0,0,1,1],
        [0,0,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [0,1,1,1,1,1,0]
    ],//3
    [
        [0,0,0,0,1,1,0],
        [0,0,0,1,1,1,0],
        [0,0,1,1,1,1,0],
        [0,1,1,0,1,1,0],
        [1,1,0,0,1,1,0],
        [1,1,1,1,1,1,1],
        [0,0,0,0,1,1,0],
        [0,0,0,0,1,1,0],
        [0,0,0,0,1,1,0],
        [0,0,0,1,1,1,1]
    ],//4
    [
        [1,1,1,1,1,1,1],
        [1,1,0,0,0,0,0],
        [1,1,0,0,0,0,0],
        [1,1,1,1,1,1,0],
        [0,0,0,0,0,1,1],
        [0,0,0,0,0,1,1],
        [0,0,0,0,0,1,1],
        [0,0,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [0,1,1,1,1,1,0]
    ],//5
    [
        [0,0,0,0,1,1,0],
        [0,0,1,1,0,0,0],
        [0,1,1,0,0,0,0],
        [1,1,0,0,0,0,0],
        [1,1,0,1,1,1,0],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [0,1,1,1,1,1,0]
    ],//6
    [
        [1,1,1,1,1,1,1],
        [1,1,0,0,0,1,1],
        [0,0,0,0,1,1,0],
        [0,0,0,0,1,1,0],
        [0,0,0,1,1,0,0],
        [0,0,0,1,1,0,0],
        [0,0,1,1,0,0,0],
        [0,0,1,1,0,0,0],
        [0,0,1,1,0,0,0],
        [0,0,1,1,0,0,0]
    ],//7
    [
        [0,1,1,1,1,1,0],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [0,1,1,1,1,1,0],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [0,1,1,1,1,1,0]
    ],//8
    [
        [0,1,1,1,1,1,0],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [1,1,0,0,0,1,1],
        [0,1,1,1,0,1,1],
        [0,0,0,0,0,1,1],
        [0,0,0,0,0,1,1],
        [0,0,0,0,1,1,0],
        [0,0,0,1,1,0,0],
        [0,1,1,0,0,0,0]
    ],//9
    [
        [0,0,0,0],
        [0,0,0,0],
        [0,1,1,0],
        [0,1,1,0],
        [0,0,0,0],
        [0,0,0,0],
        [0,1,1,0],
        [0,1,1,0],
        [0,0,0,0],
        [0,0,0,0]
    ]//:
];

有了这个数组,我们就可以用canvas绘制时钟了,首先定义一些变量及常量,绘制小球的时候会用到

var WINDOW_WIDTH=1024;    //画布的宽度
var WINDOW_HEIGHT=600;    //画布的高度
var RADIUS=8;             //小球的半径
var MARGIN_TOP=60;        //每一个数字距离画布顶端的距离
var MARGIN_LEFT=30;       //第一个数字距离画布左边距的距离                                                                                                            
const endTime=new Date(2016,7,4,15,30,00);    //倒计时的截止时间
var curShowTimeSeconds=0;  //当前显示的秒数
定义完这些量以后,我们就可以开始写主题函数了

window.onload=function(){
    var canvas=document.getElementById("canvas");
    var context=canvas.getContext("2d");

    canvas.width=WINDOW_WIDTH;
    canvas.height=WINDOW_WIDTH;
    curShowTimeSeconds=getCurrentShowTimeSeconds();
    setInterval(function(){
        render(context);
        update();
    },50)
}
其中,getCurrentShowTimeSeconds()函数用来获取当前显示的秒数,render()为负责绘制小球的函数,update()为更新显示的函数,每次改变小球位置重新绘制好后,还要更新显示才可以。

function getCurrentShowTimeSeconds(){
    var curTime=new Date();
    var ret=endTime.getTime()-curTime.getTime();   //设定的截止时间与当前时间的毫秒数差值
    ret=Math.round(ret/1000);
    return ret>=0?ret:0;
}
function update(){
    //更新显示的时间,产生时间变化的动画
    var nextShowTimeSeconds=getCurrentShowTimeSeconds();
    var nextHours=parseInt(nextShowTimeSeconds/3600);
    var nextMinutes=parseInt((nextShowTimeSeconds-nextHours*3600)/60);
    var nextSeconds=nextShowTimeSeconds%60;

    var curHours=parseInt(curShowTimeSeconds/3600);
    var curMinutes=parseInt((curShowTimeSeconds-curHours*3600)/60);
    var curSeconds=curShowTimeSeconds%60;
    //只比较秒即可,因为每50毫秒就比较一次
    if(nextSeconds!=curSeconds){
        curShowTimeSeconds=nextShowTimeSeconds;
    }
}
function render(cxt){
    //每一次更新画面,都要先清除画布,否则会叠加
    cxt.clearRect(0,0,WINDOW_WIDTH,WINDOW_HEIGHT);
    var hours=parseInt(curShowTimeSeconds/3600);
    var minutes=parseInt((curShowTimeSeconds-hours*3600)/60);
    var seconds=curShowTimeSeconds%60;
    //绘制数字的函数
    renderDigit(MARGIN_LEFT,MARGIN_TOP,parseInt(hours/10),cxt);                          //绘制小时得第一个数字
    renderDigit(MARGIN_LEFT+15*(RADIUS+1),MARGIN_TOP,parseInt(hours%10),cxt);            //绘制小时的第二个数字,14*(RADIUS+1)为一个数字的宽度
    renderDigit(MARGIN_LEFT+30*(RADIUS+1),MARGIN_TOP,10,cxt);                            //绘制冒号
    renderDigit(MARGIN_LEFT+39*(RADIUS+1),MARGIN_TOP,parseInt(minutes/10),cxt);          //绘制分钟的第一个数字
    renderDigit(MARGIN_LEFT+54*(RADIUS+1),MARGIN_TOP,parseInt(minutes%10),cxt);          //绘制分钟的第二个数字
    renderDigit(MARGIN_LEFT+69*(RADIUS+1),MARGIN_TOP,10,cxt);                            //绘制冒号
    renderDigit(MARGIN_LEFT+78*(RADIUS+1),MARGIN_TOP,parseInt(seconds/10),cxt);          //绘制秒钟的第一个数字
    renderDigit(MARGIN_LEFT+93*(RADIUS+1),MARGIN_TOP,parseInt(seconds%10),cxt);         //绘制秒钟的第二个数字
}
在上面的render()函数中,又用到了renderDigit()方法,这个方法负责绘制一个数字或者冒号,需要传入四个参数,第一个参数为绘制起点的x坐标,第二个参数为y坐标,第三个参数为要绘制的图形,0到9代表各自的数字,10代表冒号。第四个参数为context对象,renderDigit()函数如下:

function renderDigit(x,y,num,cxt){
    cxt.fillStyle="rgb(0,102,153)";
    //两重循环遍历二位数组,值为1的地方就绘制一个圆形
    for(var i=0;i<digit[num].length;i++){
        for(var j=0;j<digit[num][i].length;j++){
            if(digit[num][i][j]==1){
                cxt.beginPath();
                cxt.arc(x+j*2*(RADIUS+1)+(RADIUS+1),y+i*2*(RADIUS+1)+(RADIUS+1),RADIUS,0,2*Math.PI);
                cxt.closePath();
                cxt.fill();
            }
        }
    }
}
至此我们就完成了用canvas绘制一个简单倒计时时钟的逻辑,只需将上述代码放在一起即可,完成后的效果如下图




js代码 [removed] ;(function() { 'use strict'; var c = document.getElementById('c'); var ctx = c.getContext('2d'); var w = c.width = window.innerWidth; var h = c.height = window.innerHeight; var cx = w / 2; var cy = h / 2; var fl = 1000; function prj(obj) { var cz = obj.z fl; if(cz === 0) return; var scl = fl / cz; obj.p.x = cx obj.x * scl; obj.p.y = cy obj.y * scl; obj.s = scl; } var P = function(x, y, z) { this.x = x; this.y = y; this.z = z; this.s = 1; this.cl = 0; this.p = { x: 0, y: 0 }; }; P.prototype = { constructor: P, update: function() { this.z -= 30; }, render: function(ctx) { if(this.z <= -fl) return; ctx.save(); ctx.translate(this.p.x, this.p.y); ctx.scale(this.s, this.s); ctx.fillStyle = 'hsla(' this.cl ', 100%, 50%, 0.5)'; ctx.beginPath(); ctx.arc(0, 0, 2, 0, Math.PI * 2); ctx.fill(); ctx.restore(); } }; var M = function(x, y, z) { this.list = []; this.max = 100; this.x = x; this.y = y; this.z = z; this.s = 1; this.p = { x: 0, y: 0 }; this.ax = Math.random() * (Math.PI * 2); this.ay = Math.random() * (Math.PI * 2); this.rx = Math.random() * 100; this.ry = Math.random() * 100; this.cl = Math.random() * 360; this.cls = Math.random(); }; M.prototype = { constructor: M, update: function() { this.cl = this.cls; this.ax = Math.random() * 0.1 - 0.02; this.ay = Math.random() * 0.1 - 0.02; this.x = Math.cos(this.ax) * 100; this.y = Math.sin(this.ay) * 100; this.z = 10; if(this.z > fl) this.z = fl; if(this.list.length < this.max) { if(Math.random() * 100 < 50) { var pp = new P(this.x, this.y, this.z); pp.cl = this.cl; this.list.push(pp); } } else { var pp = this.list.shift(); pp.x = this.x; pp.y = this.y; pp.z = this.z; pp.cl = this.cl; this.list.push(pp); } }, render: function(ctx) { if(this.z <= -fl) return; ctx.save(); ctx.translate(this.p.x, this.p.y); ctx.fillStyle = 'green'; ctx.beginPath(); ctx.arc(0, 0, 2, 0, Math.PI * 2); ctx.fill(); ctx.restore(); } }; function update(mv, list) { for(var i = 0; i < list.length; i ) { var p = list[i]; p.update(); prj(p); p.render(ctx); } for(var i = list.length-1; i >= 0; i--) { var p = list[i]; if(p.z <= -fl) continue; if(i === list.length - 1) { ctx.lineWidth = Math.random(); ctx.strokeStyle = 'hsl(' mv.cl ', 100%, 50%)'; ctx.beginPath(); ctx.moveTo(p.p.x, p.p.y); } else { ctx.lineTo(p.p.x, p.p.y); } } ctx.stroke(); } var ms = []; for(var i = 0; i < 10; i ) { ms.push(new M( Math.random() * 400 - 200, Math.random() * 400 - 200, Math.random() * 400 - 200)); } requestAnimationFrame(function loop() { requestAnimationFrame(loop); ctx.clearRect(0, 0, w, h); for(var i = 0; i < ms.length; i ) { var m = ms[i]; m.update(); prj(m); update(m, m.list); } }); })(); [removed] 这是一款基于HTML5 Canvas绘制的炫酷3D线条延伸动画特效,多彩颜色变幻,非常漂亮!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值