一、JS版本
<!--* @Author: LYM* @Date: 2024-07-26 13:51:47* @LastEditors: LYM* @LastEditTime: 2024-07-26 16:14:40* @Description: Please set Description
-->
<!DOCTYPE html>
<html>
<head><title>canvas动态气泡</title><style>body {margin: 0;overflow: hidden;}#jellyCanvas {display: block;width: 100%;height: 100%;}.container {width: 780px;height: 780px;margin: 0 auto;border-radius: 99px;filter: blur(64px);opacity: 1;}</style>
</head>
<body><div class="container"><canvas id="jellyCanvas"></canvas></div><script>// 获取Canvas元素和2D绘图上下文const canvas = document.getElementById('jellyCanvas');const ctx = canvas.getContext('2d');// 定义泡泡数组const bubbles = [];// 定义泡泡数量const numBubbles = 5;// 定义泡泡最大半径和最小半径const maxRadius = 50;const minRadius = 20;// 定义泡泡颜色const colors = ['#45abb5', '#abb3ff', '#73d4c7', '#abb3ff', '#455ed4'];// 定义一个函数来生成随机数function random(min, max) {return Math.random() * (max - min) + min;}// 设置2秒完成该动画const animationDuration = 2000;let startTime;// 定义一个构造函数来创建泡泡对象function Bubble(x, y, radius, color) {this.x = x;this.y = y;this.radius = radius;this.color = color;this.dx = random(-2, 2);this.dy = random(-2, 2);// 绘制泡泡this.draw = function () {ctx.beginPath();ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);// ctx.shadowColor = this.color;// ctx.shadowBlur = 20;ctx.fillStyle = this.color;ctx.fill();ctx.closePath();};// 更新泡泡位置this.update = function () {this.x += this.dx;this.y += this.dy;// 碰撞检测if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {this.dx = -this.dx;}if (this.y + this.radius > canvas.height || this.y - this.radius < 0) {this.dy = -this.dy;}};}// 创建泡泡并添加到数组中for (let i = 0; i < numBubbles; i++) {const x = random(maxRadius, canvas.width - maxRadius);const y = random(maxRadius, canvas.height - maxRadius);const radius = random(minRadius, maxRadius);const color = colors[Math.floor(random(0, colors.length))];bubbles.push(new Bubble(x, y, radius, color));}// 动画循环function animate() {// requestAnimationFrame(animate); // 动画速度太快 但是性能比较好setInterval(function(){ctx.clearRect(0, 0, canvas.width, canvas.height);// 绘制和更新每个泡泡for (let i = 0; i < numBubbles; i++) {bubbles[i].draw();bubbles[i].update();}}, 100)}// 启动动画animate();</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>彩色气泡动画</title>
<style> canvas { border: 1px solid black; }.container {width: 800px;height: 800px;margin: 0 auto;border-radius: 50%;/* filter: blur(64px); */opacity: 1;}
</style>
</head>
<body><div class="container"><canvas id="bubbleCanvas" width="800" height="800"></canvas> </div><script>class Bubble { constructor(x, y, radius, color, speedX, speedY) { this.x = x; this.y = y; this.radius = radius; this.color = color; this.speedX = speedX; this.speedY = speedY; } update() { this.x += this.speedX; this.y += this.speedY; // 气泡碰到边界时反弹 if (this.x + this.radius > canvas.width || this.x - this.radius < 0) { this.speedX = -this.speedX; } if (this.y + this.radius > canvas.height || this.y - this.radius < 0) { this.speedY = -this. Speedy; } } draw() { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); ctx.fillStyle = this.color; ctx.fill(); ctx.closePath(); }
} const canvas = document.getElementById('bubbleCanvas');
const ctx = canvas.getContext('2d'); const bubbles = []; // 初始化气泡
function initBubbles() { for (let i = 0; i < 5; i++) { let radius = Math.random() * 50 + 40; // 气泡大小 let x = Math.random() * (canvas.width - radius * 2) + radius; let y = Math.random() * (canvas.height - radius * 2) + radius; let color = `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 0.8)`; let speedX = (Math.random() - 0.5) * 2; let speedY = (Math.random() - 0.5) * 2; bubbles.push(new Bubble(x, y, radius, color, speedX, speedY)); }
} initBubbles(); function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); bubbles.forEach(bubble => { bubble.update(); bubble.draw(); }); requestAnimationFrame(animate);
} animate();
</script>
</body>
</html>
二、TS版本
/** @Author: LYM* @Date: 2024-07-26 15:08:43* @LastEditors: LYM* @LastEditTime: 2024-07-26 17:18:06* @Description: 生成动画显示一组彩色气泡*/
/*** 生成动画显示一组彩色气泡* @param params 参数对象,用于控制气泡的生成和显示* @param params.el HTML canvas元素* @param params.colors 气泡的颜色数组,默认为粉色系颜色* @param params.numBubbles 生成的气泡数量,默认为5* @param params.maxRadius 气泡的最大半径,默认为50* @param params.minRadius 气泡的最小半径,默认为20*/
export const generatedBubbles = (params: {el: anycolors: Array<string>numBubbles: numbermaxRadius: numberminRadius: number
}) => {const {el,colors = ['#45abb5', '#47c2b5', '#73d4c7', '#a3f7ed', '#455ed4'],numBubbles = 5,maxRadius = 50,minRadius = 20,} = params ?? {}// 获取Canvas元素和2D绘图上下文const canvas = el as anyconst ctx = canvas.getContext('2d')// 定义泡泡数组const bubbles = [] as Array<any>// 定义一个函数来生成随机数const random = (min: number, max: number) => {return Math.random() * (max - min) + min}// 定义一个构造函数来创建泡泡类class Bubble {x: numbery: numberradius: numbercolor: stringconstructor(x: number, y: number, radius: number, color: string) {this.x = xthis.y = ythis.radius = radiusthis.color = color}dx = random(-2, 2)dy = random(-2, 2)// 绘制泡泡draw() {ctx.beginPath()ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2)// ctx.shadowColor = this.color;// ctx.shadowBlur = 20;ctx.fillStyle = this.colorctx.fill()ctx.closePath()}// 更新泡泡位置update() {this.x += this.dxthis.y += this.dy// 碰撞检测if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {this.dx = -this.dx}if (this.y + this.radius > canvas.height || this.y - this.radius < 0) {this.dy = -this.dy}}}// 创建泡泡并添加到数组中for (let i = 0; i < numBubbles; i++) {const x = random(maxRadius, canvas.width - maxRadius)const y = random(maxRadius, canvas.height - maxRadius)const radius = random(minRadius, maxRadius)const color = colors[Math.floor(random(0, colors.length))]bubbles.push(new Bubble(x, y, radius, color))}// 动画循环const animate = () => {// requestAnimationFrame(animate); // 动画速度太快 但是性能比较好setInterval(() => {ctx.clearRect(0, 0, canvas.width, canvas.height)// 绘制和更新每个泡泡for (let i = 0; i < numBubbles; i++) {bubbles[i].draw()bubbles[i].update()}}, 90)}// 启动动画animate()
}
/** @Author: LYM* @Date: 2024-07-26 18:36:17* @LastEditors: LYM* @LastEditTime: 2024-07-26 18:59:04* @Description: 生成气泡动画*/
/*** 生成气泡动画** @param params 生成气泡动画的参数* @param params.el 绑定的canvas元素* @param params.colors 气泡颜色数组,默认为['#45abb5', '#abb3ff', '#47c2b5', '#5e73ff', '#8e59d7']* @param params.numBubbles 气泡数量,默认为5* @param params.baseRadius 基础半径,默认为10* @param params.speed 气泡移动速度,默认为1*/
export const generatedBubbles = (params: {el: anycolors: Array<string>numBubbles: numberbaseRadius: numberspeed: number
}) => {const {el,colors = ['#45abb5', '#abb3ff', '#47c2b5', '#5e73ff', '#8e59d7'],numBubbles = 5,baseRadius = 10,speed = 1,} = params ?? {}class Bubble {x: numbery: numberradius: numbercolor: stringspeedX: numberspeedY: numberconstructor(x: number,y: number,radius: number,color: string,speedX: number,speedY: number) {this.x = xthis.y = ythis.radius = radiusthis.color = colorthis.speedX = speedXthis.speedY = speedY}update() {this.x += this.speedXthis.y += this.speedY// 气泡碰到边界时反弹if (this.x + this.radius > canvas.width || this.x - this.radius < 0) {this.speedX = -this.speedX}if (this.y + this.radius > canvas.height || this.y - this.radius < 0) {this.speedY = -this.speedY}}draw() {ctx.beginPath()ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false)ctx.fillStyle = this.colorctx.fill()ctx.closePath()}}// 获取Canvas元素和2D绘图上下文const canvas = el as anyconst ctx = canvas.getContext('2d')// 定义泡泡数组const bubbles = [] as Array<any>// 初始化气泡for (let i = 0; i < numBubbles; i++) {const radius = Math.random() * baseRadius + 20 // 气泡大小const x = Math.random() * (canvas.width - radius * 2) + radiusconst y = Math.random() * (canvas.height - radius * 2) + radiusconst color = `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 0.8)`const speedX = (Math.random() - 0.5) * speedconst speedY = (Math.random() - 0.5) * speedbubbles.push(new Bubble(x, y, radius, colors[i] ?? color, speedX, speedY))}const animate = () => {ctx.clearRect(0, 0, canvas.width, canvas.height)bubbles.forEach(bubble => {bubble.update()bubble.draw()})requestAnimationFrame(animate)}animate()
}
三、效果
四、解释
- Bubble 类:定义了气泡的属性(位置、半径、颜色、速度)和方法(更新位置、绘制)。
- initBubbles 函数:初始化一组气泡,随机设置它们的位置、大小、颜色和速度。
- animate 函数:清除画布,更新每个气泡的位置,绘制所有气泡,并使用
requestAnimationFrame
递归调用自身以创建动画效果。
这个简单的例子展示了如何在<canvas>
上创建和动画化一组彩色气泡。你可以根据需要调整气泡的数量、大小、颜色、速度等属性,以及边界反弹的行为。