还是老样子,先啰嗦一点前言。

最近各种事务缠身,所以也就隔了比较长的时间才开始码这篇文。希望不会这么快就过气。

好了,接下来就开始码代码。(写到中途,突然感觉到的。本篇设计大量初中物理知识,请怀念的往下看)

这次不像之前,是已经写好的文件,拿出来解析一波,就糊弄出来了一篇随笔。总之,我就一边的编代码,一边写文章。时不时的截图一个效果出来,不知道这样,能不能糊弄过去。。。。

这次,目标是准备实现很多canvas,素材网站上比较常见的烟花效果。只看过几次效果,也许实现的最终效果有些差异。但是,希望大家最后能以自己的能力改成自己更期待的结果,而不是只能跟着我做出一样的东西,没有任何的衍生。那意义就会缺少很多了。

既然是canvas,这一段还是不能省的。(注:往后的文章,可能会省略这段代码。主要记住ctx , width , height 这3个变量各自代表是什么就好了。之后我就直接使用了。所以希望大家多多包涵。)

var drawing = document.getElementById('drawing')
var ctx = drawing.getContext('2d')
var width = drawing.width
var height = drawing.height
  1. 对烟花的分析:
    大家心里都对,烟花有一定的印象。烟花有一个升空的过程,然后在空中爆炸散开成很多束。然后渐渐消散。
    总之,就是有2种状态了。用一个 Boolean 值来判断就好了。
    除此之外,还有烟花的位置,x, y轴上的速度,以及烟花的各种颜色。当然,还有其他各种属性,一时之间也想不到那么完美,不如我们走一步看一步,如何呢?

    function Fireworks (x, y, xSpeed, ySpeed, color) {
        this.x = x
        this.y = y
        this.xSpeed = xSpeed
        this.ySpeed = ySpeed
        this.color = color
        this.boom = false
    }

    其实,写到这里挺犹豫的。因为,不知道各位看官的知识面有多广,是否应该用  class ,最终,考量了一下,使用es6的,肯定知道构造函数,但是,反过来就不一定了。所以,也就简单做一个优雅降级吧。

  2. 上天吧!
    嘛。。。此情此景上天的当然是烟花咯。
    继承的写法多种多样,希望大家不要过多的考究。万分感谢。
        Fireworks.prototype.draw = function(){
    ctx.clearRect(, , width, height)
    ctx.beginPath()
    ctx.arc(this.x, this.y, , , *Math.PI)
    ctx.fill()
    } Fireworks.prototype.toSky = function(){
    this.x += this.xSpeed
    this.y += this.ySpeed
    this.draw()
    }

    为了更加的真实,我们还需要模拟重力加速度。 var g = 9.8 当然,这里只是假设。并不是我们必须设定的和实际的重力加速度一样。只是方便理解,而我百分百的确定,我之后一定会改变这个值的。

    Fireworks.prototype.toSky = function(){
    this.x += this.xSpeed
    this.y += this.ySpeed
    this.ySpeed -= g
    this.draw()
    }

    此时。比较细心的朋友,以及正跟着一步步敲代码的朋友,应该都会发现。这段代码里面有一些问题。我当然是故意的啦。不然,我就直接去上面改成没问题的代码,然后减掉这一段了!
    问题的bug,就是我们速度的正负值,以及canvas的y轴方向和我们正常习惯的y轴方向。有一些比较厉害的朋友,自己写方法将canvas的轴,修改成,我们通常使用的。
    但是,本篇还是使用的原生的,y轴正方向向下的情况。于是。。我们的烟花要升天。就要使用一个负值的速度。重力加速度,也需要相应的改动。我就不在这里做改动,混字数了,大家可以小修正一下y轴相关值正负,然后创建一个 Fireworks 实例加一个定时器来调用  toSky。就可以看到一小效果了,但是,这样就够了吗?其实,我接下来有更多需要丰满的地方。

  3. 现在该做什么呢?
    开头说的那么故弄玄虚,到现在不是就值做出了一个走抛物线的小球吗?而且还是写死的半径为10的黑球。就连之前说好的 color 都没有加上去。教练,这和说好的不一样啊!!
    所以,本来这一段效果优化的代码,准备放在总体逻辑完成之后再写下来的。但是现在的体验极差。就先丰满这一部分的视觉效果吧。
    首先,做一个简单操作 var r = Math.random.bind(Math)  很多人看到random。 就感觉有大事要发生。没错,就是这样。让我们对最初的构造函数,先做出小改动吧。
    function Fireworks () {
    var x = width * (r() * .8 + .1)
    this.x = x
    this.y = height
    this.xSpeed = x > width / 2 ? -(20 * r() - 10) : (20 * r() - 10)
    this.ySpeed = 20 * r() + 10
    this.color = 'rgb('+ f(r() * 256) +',' + f(r() * 256) + ','+ f(r() * 256) +' )'
    this.radius = 5
    this.dotNum = 20
    this.dots = []
    }

    大致的改动,大家都是可以自己看出来的。将起始点,定在canvas的最底部,起始点最少距离左右边缘都会有十分之一的宽度,根据起始点的位置,来决定,x轴的方向。将速度,颜色。都改成了随机数。将圆的半径也定义了进来。
    这些数字类型的值,大多都是可以自己按需修改,或者定义常量来使用。就不要过于纠结了。当然,这些数值都还不完善。只能最后我们添加了定时器,实际运行的时候,才能确定比较合理的数值。

    既然说到了定时器,不如就多说几句吧。一般我们动画上使用的定时器,每帧的间隔都会使用15ms。至于为什么就不说了。随便查一下就能找到,而且说太多了也偏离了本篇的主题了。想多说的就是做动画效果的时候的另外一个API, requestAnimationFrame 这里也不会介绍太多关于这个API,因为会偏题呀。只是之后会使用,所以,还不太了解的同学,可以先去了解一下这个API。
    到此,似乎,我们实际的效果并没有什么改变。
    那么接下来,就让我来使用新增的2个属性吧。

    Fireworks.prototype.createDotArr = function(){
    var length = this.dots.length
    if (length < this.dotNum)
    this.dots.push(
    {
    x: this.x,
    y: this.y
    })
    } else {
    for (var i = 0; i < length - 1; i++) {
    this.dots[i] = this.dots[i + 1]
    }
    this.dots[length - 1] = {
    x: this.x,
    y: this.y
    }
    }
    }

    上面这个方法,将我们之前的那个抛物线的圆,经过的点记录下来。因为只是一段较短的抛物线,所以我们暂时只记录20个点。也就是 dotNum 这个属性控制的点数。
    接下来就是将每个点都进行绘制,所以改写了我们之前的方法。于是就成了这样。

        Fireworks.prototype.draw = function(){
    var self = this
    ctx.clearRect(0, 0, width, height)
    self.dots.forEach(function(v){
    ctx.beginPath()
    ctx.arc(v.x, v.y, self.radius , 0 , 2 * Math.PI)
    ctx.fill()
    })
    } Fireworks.prototype.toSky = function(){
    this.x += this.xSpeed
    this.y -= this.ySpeed
    this.ySpeed -= g
    this.createDotArr()
    this.draw()
    }

    接下来,让我们来进行一下测试。看看现在效果如何了。

    var test = new Fireworks()
    function animate () {
    requestAnimationFrame(function () {
    test.toSky()
    animate()
    })
    }
    animate()

    并不是最终的调用形式。 只是做一个测试的效果。所以,之后这段是不包含在逻辑代码里的。另外,大家可以在做这个测试的时候,去改变构造函数内的常量参数,将它变成你喜欢的样子。我就不多废话了。
    其实,现在看起来好像也还不是很美观,颜色也并没有加上去。那就让我来加上颜色吧。当然并不是你们所想的 fillStyle = this.color 。因为这样看起来也并不好看啊。

    Fireworks.prototype.draw = function(){
    var self = this
    ctx.clearRect(0, 0, width, height)
    self.dots.forEach(function(v, i){
    var gradients = ctx.createRadialGradient(v.x, v.y, 1, v.x, v.y, i / self.dots.length * self.radius + 1)
    gradients.addColorStop(0, "rgba(" + self.R + "," + self.G + "," + self.B + "," + i / self.dotNum + ")")
    gradients.addColorStop(1, "rgba(" + self.R + "," + self.G + "," + self.B + ", 0 )")
    ctx.fillStyle = gradients
    ctx.beginPath()
    ctx.arc(v.x, v.y, self.radius , 0 , 2 * Math.PI)
    ctx.fill()
    })
    }

    忘记补充的一点,R,G,B属性。是我在构造函数中,将color属性,拆分成了,这3个属性。大家可以自己实现,我就不贴代码了。
    这里采用的渐变色,内部为最深的颜色,但是在点的索引逐渐变大,也就是这个点存在的时间变长的时候,逐渐变的透明,向外部延伸直至完全透明。要保证渐变向外延伸,所以在 createRadialGradient 的第六个参数的最后 + 1,以此确保这个值是大于1的。

