HTML5 canvas元素绘制花朵、烟花动画和刮刮乐
canvas是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,可通过脚本(通常是JavaScript)动态绘制图形。权威资料可见:
Canvas 教程 - Web API 接口参考 | MDN
本文包括几个例子:HTML5 canvas元素绘制花朵、HTML5 canvas粒子烟花绽放动画、HTML5 canva实现刮刮乐。
HTML5 canvas元素绘制花朵
先给出演示图如下:
源码如下:
<!DOCTYPE html>
<meta charset="UTF-8">
<title>使用canvas元素绘制美丽的花朵</title>
<head>
<script >
var context;
var A,n;
function btn_onclick()
{
var width;
var Height;
var canvas;
var Xo,Yo;
var k;
canvas=document.getElementById("canvas");
width=canvas.width;
height=canvas.height;
context=canvas.getContext('2d');
Xo=width/2;
Yo=height/2;
k=parseInt(document.getElementById("drawType").value);
if(k==2)
A=Yo*0.25;
else
A=Yo*0.75;
context.save();//保存当前绘制状态
context.clearRect(0,0,width,height);//擦除之前绘制的图形
context.translate(Xo,Yo);//坐标原点移动到canvas元素中央
context.beginPath();//开始创建路径
for(var B=0;B<=6.28;B=B+0.01)
{
draw(B);//绘制花朵曲线
}
context.closePath();//关闭路径
context.restore();//恢复坐标轴平移之前的绘制状态
}
function draw(B)
{
var n=10;
switch(parseInt(document.getElementById("drawType").value))
{
case 3://大丽花
r=A*Math.sin(n*B)*Math.exp(-B/(20));
break;
case 2://令箭荷花
r=A*(Math.sin(n*B)+3*Math.sin(3*n*B));
break;
case 1://蓬莱菊
r=A*Math.sin(n*B);
}
//极坐标的直角坐标
x=r*Math.cos(B);
y=r*Math.sin(B);
context.fillStyle="yellow";//设置填充颜色
context.strokeStyle="black";//设置边框颜色
context.lineTo(-x,-y);//绘制直线
context.fill();//填充图形
context.stroke();//绘制边框
}
</script>
</head>
<body>
<h2>使用canvas元素绘制美丽的花朵</h2>
花的类型:
<select id="drawType">
<option value="1">蓬莱菊</option>
<option value="2">令箭荷花</option>
<option value="3">大丽花</option>
</select>
<input type="button" id="btn" value="绘制" onclick="btn_onclick()"/><br/>
<canvas id="canvas" width="200px" height="200px"></canvas>
</body>
</html>
HTML5 canvas粒子烟花绽放动画
先给出演示图如下:
将下列代码保存为html文件名:HTML5canvas粒子烟花.HTML,用浏览器代开运行此文件,就可看到效果。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>粒子烟花</title>
<style>
body {
background-image: linear-gradient(6deg, #214, #000);
background-size: 100% 100%;
overflow:hidden
}
canvas { display: block; }
</style>
</head>
<body>
<script>
class Vector2 {
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
add(v) {
this.x += v.x;
this.y += v.y;
return this;
}
multiplyScalar(s) {
this.x *= s;
this.y *= s;
return this;
}
clone() {
return new Vector2(this.x, this.y);
}
}
class Time {
constructor() {
const now = Time.now();
this.delta = 0;
this.elapsed = 0;
this.start = now;
this.previous = now;
}
update() {
const now = Time.now();
this.delta = now - this.previous;
this.elapsed = now - this.start;
this.previous = now;
}
static now() {
return Date.now() / 1000;
}
}
class Particle {
constructor(position, velocity = new Vector2, color = 'white', radius = 1, lifetime = 1, mass = 1) {
this.position = position;
this.velocity = velocity;
this.color = color;
this.radius = radius;
this.lifetime = lifetime;
this.mass = mass;
this.isInCanvas = true;
this.createdOn = Time.now();
}
update(time) {
if (!this.getRemainingLifetime()) {
return;
}
this.velocity.add(Particle.GRAVITATION.clone().multiplyScalar(this.mass));
this.position.add(this.velocity.clone().multiplyScalar(time.delta));
}
render(canvas, context) {
const remainingLifetime = this.getRemainingLifetime();
if (!remainingLifetime) return;
const radius = this.radius * remainingLifetime;
context.globalAlpha = remainingLifetime;
context.globalCompositeOperation = 'lighter';
context.fillStyle = this.color;
context.beginPath();
context.arc(this.position.x, this.position.y, radius, 0, Math.PI * 2);
context.fill();
}
getRemainingLifetime() {
const elapsedLifetime = Time.now() - this.createdOn;
return Math.max(0, this.lifetime - elapsedLifetime) / this.lifetime;
}
}
Particle.GRAVITATION = new Vector2(0, 9.81);
class Trail extends Particle {
constructor(childFactory, position, velocity = new Vector2, lifetime = 1, mass = 1) {
super(position, velocity);
this.childFactory = childFactory;
this.children = [];
this.lifetime = lifetime;
this.mass = mass;
this.isAlive = true;
}
update(time) {
super.update(time);
// Add a new child on every frame
if (this.isAlive && this.getRemainingLifetime()) {
this.children.push(this.childFactory(this));
}
// Remove particles that are dead
this.children = this.children.filter(function(child) {
if (child instanceof Trail) {
return child.isAlive;
}
return child.getRemainingLifetime();
});
// Kill trail if all particles fade away
if (!this.children.length) {
this.isAlive = false;
}
// Update particles
this.children.forEach(function(child) {
child.update(time);
});
}
render(canvas, context) {
// Render all children
this.children.forEach(function(child) {
child.render(canvas, context);
});
}
}
class Rocket extends Trail {
constructor(childFactory, explosionFactory, position, velocity = new Vector2) {
super(childFactory, position, velocity);
this.explosionFactory = explosionFactory;
this.lifetime = 10;
}
update(time) {
if (this.getRemainingLifetime() && this.velocity.y > 0) {
this.explosionFactory(this);
this.lifetime = 0;
}
super.update(time);
}
}
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const time = new Time;
let rockets = [];
const getTrustParticleFactory = function(baseHue) {
function getColor() {
const hue = Math.floor(Math.random() * 15 + 30);
return `hsl(${hue}, 100%, 75%`;
}
return function(parent) {
const position = this.position.clone();
const velocity = this.velocity.clone().multiplyScalar(-.1);
velocity.x += (Math.random() - .5) * 8;
const color = getColor();
const radius = 1 + Math.random();
const lifetime = .5 + Math.random() * .5;
const mass = .01;
return new Particle(position, velocity, color, radius, lifetime, mass);
};
};
const getExplosionFactory = function(baseHue) {
function getColor() {
const hue = Math.floor(baseHue + Math.random() * 15) % 360;
const lightness = Math.floor(Math.pow(Math.random(), 2) * 50 + 50);
return `hsl(${hue}, 100%, ${lightness}%`;
}
function getChildFactory() {
return function(parent) {
const direction = Math.random() * Math.PI * 2;
const force = 8;
const velocity = new Vector2(Math.cos(direction) * force, Math.sin(direction) * force);
const color = getColor();
const radius = 1 + Math.random();
const lifetime = 1;
const mass = .1;
return new Particle(parent.position.clone(), velocity, color, radius, lifetime, mass);
};
}
function getTrail(position) {
const direction = Math.random() * Math.PI * 2;
const force = Math.random() * 128;
const velocity = new Vector2(Math.cos(direction) * force, Math.sin(direction) * force);
const lifetime = .5 + Math.random();
const mass = .075;
return new Trail(getChildFactory(), position, velocity, lifetime, mass);
}
return function(parent) {
let trails = 32;
while (trails--) {
parent.children.push(getTrail(parent.position.clone()));
}
};
};
const addRocket = function() {
const trustParticleFactory = getTrustParticleFactory();
const explosionFactory = getExplosionFactory(Math.random() * 360);
const position = new Vector2(Math.random() * canvas.width, canvas.height);
const thrust = window.innerHeight * .75;
const angle = Math.PI / -2 + (Math.random() - .5) * Math.PI / 8;
const velocity = new Vector2(Math.cos(angle) * thrust, Math.sin(angle) * thrust);
const lifetime = 3;
rockets.push(new Rocket(trustParticleFactory, explosionFactory, position, velocity, lifetime));
rockets = rockets.filter(function(rocket) {
return rocket.isAlive;
});
};
const render = function() {
requestAnimationFrame(render);
time.update();
context.clearRect(0, 0, canvas.width, canvas.height);
rockets.forEach(function(rocket) {
rocket.update(time);
rocket.render(canvas, context);
});
};
const resize = function() {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
};
canvas.onclick = addRocket;
document.body.appendChild(canvas);
window.onresize = resize;
resize();
setInterval(addRocket, 250);
render();
</script>
</body>
</html>
HTML5 canva实现刮刮乐
先给出演示图如下:
准本几张素材图:
源码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>刮刮看(</title>
<style>
div.msg {
font-family: 微软雅黑;
color:#ffa502 ;
}
a:hover {
color: rgb(0, 0, 0);
text-decoration: none;
}
.btn-dang{
border-radius: 8px;
background-color: #21a3f1;
color: rgb(255, 255, 255);
}
</style>
</head>
<body>
<div id="main">
<canvas
id="myCanvas"
width="400"
height="400"
style="border:1px solid #000;"
>
您的浏览器不支持 HTML5 canvas 标签。
</canvas>
<div class="msg">
<a
href="javascript:void(0)"
onClick="window.location.reload()"
class="btn-dang"
>随机换图</a
>
</div>
</div>
</body>
<script>
var mycanvas = document.getElementById("myCanvas");
var ctx = mycanvas.getContext("2d");
var arr = ["1.jpg", "2.jpg", "3.jpg"];
var number = Math.floor(Math.random() * arr.length);
var urla = "img/";
mycanvas.style.background = "url(" + urla+arr[number] + ")";
mycanvas.style.backgroundSize = "100%";
ctx.fillStyle = "#cc6633";
ctx.fillRect(0, 0, 10000,10000);
ctx.font = "normal 80px 仿宋";
ctx.strokeStyle = "slateblue";
ctx.strokeText("请刮开!",80,150); //
var status = "false";
mycanvas.onmousedown = function () {
status = "true";
};
mycanvas.onmouseup = function () {
status = "false";
};
mycanvas.onmousemove = function (e) {
if (status == "true") {
ctx.globalCompositeOperation = "destination-out";
ctx.beginPath();
ctx.arc(e.pageX, e.pageY, 20, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
}
};
</script>
</html>
HTML5 canva实现擦除上层图片的例子
先给出演示图如下:
准本几张素材图:
源码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>刮刮乐(实现擦除效果)</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
canvas{
background-image: url('img/lower1.jpg'); //底层图片
background-size: cover;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.querySelector("#canvas");
var ctx = canvas.getContext("2d");
canvas.width = 336;
canvas.height = 410;
var img = new Image();
img.src = "img/upper1.jpg"; //上层图片,实现擦除效果
img.onload=function(){
ctx.drawImage(img,0,0,canvas.width,canvas.height);
}
// 标记是否按下鼠标(开始刮)
var isDown = false;
canvas.addEventListener('mousemove',function(event){
if(isDown){
let x = event.offsetX;
let y = event.offsetY;
ctx.beginPath();
ctx.fillStyle = "white";
ctx.arc(x,y,20,Math.PI*2,false);
ctx.fill();
ctx.closePath();
ctx.globalCompositeOperation = 'destination-out';
}
})
//var isDown = false;
canvas.addEventListener('mousedown',function(){
isDown = true;
})
canvas.addEventListener('mouseup',function(){
isDown = false;
})
</script>
</body>
</html>