美文网首页后浪 · 正青春
使用canvas实现下雪的效果

使用canvas实现下雪的效果

作者: 乔一丁_2020强化班 | 来源:发表于2021-02-15 22:41 被阅读0次

    先上源码

    /* 用于绘制雪花的js文件 */
    var canvas = document.querySelector(".canvas");
    if(canvas.getContext){
        var ctx = canvas.getContext("2d");
    }else{
        /* 不支持canvas */console.log("no support");
    }
    var snow_img = new Image();
    var snows = [];//储存所有的雪花对象
    const snows_num = 50;//雪花数量的常量
    const swingY = 50;//摇摆幅度,决定在y轴上的摇摆幅度
    const swingX = 150;//摇摆幅度,决定在x轴上的摇摆幅度
    const speed = 1;//左右周期速度
    const fallSpeed = 1;//下坠速度
    
    
    snow_img.onload = function(){
        ctx.drawImage(snow_img,0,0,20,20);
    }
    snow_img.src= "img/snow.png";
    function makeSnow(snow)//构造雪花的方法,并且这个方法可以重构雪花对象
    {
        if(snow != undefined){
            snow.x = rnum(0,1600);
            snow.y = 0;
            snow.size = rnum(5,10)/10;
            snow.per = rnum(0,100);
            return;
        }
        /* 位置和大小,大小是倍数 */
        var ret = {
            x:0,y:0,
            size:1,
            dir:true,//动画行进的方向,true为正,false为反
            per:0,//动画的进度,0~100
        };
        ret.x = rnum(0,1600);
        ret.y = rnum(0,900);
        ret.size = rnum(5,10)/10;
        ret.per = rnum(0,100);
        return ret;
    }
    function rnum(start,end)//生成随机数的方法
    {   /* 包含开头,不包含结尾 */
        return start + Math.floor(Math.random()*(end-start));
    }
    function update(){
        ctx.clearRect(0,0,1600,900);
        for(snow of snows){
            snow.y += fallSpeed;
            if(snow.y >= 900){
                makeSnow(snow);
            }
            snow.per += speed;
            if(snow.per>100){
                snow.per -= 100;
                snow.dir = !snow.dir;
            }
            //因为雪花是往返下降,所以需要计算实际进度
            realPer = (snow.dir ? snow.per : 100 - snow.per)/100;
            ctx.drawImage(snow_img,snow.x + snow.size*(realPer - 0.5)*swingX
            ,snow.y - swingY*Math.pow(realPer,2) + swingY*realPer,
            40*snow.size,40*snow.size);
        }
    }
    function init()//初始化方法
    {
        for(var i = 0;i < snows_num;i++){
            snows.push(makeSnow());
        }
    }
    init();
    setInterval(update,10);
    

    首先,先介绍一下canvas。canvas是HTML5新加入的特性,通过document的方法获取到其元素对象后,可以使用专有方法来获取绘制的对象。专有方法指的是getContext。通过getContext("2d")来获取一个绘制对象。

    在此段代码开头用canvas.getContext来检测是否含有这个方法,从而确定浏览器是否支持canvas。

    获取到绘制对象后,其中提供了很多绘制的方法,此处仅讲解drawIamge这个主要使用的方法。
    drawIamge至少需要3个参数,分别是绘制的Iamge对象,以及xy轴上的位置。
    还有一种5个参数的方法,后面跟的是图片的宽高,绘制出的图片会被强制缩放成这两个值
    想要创建Iamge对象很简单,只需要new Iamge()之后对其src属性进行赋值,将图片的地址传入即可。

    注意!
    1.图片的装载是需要时间的,如果你在图片装载完成前对其使用,可能会什么也不发生,甚至报错。所以一般对Iamge对象的onload属性传入一个方法,当Iamge装载完成后,会调用此方法。
    2.画布的默认大小是300x150像素,如果仅对css属性进行修改,虽然的确可以改变其大小,但是实际上是将canvas进行放大得到的(所以实际上canvas与img是很相似的,甚至可以理解为可以自由绘制的img)所以要直接设定其宽高属性来决定canvas的实际宽高(通过对标签上的属性进行修改,例如<canvas height='200' width='200'>

    现在来介绍绘制相关的内容。首先,canvas的背景是透明的,你把这个元素放在其他元素之上,是不会遮盖底下的元素的(除非你绘制了背景,也就是填充了一个带有颜色的图形)。绘制的话直接使用drawIamge等其提供的方法即可。
    在画布上绘制完图形后,画布的上的内容是不会自动消除的,需要使用clearRect方法主动清除才行。这个方法接收4个参数,分别是开始清除的点的xy轴,以及结束点的xy轴。清除后的画布就会变成透明的。
    了解完以上内容基本就可以实现简单的下雪效果了。但是先要实现飘落的效果,还有更多需要考虑的,我就不多讲了,提示一下:二次函数。
    最后再说一点,如果把画布放在元素上面,但是你不想让画布阻挡鼠标事件,可以使用一个css属性:pointer-events:none。可以让指定元素不接收鼠标事件。

    相关文章

      网友评论

        本文标题:使用canvas实现下雪的效果

        本文链接:https://www.haomeiwen.com/subject/kpbpxltx.html