小结:

至此,就是一个可以上天,但是还不能爆炸的哑炮烟花了。代码敲到这里,主要实现烟花的各种逻辑已经全部都有讲到了,之后的内容没有什么新的知识点,大家可以自己尝试完成接下来的内容。由于时间不足,就写到这里,不久之后,我会回来填坑的。

大家就不要打我了。

canvas 从初级到XX 2# 让我们在之前的基础之上,再迈进一步吧 [中级向] (上)的更多相关文章

  1. canvas 从初级到XX 1# 部分非基础原生API的使用 [初级向]

    标题canvas 从初级到XX,XX是因为本文随机都可能会太监,并不会支持到入土.请慎重的往下看. 对于canvas的介绍,随处都可以找到,也就不啰嗦太多了.就直奔主题了. 先看一段代码,以及实现的效 ...

  2. js canvas游戏初级demo-躲避障碍物

    在线演示地址 http://200ok.fun:3100/html/game_demo.html 继上次js canvas游戏初级demo-上下左右移动(https://www.cnblogs.com ...

  3. js canvas游戏初级demo-上下左右移动

    大概流程就是监听状态变化擦除画布重绘 由于js监听时间变化的函数addEventListener只能达到每秒触发20次左右,也就是每秒20帧,看起来有点卡卡的 所以用定时器搞到每秒30帧 按上下左右键 ...

  4. 聊一聊jquery文件上传(支持多文件上传)

    谈到文件上传,现在一般都用现成的组件可以使用.PC端的可以使用uploadify.针对微网站H5也有uploadifive.但是这组件并不能满足各种场景的需求,例如:预览 切图 放大缩小,取消之类的. ...

  5. python学习之路-8 面向对象之进阶

    上篇内容回顾和补充 面向对象三大特性 封装 继承 多态 在python中没有多态的概念 变量的类型允许为多种数据类型称之为多态 # c#/java中的多态 # 伪代码 def func(int arg ...

  6. nginx实战五

    nginx用户认证 https://coding.net/u/aminglinux/p/nginx/git/blob/master/access/auth.md 当访问一些私密资源时,最好配置用户认证 ...

  7. H5拍照、选择图片上传组件核心

    背景 前段时间项目重构,改成SSR的项目,但之前用的图片选择上传组件不支持SSR(server-side-render).遂进行了调研,发现很多的工具.但有的太大,有的使用麻烦,有的不满足使用需求.决 ...

  8. 零基础的Java小白如何准备初级开发的面试

    对于各位Java程序员来说,只要能有实践的机会,哪怕工资再低,公司情况再一般,只要自己上心努力,就可能在短时间内快速提升,甚至在工作2年后进大厂都有希望,因为项目里真实的开发实践环境是平时学习不能模拟 ...

  9. HTML5学习总结——canvas绘制象棋(canvas绘图)

    一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...

