整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

canvas 两种拖尾效果实现烟花

canvas 两种拖尾效果实现烟花

canvas 两种拖尾效果实现烟花:视觉盛宴的代码艺术

**引言**

在Web前端开发领域,HTML5 Canvas以其强大的图形渲染能力,为开发者提供了无限可能。本文将聚焦于如何利用Canvas API创建出绚丽夺目的烟花特效,并重点解析两种不同风格的烟花拖尾效果实现方式。通过详细的代码示例和解析,你将学会如何打造一场属于自己的线上烟火晚会,让观众沉浸在美轮美奂的视觉盛宴之中。

## **一、基础概念与准备工作**

### **1. 创建Canvas元素**

首先,在HTML中设置一个`canvas`元素作为画布:

```html

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Canvas烟花特效</title>

<style>

canvas {

display: block;

margin: auto;

background-color: #000;

}

</style>

</head>

<body>

<canvas id="fireworksCanvas" width="800" height="600"></canvas>

<script src="fireworks.js"></script>

</body>

</html>

```

### **2. 获取Canvas上下文**

在JavaScript文件(如上例中的`fireworks.js`)中获取Canvas上下文:

```javascript

const canvas=document.getElementById('fireworksCanvas');

const ctx=canvas.getContext('2d');

```

## **二、基于点阵的烟花拖尾效果**

### **原理**

本方法采用点阵形式模拟烟花爆炸后的粒子轨迹,每个粒子随着时间推移逐渐消散或淡出。

```javascript

class Particle {

constructor(x, y, speed, color) {

this.x=x;

this.y=y;

this.speed=speed;

this.color=color;

// 其他属性...

}

update() {

// 更新粒子位置

this.y -=this.speed;

// 淡出处理...

}

draw(ctx) {

ctx.fillStyle=this.color;

ctx.beginPath();

ctx.arc(this.x, this.y, 1, 0, Math.PI * 2);

ctx.fill();

}

}

// 烟花类,包含多个粒子对象

class FireworkWithDotsTrail {

// 初始化、更新、绘制方法...

}

```

### **实现过程**

1. 在烟花发射时生成一组随机位置、速度和颜色的粒子。

2. 每帧更新所有粒子的位置和透明度,并绘制到画布上。

3. 当粒子超出屏幕或者透明度达到一定程度时,重新生成新的粒子以维持烟花的持续效果。

## **三、基于线条追踪的烟花拖尾效果**

### **原理**

此方法通过连续记录烟花移动路径上的关键点,并连接这些点形成一条平滑的线条来展现拖尾效果。

```javascript

class FireworkWithLineTrail {

constructor(startX, startY, endX, endY, color) {

this.startX=startX;

this.startY=startY;

this.endX=endX;

this.endY=endY;

this.color=color;

this.trailPoints=[[startX, startY]];

}

update(position) {

this.endX=position.x;

this.endY=position.y;

this.trailPoints.push([this.endX, this.endY]);

// 清理过旧的轨迹点...

}

draw(ctx) {

ctx.beginPath();

ctx.strokeStyle=this.color;

for (let i=0; i < this.trailPoints.length - 1; i++) {

const [x1, y1]=this.trailPoints[i];

const [x2, y2]=this.trailPoints[i + 1];

ctx.moveTo(x1, y1);

ctx.lineTo(x2, y2);

}

ctx.stroke();

}

}

```

### **实现过程**

1. 初始化烟花发射位置和目标方向,创建一个包含起点坐标的轨迹点数组。

2. 每次烟花移动时,添加新的坐标点至轨迹点数组,并清理超出指定数量的旧轨迹点。

3. 绘制时,遍历轨迹点数组并连线,形成拖尾效果。

## **四、完整示例及动画循环**

为了实现动态效果,我们需要使用`requestAnimationFrame`进行动画循环:

```javascript

function animate() {

ctx.clearRect(0, 0, canvas.width, canvas.height);

fireworks.forEach((firework)=> firework.updateAndDraw());

requestAnimationFrame(animate);

}

// 初始化若干烟花实例并开始动画循环

const fireworks=[/*...*/];

animate();

```

