<!DOCTYPE HTML>
<html>
<head>
<title>Canvas 实现放烟花特效</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,height=device-height,inital-scale=1.0,maximum-scale=1.0,user-scalable=no">
<style type="text/css">
html,body{height:100%;margin:0;padding:0}
ul,li{text-indent:0;text-decoration:none;margin:0;padding:0}
img{border:0}
body{background-color:#000;color:#999;font:100%/18px helvetica, arial, sans-serif}
canvas{cursor:crosshair;display:block;left:0;position:absolute;top:0;z-index:20}
#header img{width:100%; height:20%;}
#bg img{width:100%; height:80%;}
#header,#bg{position:fixed;left:0;right:0;z-index:10}
#header{top:0}
#bg{position:fixed;z-index:1;bottom:0}
audio{position:fixed;display:none;bottom:0;left:0;right:0;width:100%;z-index:5}
</style>
</head>
<body>
<div id="bg">
<img id="bgimg" src="http://img.ivsky.com/img/tupian/pre/201508/02/yuzhou_xingkong_yu_yueliang-006.jpg">
</div>
<script src="http://cdn.bootcss.com/jquery/2.2.0/jquery.min.js"></script>
<script>
$(function(){
var Fireworks = function(){
var self = this;
// 产生烟花随机数
var rand = function(rMi, rMa){
//按位取反运算符
return ~~((Math.random()*(rMa-rMi+1))+rMi);
},hitTest = function(x1, y1, w1, h1, x2, y2, w2, h2){
return !(x1 + w1 < x2 || x2 + w2 < x1 || y1 + h1 < y2 || y2 + h2 < y1);
};
//请求动画帧
window.requestAnimFrame=function(){
return window.requestAnimationFrame
||window.webkitRequestAnimationFrame
||window.mozRequestAnimationFrame
||window.oRequestAnimationFrame
||window.msRequestAnimationFrame
||function(callback){
window.setTimeout(callback,1000/60);
}
}();
self.init = function(){
self.canvas = document.createElement('canvas');
//canvas 全屏
self.canvas.width = self.cw = $(window).innerWidth();
self.canvas.height = self.ch = $(window).innerHeight();
self.particles = [];
self.partCount = 150;
self.fireworks = [];
self.mx = self.cw/2;
self.my = self.ch/2;
self.currentHue = 30;
self.partSpeed = 5;
self.partSpeedVariance = 10;
self.partWind = 50;
self.partFriction = 5;
self.partGravity = 1;
self.hueMin = 0;
self.hueMax = 360;
self.fworkSpeed = 4;
self.fworkAccel = 10;
self.hueVariance = 30;
self.flickerDensity = 25;
self.showShockwave = true;
self.showTarget = false;
self.clearAlpha = 25;
$(document.body).append(self.canvas);
self.ctx = self.canvas.getContext('2d');
self.ctx.lineCap = 'round';
self.ctx.lineJoin = 'round';
self.lineWidth = 1;
self.bindEvents();
self.canvasLoop();
self.canvas.onselectstart = function() {
return false;
};
};
// 创建粒子
self.createParticles = function(x,y, hue){
var countdown = self.partCount;
while(countdown--){
var newParticle = {
x: x,
y: y,
coordLast: [
{x: x, y: y},
{x: x, y: y},
{x: x, y: y}
],
angle: rand(0, 360),
speed: rand(((self.partSpeed - self.partSpeedVariance) <= 0) ? 1 : self.partSpeed - self.partSpeedVariance, (self.partSpeed + self.partSpeedVariance)),
friction: 1 - self.partFriction/100,
gravity: self.partGravity/2,
hue: rand(hue-self.hueVariance, hue+self.hueVariance),
brightness: rand(50, 80),
alpha: rand(40,100)/100,
decay: rand(10, 50)/1000,
wind: (rand(0, self.partWind) - (self.partWind/2))/25,
lineWidth: self.lineWidth
};
self.particles.push(newParticle);
}
};
// 更新粒子
self.updateParticles = function(){
var i = self.particles.length;
while(i--){
var p = self.particles[i];
var radians = p.angle * Math.PI / 180;
var vx = Math.cos(radians) * p.speed;
var vy = Math.sin(radians) * p.speed;
p.speed *= p.friction;
p.coordLast[2].x = p.coordLast[1].x;
p.coordLast[2].y = p.coordLast[1].y;
p.coordLast[1].x = p.coordLast[0].x;
p.coordLast[1].y = p.coordLast[0].y;
p.coordLast[0].x = p.x;
p.coordLast[0].y = p.y;
p.x += vx;
p.y += vy;
p.y += p.gravity;
p.angle += p.wind;
p.alpha -= p.decay;
if(!hitTest(0,0,self.cw,self.ch,p.x-p.radius, p.y-p.radius, p.radius*2, p.radius*2) || p.alpha < .05){
self.particles.splice(i, 1);
}
};
};
// 绘制粒子
self.drawParticles = function(){
var i = self.particles.length;
while(i--){
var p = self.particles[i];
var coordRand = (rand(1,3)-1);
self.ctx.beginPath();
self.ctx.moveTo(Math.round(p.coordLast[coordRand].x), Math.round(p.coordLast[coordRand].y));
self.ctx.lineTo(Math.round(p.x), Math.round(p.y));
self.ctx.closePath();
self.ctx.strokeStyle = 'hsla('+p.hue+', 100%, '+p.brightness+'%, '+p.alpha+')';
self.ctx.stroke();
if(self.flickerDensity > 0){
var inverseDensity = 50 - self.flickerDensity;
if(rand(0, inverseDensity) === inverseDensity){
self.ctx.beginPath();
self.ctx.arc(Math.round(p.x), Math.round(p.y), rand(p.lineWidth,p.lineWidth+3)/2, 0, Math.PI*2, false)
self.ctx.closePath();
var randAlpha = rand(50,100)/100;
self.ctx.fillStyle = 'hsla('+p.hue+', 100%, '+p.brightness+'%, '+randAlpha+')';
self.ctx.fill();
}
}
};
};
// 创建烟花
self.createFireworks = function(startX, startY, targetX, targetY){
var newFirework = {
x: startX,
y: startY,
startX: startX,
startY: startY,
hitX: false,
hitY: false,
coordLast: [
{x: startX, y: startY},
{x: startX, y: startY},
{x: startX, y: startY}
],
targetX: targetX,
targetY: targetY,
speed: self.fworkSpeed,
angle: Math.atan2(targetY - startY, targetX - startX),
shockwaveAngle: Math.atan2(targetY - startY, targetX - startX)+(90*(Math.PI/180)),
acceleration: self.fworkAccel/100,
hue: self.currentHue,
brightness: rand(50, 80),
alpha: rand(50,100)/100,
lineWidth: self.lineWidth
};
self.fireworks.push(newFirework);
};
// 更新烟花
self.updateFireworks = function(){
var i = self.fireworks.length;
while(i--){
var f = self.fireworks[i];
self.ctx.lineWidth = f.lineWidth;
vx = Math.cos(f.angle) * f.speed,
vy = Math.sin(f.angle) * f.speed;
f.speed *= 1 + f.acceleration;
f.coordLast[2].x = f.coordLast[1].x;
f.coordLast[2].y = f.coordLast[1].y;
f.coordLast[1].x = f.coordLast[0].x;
f.coordLast[1].y = f.coordLast[0].y;
f.coordLast[0].x = f.x;
f.coordLast[0].y = f.y;
if(f.startX >= f.targetX){
if(f.x + vx <= f.targetX){
f.x = f.targetX;
f.hitX = true;
} else {
f.x += vx;
}
} else {
if(f.x + vx >= f.targetX){
f.x = f.targetX;
f.hitX = true;
} else {
f.x += vx;
}
}
if(f.startY >= f.targetY){
if(f.y + vy <= f.targetY){
f.y = f.targetY;
f.hitY = true;
} else {
f.y += vy;
}
} else {
if(f.y + vy >= f.targetY){
f.y = f.targetY;
f.hitY = true;
} else {
f.y += vy;
}
}
if(f.hitX && f.hitY){
self.createParticles(f.targetX, f.targetY, f.hue);
self.fireworks.splice(i, 1);
}
};
};
// 绘制烟花
self.drawFireworks = function(){
var i = self.fireworks.length;
self.ctx.globalCompositeOperation = 'lighter';
while(i--){
var f = self.fireworks[i];
self.ctx.lineWidth = f.lineWidth;
var coordRand = (rand(1,3)-1);
self.ctx.beginPath();
self.ctx.moveTo(Math.round(f.coordLast[coordRand].x), Math.round(f.coordLast[coordRand].y));
self.ctx.lineTo(Math.round(f.x), Math.round(f.y));
self.ctx.closePath();
self.ctx.strokeStyle = 'hsla('+f.hue+', 100%, '+f.brightness+'%, '+f.alpha+')';
self.ctx.stroke();
if(self.showTarget){
self.ctx.save();
self.ctx.beginPath();
self.ctx.arc(Math.round(f.targetX), Math.round(f.targetY), rand(1,8), 0, Math.PI*2, false)
self.ctx.closePath();
self.ctx.lineWidth = 1;
self.ctx.stroke();
self.ctx.restore();
}
if(self.showShockwave){
self.ctx.save();
self.ctx.translate(Math.round(f.x), Math.round(f.y));
self.ctx.rotate(f.shockwaveAngle);
self.ctx.beginPath();
self.ctx.arc(0, 0, 1*(f.speed/5), 0, Math.PI, true);
self.ctx.strokeStyle = 'hsla('+f.hue+', 100%, '+f.brightness+'%, '+rand(25, 60)/100+')';
self.ctx.lineWidth = f.lineWidth;
self.ctx.stroke();
self.ctx.restore();
}
};
};
// 绑定事件
self.bindEvents = function(){
$(window).on('resize', function(){
clearTimeout(self.timeout);
self.timeout = setTimeout(function() {
self.canvas.width = self.cw = $(window).innerWidth();
self.canvas.height = self.ch = $(window).innerHeight();
self.ctx.lineCap = 'round';
self.ctx.lineJoin = 'round';
}, 100);
});
$(self.canvas).on('mousedown', function(e){
self.mx = e.pageX - self.canvas.offsetLeft;
self.my = e.pageY - self.canvas.offsetTop;
self.currentHue = rand(self.hueMin, self.hueMax);
self.createFireworks(self.cw/2, self.ch, self.mx, self.my);
$(self.canvas).on('mousemove.fireworks', function(e){
self.mx = e.pageX - self.canvas.offsetLeft;
self.my = e.pageY - self.canvas.offsetTop;
self.currentHue = rand(self.hueMin, self.hueMax);
self.createFireworks(self.cw/2, self.ch, self.mx, self.my);
});
});
$(self.canvas).on('mouseup', function(e){
$(self.canvas).off('mousemove.fireworks');
});
};
self.clear = function(){
self.particles = [];
self.fireworks = [];
self.ctx.clearRect(0, 0, self.cw, self.ch);
};
self.canvasLoop = function(){
requestAnimFrame(self.canvasLoop, self.canvas);
self.ctx.globalCompositeOperation = 'destination-out';
self.ctx.fillStyle = 'rgba(0,0,0,'+self.clearAlpha/100+')';
self.ctx.fillRect(0,0,self.cw,self.ch);
self.updateFireworks();
self.updateParticles();
self.drawFireworks();
self.drawParticles();
};
self.init();
}
var fworks = new Fireworks();
$('#info-toggle').on('click', function(e){
$('#info-inner').stop(false, true).slideToggle(100);
e.preventDefault();
});
});
</script>
<canvas width="1400" height="449"></canvas>
</body>
</html>

Fireworks(whole page)的更多相关文章

  1. Fireworks Extension —— AutoSlice 介绍

    前不久在网上到处瞎晃的时候,发现Adobe的软件几乎都可以写插件.Fireworks更是很早的版本就支持使用javascript编写插件,于是乎如入桃园,奋斗几日为VD小伙伴们写了一个插件,命名Aut ...

  2. Fireworks Extension —— 开发篇(Dom模型)

    如上一篇博文所叙述的,一个很偶然的机会,我得知可以使用Javascript开发Fireworks插件,又注意到了视觉小伙伴的需求,于是便上手开发Fireworks Extension了. 很幸运的,在 ...

  3. [label][Fireworks][转载] Web Slices - Fireworks CS5

    Web Slices – Fireworks CS5 http://bestwebdesignz.com/tips/fireworks/web-slices-fireworks-cs5/ Need a ...

  4. 我这么玩Web Api(一):帮助页面或用户手册(Microsoft and Swashbuckle Help Page)

    前言 你需要为客户编写Api调用手册?你需要测试你的Api接口?你需要和前端进行接口对接?那么这篇文章应该可以帮到你.本文将介绍创建Web Api 帮助文档页面的两种方式,Microsoft Help ...

  5. HTML5 Page Visibility

    什么是 Page Visibility ? Page Visibility 即页面可见性,通过 visibilityState 的值检测页面当前是否可见.当一个网站是可见或点击选中的状态时 Page ...

  6. angularjs 1 开发简单案例(包含common.js,service.js,controller.js,page)

    common.js var app = angular.module('app', ['ngFileUpload']) .factory('SV_Common', function ($http) { ...

  7. Selenium的PO模式(Page Object Model)[python版]

     Page Object Model 简称POM  普通的测试用例代码: .... #测试用例 def test_login_mail(self): driver = self.driver driv ...

  8. SharePoint2013 Set a custom application page as site welcome page

    本文主要介绍如何添加一个custom application page as site welcome page 1.首先创建一个sharepoint 2013 empty solution, add ...

  9. 使用page object模式抓取几个主要城市的pm2.5并从小到大排序后写入txt文档

    #coding=utf-8from time import sleepimport unittestfrom selenium import webdriverfrom selenium.webdri ...

随机推荐

  1. 对LCD接口的认识

    LCD接口类型: 1.首先我们以传递的信号类型来区分主要有两大类:- 模拟信号: - VGA: Video Graphics Array- 数字信号 - TTL: Transistor Transis ...

  2. Google Code Jam 资格赛: Problem A. Magic Trick

    Note: To advance to the next rounds, you will need to score 25 points. Solving just this problem wil ...

  3. 内核initcall分析

    linux中init相关内容定义在include/linux/init.h initcall相关定义 先看下文件说明,此文件定义的宏主要用于初始化阶段标记函数或初始化数据,之后占用的资源会被释放掉. ...

  4. 写shader注意的一些报错

    1.Shader warning in 'Custom/1': Both vertex and fragment programs must be present in a CGPROGRAM. Ex ...

  5. 已备份数据库的磁盘结构版本号为611,server支持版本号为539,无法还原或升级数据库

    提供的是bak文件是2005备份的,还原到本地的sqlserver2000,提示:已备份数据库的磁盘上结构版本号为611.服务器支持版本号539,无法还原或升级数据库. 网上找了下,原因是611是sq ...

  6. local variable 'xxx' referenced before assignment(犯过同样的错)

    这个问题很囧,在外面定义了一个变量 xxx ,然后在Python的一个函数里面引用这个变量,并改变它的值,结果报错local variable 'xxx' referenced before assi ...

  7. c3p0;jdbc;dbcp;mybatis;ubutils;

    [说明]今天还是完成了一定东西的,上午是jdbc的测试,下午是 数据库连接池 和 dbutils 的测试,晚上是mybatis的测试,都是找了一些网上的例子运行了一下,解决出现的问题. 一:今日完成 ...

  8. 装服务器,测试数据库,简单的maven命令

    [说明]今天总体回顾一下:大概是早上装服务器,下午测试数据库,晚上了解简单的maven命令 一:今日完成 1)在远程服务器的tomcat 设置好管理员的登录账号 2)登录tomcat 的项目管理 查看 ...

  9. Jmeter 03 Jmeter脚本开发

    JMeter 工作区介绍 JMeter Http 协议录制 JMeter 脚本调测 JMeter 关联 JMeter 参数化 JMeter 检查点 JMeter 事务 JMeter 集合点 JMete ...

  10. android菜鸟学习笔记21----ContentProvider(一)ContentProvider的简单使用

    ContentProvider是Android四大组件之一,它用来封装数据,并通过ContentResolver接口将数据提供给其他应用.只有当需要在多个应用之间共享数据时才会用到ContentPro ...