<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title> Bubbles 泡沫</title>
<style>
body{
position: relative;
margin: 0;
}
canvas{
position: absolute;
cursor: crosshair;
}</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
function aa() {
var c = document.getElementById('c'),
$ = c.getContext('2d'),
w = c.width = window.innerWidth,
h = c.height = window.innerHeight;
var i, bubblesNumber = w * h > 750000 ? 200 : 150,
objects = [],
maxRadius = w * h > 500000 ? 50 : 35,
maxYVelocity = 2;
function randomInRange(min, max) {
return Math.random() * (max - min) + min;
}
function insertElementsAtIndex(index, arrayTo, arrayFrom, removeCount) {
var removed = false;
for (var i = arrayFrom.length - 1; i >= 0; i--) {
if (removeCount && !removed) {
arrayTo.splice(index, removeCount, arrayFrom[i]);
removed = true;
continue;
}
arrayTo.splice(index, 0, arrayFrom[i]);
}
}
function Vector(x, y) {
this.x = x || 0;
this.y = y || 0;
}
Vector.prototype.add = function(v) {
this.x += v.x;
this.y += v.y;
return this;
};
Vector.prototype.multiply = function(value) {
this.x *= value;
this.y *= value;
return this;
};
Vector.prototype.getMagnitude = function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
};
function Fragment(position, velocity, radius, hue) {
this.position = position;
this.velocity = velocity;
this.startSpeed = this.velocity.getMagnitude();
this.radius = radius;
this.hue = hue;
}
Fragment.prototype.update = function(world) {
this.velocity.multiply(world.physicalProperties.friction);
this.position.add(this.velocity);
this.radius *= this.velocity.getMagnitude() / this.startSpeed;
if (this.radius < 0.1) {
world.objects.splice(world.objects.indexOf(this), 1);
}
}
Fragment.prototype.render = function($) {
$.beginPath();
$.fillStyle = 'hsl(' + this.hue + ', 100%, 50%)';
$.arc(this.position.x, this.position.y, this.radius, 0, Math.PI * 2);
$.fill();
};
function Bubble(x, y, speed, radius, fragments, swing, hue) {
this.x = x;
this.y = y;
this.startX = this.x;
this.speed = speed;
this.radius = radius;
this.fragments = fragments;
this.swing = swing;
this.hue = hue;
}
Bubble.prototype.update = function(world) {
this.x = this.startX + Math.cos(this.y / 80) * this.swing;
this.y += this.speed;
if (this.y + this.radius < 0) {
this.y = world.physicalProperties.height + this.radius;
}
}
Bubble.prototype.render = function($) {
$.beginPath();
$.fillStyle = 'hsl(' + this.hue + ', 100%, 50%)';
$.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
$.fill();
};
Bubble.prototype.pop = function(world) {
var arr = [];
for (var i = 0; i < this.fragments; i++) {
arr.push(new Fragment(new Vector(this.x, this.y), new Vector(randomInRange(-2, 2), randomInRange(-2, 2)), randomInRange(2, this.radius / 4), this.hue));
}
insertElementsAtIndex(world.objects.indexOf(this), world.objects, arr, 1);
};
function World(physicalProperties, objects, ctx, background) {
this.physicalProperties = physicalProperties;
this.objects = objects;
this.ctx = ctx;
this.background = background;
this.frameID = 0;
}
World.prototype.update = function() {
for (var i = 0; i < this.objects.length; i++) {
this.objects[i].update(this);
}
};
World.prototype.render = function() {
this.ctx.clearRect(0, 0, this.physicalProperties.width, this.physicalProperties.height);
if (this.background) {
this.ctx.fillStyle = this.background;
this.ctx.fillRect(0, 0, this.physicalProperties.width, this.physicalProperties.height);
}
for (var i = 0; i < this.objects.length; i++) {
this.objects[i].render(this.ctx);
}
};
World.prototype.animate = function() {
this.update();
this.render();
this.frameID = requestAnimationFrame(this.animate.bind(this));
};
for (i = 0; i < bubblesNumber; i++) {
objects.push(new Bubble(Math.random() * w, Math.random() * h, -randomInRange(0.5, maxYVelocity), randomInRange(5, maxRadius), randomInRange(7, 10), randomInRange(-40, 40), randomInRange(0, 360)));
}
var world = new World({
width: c.width,
height: c.height,
friction: 0.997
}, objects, $, 'rgb(0, 50, 255)');
$.globalCompositeOperation = 'lighter';
world.animate();
window.addEventListener('resize', function() {
w = world.physicalProperties.width = c.width = window.innerWidth;
h = world.physicalProperties.height = c.height = window.innerHeight;
$.globalCompositeOperation = 'lighter';
});
window.addEventListener('mousemove', function(e) {
for (var i = 0; i < world.objects.length; i++) {
if ((world.objects[i] instanceof Bubble) && (e.clientX > world.objects[i].x - world.objects[i].radius && e.clientX < world.objects[i].x + world.objects[i].radius && e.clientY < world.objects[i].y + world.objects[i].radius && e.clientY > world.objects[i].y - world.objects[i].radius)) {
world.objects[i].pop(world);
}
}
});
window.addEventListener('touchmove', function(e) {
for (var i = 0; i < world.objects.length; i++) {
if ((world.objects[i] instanceof Bubble) && (e.touches[0].clientX > world.objects[i].x - world.objects[i].radius && e.touches[0].clientX < world.objects[i].x + world.objects[i].radius && e.touches[0].clientY < world.objects[i].y + world.objects[i].radius && e.touches[0].clientY > world.objects[i].y - world.objects[i].radius)) {
world.objects[i].pop(world);
}
}
});
};
aa();</script>
</body>
</html>
html5 canvas实现的悬浮泡泡上升,鼠标滑过泡沫破裂动画特效源码.zip
版权申诉
58 浏览量
2022-11-03
23:35:53
上传
评论
收藏 2KB ZIP 举报
毕业_设计
- 粉丝: 1932
- 资源: 1万+
最新资源
- 基于pytorch+Unet进行MRI肝脏图像分割源码+数据集+模型.zip
- 在Android Studio中开发一个Android App项目步骤
- 基于yolov8实现进行物体跟踪源码.zip
- Java多线程学习Java多线程学习Java多线程学习Java多线程学习.txt
- 算法数据结构-动态规划算法(Dynamic Programming)超详细总结加应用案例讲解.txt
- 2024最强秋招八股文(精简、纯手打)2024最强秋招八股文(精简、纯手打).txt
- 基于tensorflow多特征融合的微表情识别python源码.zip
- 基于yolov8实现人脸检测的python源码+运行说明.zip
- Micron Memory DDR3 SDRAM 全系列AD集成库(原理图库+PCB封装库).IntLib
- 基于tensorflow多特征融合的微表情识别python源码+详细使用说明.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