**结语**

通过以上介绍,我们成功地展示了如何利用Canvas技术在网页上实现两种不同的烟花拖尾效果。无论是点阵式的粒子轨迹,还是线条追踪形成的连贯轨迹,都能带给用户强烈的视觉冲击力。理解并掌握这两种实现方式,无疑会让你在Web前端设计与开发领域更加游刃有余,能够创造出更多惊艳的交互式视觉体验。而实际应用中,根据具体需求,还可以进一步优化细节,例如增加色彩渐变、粒子形状变化等特性,使烟花特效更为丰富多样。不断探索Canvas的无穷魅力,你将在Web世界中描绘出属于自己的璀璨星空!

教程

目录:

1. 绘制静态粒子图形效果

2. 添加静态粒子动画效果

3. 添加粒子碰撞动画效果

4. 添加粒子四面碰撞效果

基础要求:

1. 了解基础HTML标签,例如canvas标签

2. 了解Javascript的基础知识

第一步: 生成静态粒子图形

生成静态粒子图形,我们将会使用到Canvas的如下相关方法:

context.fillRect(x, y, width, height);

context.arc(x, y, r, sAngle, eAngle, counterclockwise);

其中,使用fillRect方法生成了整个动画场景,布满了画布全部区域,再使用arc方法来生成一个圆形,arc方法本身用来生成圆弧,但是如果生成一个360度的圆弧的话,就自然生成了圆形,完整代码如下:

var canvas=document.getElementById('gbcanvas'),

context=canvas.getContext('2d');

var posX=30, //定义圆心X坐标

posY=30, //定义圆心Y坐标

particleRadius=30; //定义半径

context.fillStyle='#E4E4E4';

context.fillRect(0,0,canvas.width,canvas.height); //生成画布背景色

context.beginPath;

context.fillStyle='#dd4814';

context.arc(posX, posY, particleRadius, 0 , Math.PI*2, true);

context.closePath;

context.fill;

在线演示&调试地址

http://www.igeekbar.com/igclass/code/5392196c-400d-466c-b0cb-647bbc3469cc.htm

第二步: 生成粒子运行效果

动画效果原理:

HTML5 画布动画生成原理,本质来说实现方式就是每隔固定时间段重新绘制画布内的图形,如下是代码:

var canvas=document.getElementById('gbcanvas'),

context=canvas.getContext('2d'),

posX=30,

posY=30,

particleRadius=30;

//定义setInterval来隔特定时间生成粒子,如下

setInterval(function{

//为了能够生成粒子移动效果,我们需要在每次绘制粒子之前清楚界面里的绘图

context.fillStyle='#E4E4E4';

context.fillRect(0,0,canvas.width,canvas.height); //使用背景色填充

posX+=2;

posY+=1;

context.arc(posX, posY, particleRadius, 0, Math.PI*2, true);

}, 10);

以上代码我们使用fillRect方法来先将整个背景色重新填充,再使用arc方法重新绘制圆形,来生成移动的效果

在线演示&调试地址

http://www.igeekbar.com/igclass/code/d2ff678f-23f1-4cab-9eba-9898d4393017.htm

第三步: 生成粒子碰撞效果

使用HTML5画布生成一个粒子碰撞地面效果,并且同时添加相关重力加速度效果。

首先定义粒子x轴和y轴的运动速度及重力加速度,如下:

speedX=10, //定义一个X轴方向的速度

speedY=10, //定义一个Y轴方向的速度

gravity=1; //定义一个重力的参数,即重力加速度

然后,设置粒子运动速度,即每次绘制粒子圆心坐标的变化,如下:

//以下代码设置运动速度

posX+=speedX;

posY+=speedY;

同时,保证Y轴拥有一个加速度效果,如下:

//添加重力加速度效果

speedY+=gravity;

最后,我们添加一个地面碰撞效果,判断当粒子的中心Y轴低于canvas的高度减去粒子半径,即粒子部分区域低于画布最低端的时候,重新定义粒子的位置,如下:

//接下来我们添加地面反弹效果,只需要判断当粒子运动到近画布底端的时候,粒子Y轴坐标反向

