• canvas动画3:交互


    canvas动画3

    时隔很久,本人终于又写博客了(重度拖延症),把之前留下的canvas交互动画讲一讲。

    电脑上的交互,指的是鼠标和键盘,我们今天主要用的是鼠标。

    既然是鼠标的话,就要获取鼠标的各种事件,这次以mousemove做示例。

    我们先定义一个鼠标对象,然后添加mousemove事件:

    var mouse = {
        x: undefined,
        y: undefined
    }
    //这样的话控制台就会跟随我们的鼠标移动输出相应的坐标
    window.addEventListener("mousemove",function (event) {
        mouse.x = event.x;
        mouse.y = event.y;
        console.log(mouse);
    });
    

    我们声明一个初始化函数init(),用于把制造圆的过程封装:

    function init() {
        circleArray = []
        for (var i = 0; i < 800; i++) {
            var x = Math.random()*window.innerWidth;
            var y = Math.random()*window.innerHeight;
            var dx = (Math.random()-0.5)*2;
            var dy = (Math.random()-0.5)*2;
            var radius = Math.random()*3 +1;
            circleArray.push(new Circle(x, y, dx, dy, radius));
        }
    }
    init();
    

    这样的话,按照上一篇文章的做法,我们的canvas会出现一些问题。所以,需要给Circle对象update()里的属性都加上this

    function Circle(x, y, dx, dy, radius) {
        this.x = x;
        this.y = y;
        this.dx = dx;
        this.dy = dy;
        this.radius = radius;
    
        this.draw = function() {
            ctx.beginPath();
            ctx.strokeStyle = "#000";
            ctx.arc(this.x,this.y,this.radius,Math.PI/180*0,Math.PI/180*360,false);
            ctx.stroke();
            ctx.fill();
        }
        this.update = function() {
            //圆触碰边界时反弹,偏移值为负
            if (this.x + this.radius > innerWidth || this.x - this.radius < 0 ) {
                this.dx = -this.dx;
            }
            if (this.y + this.radius > innerHeight || this.y - this.radius < 0 ) {
                this.dy = -this.dy;
            }
            //刷新绘制时圆的偏移运动
            this.x += this.dx;
            this.y += this.dy;
            //根据更新的值进行绘制
            this.draw();
    
        }
    }
    

    接下来我们就要用mousemove于动画进行交互了,我们假定圆心在鼠标坐标周围50px以内的时候圆会增大,这段代码应该写在update()里:

    if (mouse.x - this.x < 50 && mouse.x - this.x >-50 && mouse.y - this.y < 50 && mouse.y - this.y >-50) {
        // if (this.radius < maxRadius) {
            this.radius += 1;
        // }
    }
    
    我们设置了10个圆,把鼠标移上去的时候会看到在控制范围内的圆会不断变大,不会停下来,所以我在前面就设置了一个圆半径的最大值,以免它一直增大,然后把注释的内容去掉,圆就不会无限增大了:

    但是有一个问题,圆放大了以后不会缩小,那么我们就让它在离开圆50px半径范围后缩小:

    if (mouse.x - this.x < 50 && mouse.x - this.x >-50 && mouse.y - this.y < 50 && mouse.y - this.y >-50) {
        if (this.radius < maxRadius) {
            this.radius += 1;
        }
    //其他的所有圆半径不断减小
    }else{
        this.radius -= 1;
    }
    

    这时候又有新问题产生了,画面一片空白,因为圆心不在鼠标固定范围内的圆全都变小了,甚至半径为负!显然简单的else是不成立的,还是得加个条件:

    if (mouse.x - this.x < 50 && mouse.x - this.x >-50 && mouse.y - this.y < 50 && mouse.y - this.y >-50) {
        if (this.radius < maxRadius) {
            this.radius += 1;
        }
    //其他的所有圆半径减小到最小值
    }else if (this.radius > this.minRadius) {
        this.radius -= 1;
    }
    

    这里出现了一个新值:minRadius,我加在了Circle对象里this.minRadius = radius;,以原本的初始值作为它的最小值。好了,现在基本效果已经成型了:

    接下来就是颜色的问题了,只要懂得canvas的基本api,修改颜色完全就是小儿科。我们设置一个数组,用于存放颜色值。

    var colorArray = [
        '#58D68D',
        '#E67F22',
        '#3598DB',
        '#E84C3D',
        '#9A59B5',
        '#27AE61',
        '#D25400',
        '#BEC3C7',
        '#297FB8'
    ]
    

    然后在Circle对象里加上一个bg属性:this.bg = colorArray[Math.floor(Math.random()*colorArray.length)];,再往Circle的绘制函数添上一句ctx.fillStyle = this.bg;,然后ctx.fill();,多彩运动的圆圈canvas就做完了。

    这是一个运用mousemove事件做的canvas交互动画,有兴趣的可以尝试其他事件(制作游戏用的键盘事件以及其他鼠标事件),或者思考如何给球加重力,如何检测碰撞事件,canvas的世界并不只有这么一点,相关资料的话,给大家推荐本书《canvas开发详解》。

    本文的最终js代码如下:

    /**
     * 
     * @authors dkplus (dkplus@qq.com)
     * @date    2017-10-01 20:37:26
     * @version $1.0$
     */
    /**
     * 获取canvas对象,设置宽度高度自适应
     * @type {[type]}
     */
    var canvas = document.querySelector("#canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    
    var ctx = canvas.getContext("2d");
    /**
     * 屏幕鼠标坐标
     * @type {Object}
     */
    var mouse = {
        x: undefined,
        y: undefined
    }
    /**
     * @param  {鼠标移动事件,回调函数,赋值给鼠标坐标}
     * @return {[type]}
     */
    window.addEventListener("mousemove",function (event) {
        mouse.x = event.x;
        mouse.y = event.y;
        // console.log(mouse);
    });
    /**
     * @param  {重新设置窗口大小,使canvas宽高自适应屏幕}
     * @return {[type]}
     */
    window.addEventListener("resize",function () {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        //初始化canvas
        init();
    })
    //绘制圆的最大半径
    var maxRadius = 40;
    // var minRadius = 2;
    
    //圆的颜色数组
    var colorArray = [
        '#58D68D',
        '#E67F22',
        '#3598DB',
        '#E84C3D',
        '#9A59B5',
        '#27AE61',
        '#D25400',
        '#BEC3C7',
        '#297FB8'
    ]
    /**
     * @param {x圆中心的x坐标}
     * @param {y圆中心的y坐标}
     * @param {dx圆运动的x偏移量}
     * @param {dy圆运动的y偏移量}
     * @param {radius圆的半径}
     * minRadius圆的最小半径
     * bg圆的背景颜色
     * draw绘制函数
     * update圆运动偏移
     */
    function Circle(x, y, dx, dy, radius) {
        this.x = x;
        this.y = y;
        this.dx = dx;
        this.dy = dy;
        this.radius = radius;
        this.minRadius = radius;
        this.bg = colorArray[Math.floor(Math.random()*colorArray.length)];
    
        this.draw = function() {
            ctx.beginPath();
            ctx.strokeStyle = "#777";
            ctx.fillStyle = this.bg;
            ctx.arc(this.x,this.y,this.radius,Math.PI/180*0,Math.PI/180*360,false);
            // ctx.stroke();
            ctx.fill();
        }
        this.update = function() {
            //圆触碰边界时反弹,偏移值为负
            if (this.x + this.radius > innerWidth || this.x - this.radius < 0 ) {
                this.dx = -this.dx;
            }
            if (this.y + this.radius > innerHeight || this.y - this.radius < 0 ) {
                this.dy = -this.dy;
            }
            //刷新绘制时圆的偏移运动
            this.x += this.dx;
            this.y += this.dy;
            //鼠标半径50像素范围内的圆,它们的半径逐步增加到最大值
            if (mouse.x - this.x < 50 && mouse.x - this.x >-50 && mouse.y - this.y < 50 && mouse.y - this.y >-50) {
                if (this.radius < maxRadius) {
                    this.radius += 1;
                }
            //其他的所有圆半径减小到最小值
            }else if (this.radius > this.minRadius) {
                this.radius -= 1;
            }
            //根据更新的值进行绘制
            this.draw();
    
        }
    }
    //圆的对象数组
    var circleArray = [];
    /**
     * 初始化函数,制造800个随机坐标、偏移速度和半径的圆,加入到对象数组
     * @return {[type]}
     */
    function init() {
        circleArray = []
        for (var i = 0; i < 800; i++) {
            var x = Math.random()*window.innerWidth;
            var y = Math.random()*window.innerHeight;
            var dx = (Math.random()-0.5)*2;
            var dy = (Math.random()-0.5)*2;
            var radius = Math.random()*3 +1;
            circleArray.push(new Circle(x, y, dx, dy, radius));
        }
    }
    init();
    /**
     * 动画函数
     * @return {[type]}
     */
    function animate() {
        //更新前清楚画布
        ctx.clearRect(0,0,window.innerWidth,window.innerHeight);
        requestAnimationFrame(animate);
        //每个圆都调用update()方法
        for (var i = 0; i < circleArray.length; i++) {
            circleArray[i].update();
        }
    
    }
    animate();
    
  • 相关阅读:
    excel使用总结
    使用spring的@Scheduled注解执行定时任务,启动项目不输出警告
    web.xml配置错误导致applicationContext.xml配置重复加载
    POI3.8解决导出大数据量excel文件时内存溢出的问题
    linux常用命令总结
    javax.mail 发送邮件异常
    eclipse下创建maven项目
    java单例模式的几种写法比较
    msql数据迁移,myisam及innoDB
    JS监听回车事件
  • 原文地址:https://www.cnblogs.com/dkplus/p/7887482.html
Copyright © 2020-2023  润新知