随机推荐

  1. 【Android开发学习笔记之一】5大布局方式详解

    Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...

  2. win7及以上系统打开chm空白或显示"无法打开"的2个解决方案

    1:在文件上右键单击属性.选择解锁. 2:确保文件路径中没有特殊字符.比如"#".如果路径中存在特殊字符,chm文件可能找不到路径而无法显示.如 d:\资料\c#\***.chm. ...

  3. Django学习(1)一首情诗

    Django是Python中Web开发的最有代表性的框架之一.本文将简单介绍如何入门Django开发. 首先确保你的linux系统已安装django模块.打开Python3,利用以下命令可找到djan ...

  4. CCF-201604-3-路径解析

    问题描述 试题编号: 201604-3 试题名称: 路径解析 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 在操作系统中,数据通常以文件的形式存储在文件系统中.文件系统一般采 ...

  5. c# textbox的滚动条总是指向最底端

    当我第一次添加滚动条时候,我发现滚动条总是跑向上方,经过研究 解决方案如下: this.textBox1.Focus(); 获取焦点 this.textBox1.Select(this.textBox ...

  6. C# 在RichTextBox中滚动鼠标时滚动的是父窗口的滚动条

    1. RichTextBox u2 = new RichTextBox(); 2. 先记住日RichTextBox没有显示滚动条时的总宽度和显示宽度 u2.Width - u2.ClientSize. ...

  7. Wes7 剪裁方法

    1. 加载x64的 DS共享库,加载一个compatibility.xml模板 2. 导入硬件信息文件File—Import—Import PMQ 用TAP.exe工具创建.PMQ文件(.PMQ文件保 ...

  8. java.util.ArrayList、java.util.vector和java.util.LinkedList (JDK 1.8.0_111)

    一.java.util.ArrayList 1.1 ArrayList 继承结构 ArrayList实现了RandomAccess,可以随机访问(其实就是通过数组下标访问):实现了Cloneable, ...

  9. 利用vmware搭建分布式集群

    背景:      我们需要至少3台服务器来实现分布式,鉴于没那么多钱买真机器,从学习和开发的角度看,只有虚拟机一条路了. 软件选择:     虚拟机使用VMware软件,因为主流而且资料比较多,学习成 ...

  10. gcc/g++ 命令的经常使用选项

    gcc/g++ 命令的经常使用选项格式(选项 解释) -o FILE 指定输出文件名称.在编译为目标代码时,这一选项不是必须的.假设FILE没有指定,缺省文件名称是a.out. -c 仅仅编译生成目标 ...