if(posY > canvas.height - particleRadius){

speedY*=-0.5; //这里设置粒子速度为负值,修改此数值可以修改粒子Y轴运动速度损耗量

speedX*=0.5; //这里设置粒子X轴速度的损耗量

posY=canvas.height - particleRadius; //这里当粒子低于画布最低端的时候,设置保证其不消失

}

在线演示&调试地址

http://www.igeekbar.com/igclass/code/8a3cfeb7-b052-4bf7-b3b1-8ec4e59584af.htm

第四步: 生成四面碰壁粒子效果

上面我们生成了粒子碰撞地面效果,本节我们添加粒子四面碰壁效果,基本代码如下:

//判断粒子位于画布右侧可显示区域外

if(posX > canvas.width - particleRadius){

speedX*=-1;

posX=canvas.width - particleRadius;

}

//判断粒子位于画布左侧可显示区域外

if(posX < particleRadius){

speedX*=-1;

posX=particleRadius;

}

//最后添加顶端的反弹效果

if(posY < particleRadius){

speedY*=-1;

posY=particleRadius;

}

大家可以看到,代码基本和碰撞地面效果类似,只不过判断粒子中心所处的坐标位置来修改粒子运动的方向。

在线演示&调试地址

http://www.igeekbar.com/igclass/code/87784219-f527-4f52-bfb2-62cd82bbc07d.htm

Done!以上就是几个HTML5实现粒子物理碰撞的例子, 希望大家能够觉得有用, 有任何问题,请给我留言哈


、什么是Canvas

没有Canvas的年代,绘图只能借助Flash,页面不得不用JavaScript和Flash进行交互,而现在可以直接用Html5的canvas元素使用JavaScript在网页上绘制图形。

Canvas指定了尺寸,可以在这个范围内任意绘制。

Canvas拥有多种绘制路径、矩形、圆形、字符以及添加图形的方法。

二、Canvas的环境

由于浏览器对HTML5标准支持不一致,所以通常在<canvas>的内部添加一些说明性HTML代码,如果不支持将显示其内部的HTML。

<canvas width="100" height="100" id="canva">
 <p>您的浏览器版本暂不支持Canvas,请进行升级</p>
</canvas>

var canvas=document.getElementById('canva');
if (canvas.getContext){
 var ctx=canvas.getContext('2d');
 // drawing code here
} else {
 // canvas-unsupported code here
}

三、Canvas的坐标系统

Canvas的坐标系统以左上角为原点,水平向右为X轴,垂直向下为Y轴,以像素为单位,所以每个点都是非负整数。

?

四、绘制矩形

Canvas只支持一种原生图形的绘制:矩形。

所有其他图形都至少需要生成一种路径。

Canvas提供了几种方式绘制矩形:

描述方法参数创建矩形rect(x,y,width,height)x:矩形左上角X坐标

y:矩形左上角的Y坐标

width:矩形的宽度,以像素计

height:矩形的高度,以像素计

绘制一个填充颜色的矩形,默认黑色fillRect(x,y,width,height)x:矩形左上角X坐标

y:矩形左上角的Y坐标

width:矩形的宽度,以像素计

height:矩形的高度,以像素计

绘制一个矩形边框,默认黑色strokeRect(x,y,width,height)x:矩形左上角X坐标

y:矩形左上角的Y坐标

width:矩形的宽度,以像素计

height:矩形的高度,以像素计

在给定的矩形内清除指定的像素,然后这块区域变完全透明clearRect(x,y,width,height)x:要清除的矩形左上角X坐标

y:要清除的矩形矩形左上角的Y坐标

width:要清除的矩形矩形的宽度,以像素计

height:要清除的矩形矩形的高度,以像素计

例如:

?

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>1.绘制矩形</title>
 <style>
 #canvas{
 width: 500px;
 height: 200px;
 border: 1px solid red;
 }
 </style>
