资讯专栏INFORMATION COLUMN

好看漂亮的html5网页特效学习笔记(4)_canvas实现火焰跟随鼠标

SwordFly / 1735人阅读

摘要:好看漂亮的网页特效学习笔记猜猜下一个颜色是什么分步详细解释第一步很简单的初始化函数。绘制新的火焰红色的圆以及火花之前元素,即新的火焰红色的圆以及火花的生命周期未完的话,就继续更新它,否则就删除它第五步以火焰为粒子。

效果:

逼真的火焰跟随鼠标,还冒出火花,照亮背景文字

使用canvas绘制

使用javascript,但并无复杂逻辑。上手程度:简单

欢迎来我的博客看此文章: https://clatterrr.com/archive...

源码:

演示地址:https://clatterrr.github.io/f...

源码已在下方给出,或者访问github代码仓库https://github.com/clatterrr/...

学习笔记: google字体

在上一篇中已讲过。好看漂亮的html5网页特效学习笔记(3)_猜猜下一个颜色是什么?
javascript分步详细解释

第一步:

很简单的初始化函数。

var oCanvas;
init = function()
{
 
    oCanvas = new Fire();
    oCanvas.run();
}
window.onload = init;
第二步:

初始化canvas,定义各种基础的东西,以及为鼠标添加事件监测。addEventListener第三个参数的意思是,若为false,则为事件处理顺序为先进先处理,为true则为先进后处理。具体请看https://www.runoob.com/jsref/...

    var Fire  = function(){
 
    this.canvas         = document.getElementById("fire");
    this.ctx             = this.canvas.getContext("2d");
    this.canvas.height     = window.innerHeight;
    this.canvas.width     = window.innerWidth;
 
    this.aFires         = [];
    this.aSpark         = [];
    this.aSpark2         = [];
 
    this.mouse = {
        x : this.canvas.width * .5,
        y : this.canvas.height * .75,
    }
    //一旦鼠标移动,就更新this.mouse.x和this.mouse.y,因为设置了false,所以先进来的事件先处理
    this.canvas.addEventListener("mousemove", this.updateMouse.bind( this ), false);
}
Fire.prototype.updateMouse = function( e ){
    this.mouse.x = e.clientX;
    this.mouse.y = e.clientY;
}
第三步:

使用requestAnimationFrame使下一帧重新运行一遍run函数。为什么不用setInterval呢?因为内在运行机制会让它运行速度随机器性能变化而变化,导致时间控制不精确。而requestAnimationFrame使用系统时间,保证每秒执行60次。参考:https://www.cnblogs.com/xiaoh...

并用bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。参考:https://developer.mozilla.org...

Fire.prototype.run = function(){
    //重新新绘制火焰和火花
    this.update();
    this.draw();
    //稳定重绘画面
    requestAnimationFrame( this.run.bind( this ) );
}
第四步:

重新绘制一个火焰(实际上是红色的圆)和两个火花(实际上是小长方形)。若有火焰或火花的生命周期完了,那么就用删除它。否则继续更新它。
注意火焰火花原本被存储在数组里,所以删除用slice就好了。

Fire.prototype.update = function(){
 
    //绘制新的火焰(红色的圆)以及火花
    this.aFires.push( new Flame( this.mouse ) );
    this.aSpark.push( new Spark( this.mouse ) );
    this.aSpark2.push( new Spark( this.mouse ) );
   //之前元素,即新的火焰(红色的圆)以及火花的生命周期未完的话,就继续更新它,否则就删除它
    for (var i = this.aFires.length - 1; i >= 0; i--) {
        if( this.aFires[i].alive )
            this.aFires[i].update();
        else
            this.aFires.splice( i, 1 );
    }
    for (var i = this.aSpark.length - 1; i >= 0; i--) {
        if( this.aSpark[i].alive )
            this.aSpark[i].update();
        else
            this.aSpark.splice( i, 1 );
    }
    for (var i = this.aSpark2.length - 1; i >= 0; i--) {
        if( this.aSpark2[i].alive )
            this.aSpark2[i].update();
        else
            this.aSpark2.splice( i, 1 );
    }
}
第五步:

