zoukankan      html  css  js  c++  java
  • 用canvas给自己的博客园加背景(二)

    canvas入门(二)

    前一篇大概介绍了canvas绘图的一些基础API,本文来介绍动画的部分,canvas最关键的函数是requestAnimationFrame(callback)

    注:本文面向canvas入门人员,写的如有纰漏请指出,不喜勿喷。

    requestAnimationFrame(callback)

    这是一个用于制作逐帧动画的函数,在它出现之前,我们的动画基本用setTimeout或者setInterval制作。

    我们可以尝试声明一个animate函数:

    //这个函数会在控制台无限输出"dkplus-canvas"
    (function animate() {
        requestAnimationFrame(animate);
        console.log("dkplus-canvas");
    })();
    

    此时打开控制台看一下效果。

    可以看到animate()里面的操作在无限执行,而我们用canvas绘制动画也可以选择这样的思路,无限刷新画布,无限绘制画布。

        ctx.arc(100,100,40,0,Math.PI*2,false);
        ctx.stroke();
    (function animate() {
        requestAnimationFrame(animate);
        //在同一个坐标无限循环画一个圆
        //重新定义开始坐标,试着注释掉这一行看看效果有何不同
        ctx.beginPath();
        ctx.arc(100,100,40,0,Math.PI*2,false);
        ctx.stroke();
    })();
    

    这段代码画出来的圆和只画一次的圆是有区别的,明显很多个圆叠加在一起了。

    我们试着改一改代码:

    //初始化坐标
    var x = 100;
    var y = 100;
    (function animate() {
        requestAnimationFrame(animate);
        //重新定义开始坐标,试着注释掉这一行看看效果有何不同
        ctx.beginPath();
        ctx.arc(x,y,40,0,Math.PI*2,false);
        ctx.stroke();
        //动态修改坐标
        x += 1;
        y += 1;
    })();
    

    刷新画布

    可以看到,这个图确实是动起来了,但是前面的图像没有被清除,而是简单的图像覆盖。所以我们要在每次绘图之前先清楚画布,使用clearRect()这个函数(可以说是canvas的橡皮擦)。

    和fillRect(),strokeRect()参数一样,clearRect(x坐标,y坐标,宽度,高度):

    var x = 100;
    var y = 100;
    (function animate() {
        requestAnimationFrame(animate);
        //这是我们加入的橡皮擦函数
        ctx.clearRect(0,0,innerWidth,innerHeight);
        ctx.beginPath();
        ctx.arc(x,y,40,0,Math.PI*2,false);
        ctx.stroke();
        x += 1;
        y += 1;
    })();
    

    保存打开浏览器,效果确实不一样了,看到的是一个圆圈在运动。

    反弹条件

    但是这个圆圈只会斜向下走,我们得做一些判断,让它反弹回来。比如说当圆心+半径超出浏览器边界时,我们把x+=1变为x+= -1。这里的1其实代表着速度,我们可以把速度储存到一个变量里,方便修改。

    //我把参数都设为变量
    var x = 100;
    var y = 100;
    var dx = 6;
    var dy = 6;
    var radius = 40;
    (function animate() {
        requestAnimationFrame(animate);
        ctx.clearRect(0,0,innerWidth,innerHeight);
        ctx.beginPath();
        ctx.arc(x,y,radius,0,Math.PI*2,false);
        ctx.stroke();
        //当触及边界时进行反弹
        if (x+radius>innerWidth || x-radius<0) {
            dx = -dx;
        }
        if (y+radius>innerHeight || y-radius<0) {
            dy = -dy;
        }
        x += dx;
        y += dy;
    })();
    

    既然都设了变量,为何不让变量变起来呢?设为随机数可好?

    //半径暂且不设随机,以后有用
    var x = Math.random()*innerWidth;
    var y = Math.random()*innerHeight;
    var dx = Math.random()*5;
    var dy = Math.random()*5;
    var radius = Math.random()*40;
    })();
    

    面向对象

    本人对面向对象这块不太熟,可能说的不太好请见谅

    好,现在我们声明一个function为Circle,假装我们有一个Circle类,把这些变量传进去,同时把我们刚才用于绘图的、用于刷新的代码都填进去。

    var x = Math.random()*innerWidth;
    var y = Math.random()*innerHeight;
    var dx = Math.random()*5;
    var dy = Math.random()*5;
    var radius = 40;
    //这是一个Circle对象
    function Circle(x,y,dx,dy,radius) {
        this.x = x;
        this.y = y;
        this.dx = dx;
        this.dy = dy;
        this.raidus = radius;
        //这是绘制方法
        this.draw = function () {
            ctx.beginPath();
            ctx.arc(x,y,radius,0,Math.PI*2,false);
            ctx.stroke();
        }
        //这是刷新方法
        this.update = function () {
            if (x+radius>innerWidth || x-radius<0) {
                dx = -dx;
            }
            if (y+radius>innerHeight || y-radius<0) {
                dy = -dy;
            }
            x += dx;
            y += dy;
            //每刷新一次重新绘图
            this.draw();
        }
    }
    //new一个Circle对象
    var c = new Circle(x,y,dx,dy,radius);
    function animate() {
        requestAnimationFrame(animate);
        ctx.clearRect(0,0,innerWidth,innerHeight);
        //对象c调用刷新方法
        c.update();
    };
    animate();
    

    多圆

    现在我们已经实现了一个圆在画布上的弹跳,那么我们要怎么实现很多圆弹跳呢?

    我们可以用for循环,循环随机参数,循环制造圆,循环刷新不同的圆。那么我们先引进一个圆的数组,一切都是为了方便操作:

    //圆的数组
    var cirleArray = [];
    //循环制造不同的圆,放进数组
    for (var i = 0; i < 100; i++) {
        var x = Math.random()*innerWidth;
        var y = Math.random()*innerHeight;
        var dx = Math.random()*5;
        var dy = Math.random()*5;
        var radius = 40;
        cirleArray.push(new Circle(x,y,dx,dy,radius));
    }
    function animate() {
        requestAnimationFrame(animate);
        ctx.clearRect(0,0,innerWidth,innerHeight);
        //循环刷新不同的圆
        for (var i = 0; i < cirleArray.length; i++) {
            cirleArray[i].update();
        }
    };
    animate();
    

    这篇就介绍到这里,大家有兴趣可以试试,下一篇我们讲怎么用canvas进行交互。

  • 相关阅读:
    节点树状图
    获取元素的方法
    Client Scroll Offset
    函数封装
    js和jq文档操作
    HashSet与HashMap的区别
    java中Map及Map.Entry详解
    SpringBoot教程(学习资源)
    java线程同步以及对象锁和类锁解析(多线程synchronized关键字)
    vue路由监听和参数监听
  • 原文地址:https://www.cnblogs.com/dkplus/p/7625511.html
Copyright © 2011-2022 走看看