</head>
<body>
 <canvas id="canvas"></canvas>
 <script>
 window.onload=function () {
 var canvas=document.getElementById('canvas');
 if (!canvas.getContext) return;
 var context=canvas.getContext('2d');
 context.strokeRect(20,20,100,100);
 context.fillRect(30,30,80,80);
 context.clearRect(40,40,60,60);
 }
 </script>
</body>
</html>

五、绘制路径

图形的基本元素是路径。

路径通过不同颜色和宽度的线段、曲线相连形成不同形状的点集合。

一个路径,甚至一个子路径,都是闭合的。

步骤:

1. 创建路径起始点 -- beginPath()

2. 使用画图命令画出路径 -- moveTo()等

3. 路径封闭 -- closePath()

4. 一旦路径生成即可通过描边或填充路径来渲染图形 -- fill()

描述方法参数填充当前绘图fill()

绘制已定义的路径stroke()

起始一条路径,或重置当前当前路径beginPath()

把路径以定到画布指定点moveTo(x,y)x:路径的目标位置的X坐标

y:路径的目标位置的Y坐标

创建从当前点到起始点的路径closePath()

添加一个新点,然后再画布中创建从该点到最后指定点的线条lineTo(x,y)x:路径的目标位置的X坐标

y:路径的目标位置的Y坐标

从原始画布剪切任意形状和尺寸的区域clip()

创建二次贝赛尔曲线quadraticCurveTo(cpx,cpy,x,y)cpx:贝塞尔控制点的X坐标

cpy:贝塞尔控制点的Y坐标

x:结束点的X坐标

y:结束点的Y坐标

创建三次贝塞尔曲线bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)cp1x:第一个贝塞尔控制点的 x 坐标

cp1y:第一个贝塞尔控制点的 y 坐标

cp2x:第二个贝塞尔控制点的 x 坐标

cp2y:第二个贝塞尔控制点的 y坐标

x:结束点的 x 坐标

y:结束点的 y 坐标

创建弧、曲线(用于创建圆形或部分圆)arc(x,y,r,sAngle,eAngle,counterclockwise)x:圆的中心的 x 坐标

y:圆的中心的 y 坐标

r:圆的半径

sAngle:起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)

eAngle:结束角,以弧度计

counterclockwise:可选,规定在逆时针还是在顺时针绘图,False=顺时针,true=逆时针

创建两切线之间的弧、曲线arcTo(x1,y1,x2,y2,r)x1:弧的起点的 x 坐标

y1:弧的起点的 y 坐标

x2:弧的终点的 x 坐标

y2:弧的终点的 y 坐标

r:弧的半径

如果指定的点位于当前路径中,则返回true,否则返回falseisPointInPath(x,y)x:测试的 x 坐标

y:测试的 y 坐标

延伸:

一次贝塞尔曲线

?

二次贝塞尔曲线

转存失败

重新上传

取消

?

三次贝塞尔曲线

?

六、添加样式、颜色和阴影

描述方法参数用于填充绘画的颜色、渐变或模式fillStylecolor|gradient|pattern

color:css颜色值

gradient:用于填充绘图的渐变对象(线性或放射性)

pattern:用于填充绘图的 pattern 对象

用于笔触的颜色、渐变或模式strokeStylecolor|gradient|pattern

colorcss颜色值

gradient:用于填充绘图的渐变对象(线性或放射性)

pattern:用于填充绘图的 pattern 对象

用于阴影的颜色shadowColorcolor:css颜色值用于阴影的模糊级别shadowBlurnumber:模糊级别数阴影距形状的水平距离shadowOffsetXnumber:正值或负值,定义阴影与形状的水平距离阴影距形状的垂直距离shadowOffsetYnumber:正值或负值,定义阴影与形状的垂直距离

创建线性渐变createLinearGradient(x0,y0,x1,y1)x0:渐变开始点的 x 坐标
y0:渐变开始点的 y 坐标
x1:渐变结束点的 x 坐标
y1:渐变结束点的 y 坐标

在指定方向上重复指定的元素(元素可以是图片、视频,或者其他 <canvas> 元素)cratePattern(image,"repeat|repeat-x|repeat-y|no-repeat")image:规定要使用的图片、画布或视频元素
"repeat:默认。该模式在水平和垂直方向重复
repeat-x:该模式只在水平方向重复
repeat-y:该模式只在垂直方向重复
no-repeat:该模式只显示一次(不重复)
"

