本文实例为大家分享了JavaScript实现带粒子效果进度条的具体代码,供大家参考,具体内容如下
<html>
<head>
<meta charset="utf8"/>
<!--
<meta name="viewport" content="width=device-width,user-scalable=no, initial-scale=1, maximum-scale=1" />
-->
<title>粒子效果实战</title>
<style type="text/css">
body {
background:#111;
}
#canvas {
background:transparent;
border:1px dashed #171717;
margin:-151px 0 0 -401px;
position:absolute;
left:50%;
top:50%;
}
</style>
</head>
<body onload="init()">
<canvas id="canvas" width="800px" height="300px">浏览器不支持canvas</canvas>
<script type="text/javascript">
//判断是否支持canvaas
function isSupportCanvas(canvas) {
return !!(canvas.getContext && canvas.getContext("2d"));
}
//requestAnimationFrame会自动使用最优的帧率进行渲染
function setupRAF() {
window.lastTime = 0;
//兼容各个浏览器,Internet Explorer11、Google Chrome(Microsoft Edge)、Mozilla Firefox、Opera
var vendors = ["ms", "moz", "webkit", "o"];
for(var i=0; i<vendors.length; i++) {
window.requestAnimationFrame = window[vendors[i] + "RequestAnimationFrame"];
window.cancelAnimationFrame = window[vendors[i] + "CancelAnimationFrame"] || window[vendors[i] + "CancelRequestAnimationFrame"];
//测试浏览器支持哪一张
if(window.requestAnimationFrame) {
console.log(vendors[i] + "requestAnimationFrame");
}
if(window[vendors[i] + "CancelAnimationFrame"]) {
console.log(vendors[i] + "CancelAnimationFrame");
}
if(window[vendors[i] + "CancelRequestAnimationFrame"]) {
console.log(vendors[i] + "CancelRequestAnimationFrame");
}
}
//回退机制
if(!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currentTime = new Date().getTime();
var timeToCall = Math.max(0, 16-(currentTime-window.lastTime));
var callTime = currentTime + timeToCall;
var id = window.setTimeout(function() {
callback(callTime);
}, timeToCall);
window.lastTime = callTime;
return id;
};
}
//回退机制
if(!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
}
}
}
//在[min, max]中随机取一个数
function rand(min, max) {
return Math.random() * (max - min + 1) + min;
}
//判断两碰撞盒是否相交
function isHit(x1, y1, w1, h1, x2, y2, w2, h2) {
return !( x1 + w1 < x2 || x2 + w2 < x1 || y1 + h1 < h2 || y2 + h2 < h1);
}
//判断点是否在指定区域内
function isInRect(x, y, rx, ry, rw, rh) {
return !(x < rx || x > rx + rw || y < ry || y > ry + rh);
}
//将数限制在某个范围之内
function limit(value, min, max) {
if(value < min) {
return min;
} else if(value > max) {
return max;
}
return value;
}
var CanvasController = function(canvas) {
var ctx = canvas.getContext("2d");
//进度条对象
var Loader = function() {
//进度条宽度
this.width = canvas.width - 80;
//进度条高度
this.height = 20;
//进度条X坐标
this.x = (canvas.width - this.width) / 2;
//进度条Y坐标
this.y = (canvas.height - this.height) / 2;
//进度条当前值
this.value = 0;
//进度条最大值
this.maxValue = 100;
//进度条更新速度
this.speed = .5;
//加深的颜色
this.lighterColor = "#222";
//HSL(Hue:色相,Saturation:饱和度,Lightness:饱和度)
this.hue = 0;
this.hueStart = 0;
this.hueEnd = 360;
//获取当前值对应的X坐标
this.currentPosX = function() {
return this.x + this.width * this.value / 100;
}
//更新进度条
this.update = function() {
this.value += this.speed;
if(this.value > this.maxValue) {
this.value = 0;
}
}
//渲染进度条
this.render = function() {
ctx.globalCompositeOperation = "source-over";
var currentWidth = this.width * this.value / 100;
this.hue = this.hueStart + (this.hueEnd - this.hueStart) * this.value / 100;
//ctx.fillStyle = "hsl(" + this.hue + ", 100%, 40%)";
var linearGradient = ctx.createLinearGradient(this.x, this.y, this.x + currentWidth, this.y);
linearGradient.addColorStop(0, "hsl(" + this.hueStart + ", 100%, 40%)");
linearGradient.addColorStop(1, "hsl(" + this.hue + ", 100%, 40%)");
ctx.fillStyle = linearGradient;
ctx.fillRect(this.x, this.y, currentWidth, this.height);
ctx.fillStyle = this.lighterColor;
ctx.globalCompositeOperation = "lighter";
ctx.fillRect(this.x, this.y, currentWidth, this.height/2);
}
}
//单个粒子对象
var Particle = function(x, y, hue, minX, maxX) {
//粒子的X坐标
this.x = x;
//粒子的Y坐标
this.y = y;
//粒子的宽度
this.width = rand(1,3);
//粒子的高度
this.height = rand(1,2);
//粒子的HSL颜色的hue分量
this.hue = limit(hue + rand(-15,15), 0, 360);
//粒子在X方向上的速度
this.velocityX = rand(-1,1);
//粒子在Y方向上的速度
this.velocityY = rand(-30,-20);
//粒子在X方向上的加速度
this.accelerationX = -.5;
//粒子在Y方向上的加速度
this.accelerationY = 4;
//单位时间
this.unitTime = .2;
//更新粒子位置
this.update = function() {
this.x += (this.velocityX * this.unitTime);
this.y += (this.velocityY * this.unitTime);
this.velocityX += (this.accelerationX * this.unitTime * rand(-1,1));
this.velocityY += (this.accelerationY * this.unitTime);
}
//渲染粒子
this.render = function() {
ctx.fillStyle = "hsl(" + this.hue + ", 100%, 40%)"
ctx.globalCompositeOperation = "source-over";
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
//所有粒子效果的对象
var Particles = function(minX, maxX) {
//存放生成的所有粒子对象
this.values = [];
//粒子生成速率
this.rate = 3;
//生成粒子
this.generate = function(x, y, hue) {
for(var i=0; i<this.rate; i++) {
this.values.push(new Particle(x, y, hue, minX, maxX));
}
}
//更新进度值
this.update = function() {
for(var i = this.values.length-1; i >= 0; i--) {
this.values[i].update();
if(!isInRect(this.values[i].x, this.values[i].y, 0, 0, canvas.width, canvas.height)) {
this.values.splice(i, 1);
}
}
}
//渲染进度条
this.render = function() {
for(var i =0; i<this.values.length; i++) {
this.values[i].render();
}
}
}
//清空画布
function clearCanvas() {
//默认值,表示图形将绘制在现有画布之上
ctx.globalCompositeOperation = "source-over";
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
//初始化函数
this.init = function() {
var loader = new Loader();
var particles = new Particles(loader.x, loader.x + loader.width);
var loop = function() {
requestAnimationFrame(loop, canvas);
clearCanvas();
loader.update();
loader.render();
particles.generate(loader.currentPosX()-3, loader.y + loader.height/2, loader.hue);
particles.update();
particles.render();
}
loop();
}
}
function init() {
var canvas = document.getElementById("canvas");
if(!isSupportCanvas(canvas)) {
return;
}
setupRAF();
var canvasController = new CanvasController(canvas);
canvasController.init();
}
</script>
</body>
</html>