以火焰为粒子。部分注释在代码中。先使用构造函数确定火焰的各项参数。若火焰被更新,那么就更新它的坐标,生命周期,以及用生命周期计算颜色。这里的颜色使用的是HSLA颜色,参考:http://caibaojian.com/css3/va...。
火花的构造参数和更新参数也是一样的。

var Flame = function( mouse ){
 
    //鼠标坐标
    this.cx = mouse.x;
    this.cy = mouse.y;
    
    //随机在鼠标周围产生
    this.x = rand( this.cx - 25, this.cx + 25);
    this.y = rand( this.cy - 5, this.cy + 5);
    
    //随机变量,横轴纵轴以及半径的变化
    this.vy = rand( 1, 3 );
    this.vx = rand( -1, 1 );
    this.r = rand( 20, 30 );
    
    //生命周期
    this.life = rand( 3, 6 );
    this.alive = true;
    //用于绘制火焰颜色
    this.c = {
        h : Math.floor( rand( 2, 40) ),
        s : 100,
        l : rand( 80, 100 ),
        a : 0,
        ta : rand( 0.8, 0.9 )
    }
}
 
Flame.prototype.update = function()
{
    //y坐标变化
    this.y -= this.vy;
    this.vy += 0.05;
   
    //x坐标变化
    this.x += this.vx;
    if( this.x < this.cx )
        this.vx += 0.1;
    else
        this.vx -= 0.1;
    
    //半径变化
    if(  this.r > 0 )
        this.r -= 0.1;
    if(  this.r <= 0 )
        this.r = 0;
 
 
    //计算生命周期,根据生命周期计算火焰颜色
    this.life -= 0.15;
    if( this.life <= 0 ){
        this.c.a -= 0.05;
        if( this.c.a <= 0 )
            this.alive = false;
    }else if( this.life > 0 && this.c.a < this.c.ta ){
        this.c.a += .08;
    }
 
}
第六步:

canvas的主场,绘制背景,包括黑色背景,文字FIRE,以及一个跟随在火焰后的暗红色大圆。这个大圆大圆,更像是墙壁的上的投影,需要仔细一点才能发现。canvas参考https://www.w3school.com.cn/t...,自己一个函数一个函数慢慢去查才能加深印象。
注意globalCompositeOperation的参数soft-light和color-dodge似乎国内网站都没找到解释,只在英文mdn上看到了样例。参考:
https://developer.mozilla.org...

Fire.prototype.draw = function(){
 
    //绘制背景
    this.ctx.globalCompositeOperation = "source-over";
    this.ctx.fillStyle = "rgba( 15, 5, 2, 1 )";
    this.ctx.fillRect( 0, 0, window.innerWidth, window.innerHeight );
    
    //定义渐变颜色样式
    this.grd = this.ctx.createRadialGradient( this.mouse.x, this.mouse.y - 200,200,this.mouse.x, this.mouse.y - 100,0 );
    this.grd.addColorStop(0,"rgb( 15, 5, 2 )");
    this.grd.addColorStop(1,"rgb( 30, 10, 2 )");
    
    //绘制一个圆形,并使用颜色渐变样式。这个圆是一个暗红色的大圆
    //跟随在火焰后的大圆,更像是墙壁的上的投影,需要仔细一点才能发现
    this.ctx.beginPath();
    this.ctx.arc( this.mouse.x, this.mouse.y - 100, 200, 0, 2*Math.PI );
    this.ctx.fillStyle= this.grd;
    this.ctx.fill();
    
    //绘制文字Fire
    this.ctx.font = "15em Amatic SC";
    this.ctx.textAlign = "center";
    this.ctx.strokeStyle = "rgb(50, 20, 0)";
    this.ctx.fillStyle = "rgb(120, 10, 0)";
    this.ctx.lineWidth = 2;
    this.ctx.strokeText("Fire",this.canvas.width/2, this.canvas.height * .72 );
    this.ctx.fillText("Fire",this.canvas.width/2, this.canvas.height * .72 );    
    
    //绘制火焰
    this.ctx.globalCompositeOperation = "overlay";
    for (var i = this.aFires.length - 1; i >= 0; i--)this.aFires[i].draw( this.ctx );
    
    //绘制粒子
    this.ctx.globalCompositeOperation = "soft-light";
    for (var i = this.aSpark.length - 1; i >= 0; i--)
    if( ( i % 2 ) === 0 )
            this.aSpark[i].draw( this.ctx );
 
    //绘制粒子2
    this.ctx.globalCompositeOperation = "color-dodge";
    for (var i = this.aSpark2.length - 1; i >= 0; i--) this.aSpark2[i].draw( this.ctx );
}
最后一步:

最关键但也很简单的地方,就是真正的绘制火焰和火花啦。beginpath(),arc(),fillstyle()和fill()都是canvas的方法。慢慢查找资料吧。只是注意这儿的颜色用的是hsla颜色而不是rgba颜色哦。

 
Flame.prototype.draw = function( ctx ){
 
    ctx.beginPath();
    ctx.arc( this.x, this.y, this.r * 3, 0, 2*Math.PI );
    ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a/20) + ")";
    ctx.fill();
 
    ctx.beginPath();
    ctx.arc( this.x, this.y, this.r, 0, 2*Math.PI );
    ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
    ctx.fill();
 
}
完整源码:




Canvas实现火焰跟随鼠标动画
 

 


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/116336.html

相关文章

  • 好看漂亮html5网页特效学习笔记(1)_水墨动画

    摘要:对于来说,表示元素,除了优先级更高之外,与选择器相同。从父元素继承颜色渐变背景漂亮的深蓝浅蓝效果就是这个的作用。媒体查询,简单来说就是可以让网页自动适应不同的设备屏幕尺寸。具体请看贝塞尔曲线,用来生成水墨效果的关键。 showImg(https://segmentfault.com/img/bVbwNaj); 效果 鼠标触碰按钮,出现水墨风格动画 屏幕自适应 一份html文件,一份c...

    habren 评论0 收藏0
  • 好看漂亮html5网页特效学习笔记(1)_水墨动画

    摘要:对于来说,表示元素,除了优先级更高之外,与选择器相同。从父元素继承颜色渐变背景漂亮的深蓝浅蓝效果就是这个的作用。媒体查询,简单来说就是可以让网页自动适应不同的设备屏幕尺寸。具体请看贝塞尔曲线,用来生成水墨效果的关键。 showImg(https://segmentfault.com/img/bVbwNaj); 效果 鼠标触碰按钮,出现水墨风格动画 屏幕自适应 一份html文件,一份c...

    Null 评论0 收藏0
  • 好看漂亮html5网页特效学习笔记(5)_弧形菜单

    摘要:定义标准的文本。然后看看函数的定义自启动来按下按钮的时差不能超过最大持续时间重新绘制菜单项的位置先用确定按下按钮的时间,储存在中。如果到了规定时间的话,就执行。然后再把取下的第一个当成第十三个接在最后面,又成了新的菜单排列。 showImg(https://segmentfault.com/img/bVbw1zV?w=818&h=479); 效果: 弧形菜单,文字按规则变形以及变换透...

    Guakin_Huang 评论0 收藏0
  • 好看漂亮html5网页特效学习笔记(2)_svg实现不同投票不同表情

    摘要:表情绘制使用纯代码绘制。其它表情请看源代码。当评分改变,这个高度很大的元素就向上移动,把需要的表情显示出来。源码不同投票不同表情 showImg(https://segmentfault.com/img/bVbwOQe?w=254&h=198); 特点: 根据不同评分显示不同表情,并且这些表情看起来像是在一个传送带上可以滚动 使用纯代码(svg)绘制表情以及用于评分的星星 html+...

    BaronZhang 评论0 收藏0
  • 好看漂亮html5网页特效学习笔记(2)_svg实现不同投票不同表情

    摘要:表情绘制使用纯代码绘制。其它表情请看源代码。当评分改变,这个高度很大的元素就向上移动,把需要的表情显示出来。源码不同投票不同表情 showImg(https://segmentfault.com/img/bVbwOQe?w=254&h=198); 特点: 根据不同评分显示不同表情,并且这些表情看起来像是在一个传送带上可以滚动 使用纯代码(svg)绘制表情以及用于评分的星星 html+...

    yankeys 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<