创建放射状、环形的渐变createRadialGradient(x0,y0,r0,x1,y1,r1)x0:渐变的开始圆的 x 坐标
y0:渐变的开始圆的 y 坐标
r0:开始圆的半径
x1:渐变的结束圆的 x 坐标
y1:渐变的结束圆的 y 坐标
r1:结束圆的半径

规定渐变对象中的颜色和停止位置addColorStop(stop,color)stop:介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置

color: css 颜色值

线条的结束端点样式lineCap"butt|round|square"

"

butt:默认。向线条的每个末端添加平直的边缘

round:向线条的每个末端添加圆形线帽

square:向线条的每个末端添加正方形线帽

"

两条线相交时,所创建的拐角类型lineJoin"bevel|round|miter"

"

bevel:创建斜角

round:创建圆角

miter:默认。创建尖角

"

当前的线条宽度lineWidthnumber:当前线条的宽度,以像素计

最大的斜接长度miterLimitnumber:正数。规定最大斜接长度。

如果斜接长度超过 miterLimit 的值,边角会以 lineJoin 的 "bevel" 类型来显示

七、绘制文字

描述方法参数当前字体属性font

当前对齐方式textAlign

当前文本基线textBaseline

在画布上绘制被填充的文本fillText()

在画布上绘制未被填充的文本strokeText()

返回包含指定文本宽度的对象measureText()

八、绘制图片

描述方法参数在画布上绘制图像、画布或视频drawImageimg:规定要使用的图形、画布或视频

sx:可选,开始剪切的X坐标位置

sy:可选,开始剪切的Y坐标位置

swidth:可选,被剪切图形的宽度

sheight:可选,被剪切图形的高度

x:在画布上放置图形的X坐标位置

y:在画布上放置图形的Y坐标位置

width:可选,要使用的图形的宽度(伸展或缩小图像)

height:可选,要使用的图形的高度(伸展或缩小图像)

返回ImageData对象的宽度width

返回ImageData对象的高度height

返回一个对象,其包含指定的ImageData对象的图像数据data

创建新的、空白的ImageData对象crateImageData()

返回ImageData对象,该对象为画布上指定的矩形复制像素数据getImageData()

把图像数据(从指定的ImageData对象)放回画布上putImageData()

九、变形

描述方法参数重新映射画布上的(0,0)位置translate()x:左右偏移量

y:上下偏移量

移动中心是坐标原点。

缩放当前绘图至更大或更小scale()scaleWIdth:缩放当前绘图宽度(1=100% 2=200%)

scaleHeight:缩放当前绘图高度(1=100% 2=200%)

旋转当前绘图rotate()angel:旋转角度,以弧度计,如需将角度转换为弧度,以degrees * Matn.PI/180公式计算。顺时针方向旋转,旋转中心是坐标原点。替换绘图的当前转换矩阵transform()a:水平缩放绘图

b:水平倾斜绘图

c:垂直倾斜绘图

d:垂直缩放绘图

e:水平移动绘图

f:垂直移动绘图

将当前转换重置为单位矩阵,然后运行transform()setTransform()a:水平旋转绘图

b:水平倾斜绘图

c:垂直倾斜绘图

d:垂直缩放绘图

e:水平移动绘图

f:垂直移动绘图

延伸:

1.translate:

?

2.rotate

转存失败

重新上传

取消

?

十、合成

描述方法参数设置或返回绘图当前alpha或透明值globalAlphanumber:透明值,必须介于0.0-1.0之间设置或返回心图形如何绘制到已有的图像上globalCompositeOperation等多个属性操作,略。。

十一、其他

描述方法参数保存当前环境的状态save()

返回之前报错过的路径状态和属性restore()

createEvent()

getContext()

toDataURL()

十二、动画

基本步骤:

1. 在绘制每一帧动画之前,需要清空所有canvas -- clearRect()

2. 保存canvas状态

3. 绘制动画图形

4. 恢复canvas状态