canvas 绘制爱心 及鼠标点击显示爱心效果

鼠标点击显示爱心效果

(function (window, document, undefined) {
		var hearts = [];
		window.requestAnimationFrame = (function () {
			return window.requestAnimationFrame ||
				window.webkitRequestAnimationFrame ||
				window.mozRequestAnimationFrame ||
				window.oRequestAnimationFrame ||
				window.msRequestAnimationFrame ||
				function (callback) {
					setTimeout(callback, 1000 / 60);
				}
		})();
		init();
		function init() {
			css(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: absolute;}.heart:after{top: -5px;}.heart:before{left: -5px;}");
			attachEvent();
			gameloop();
		}
		function gameloop() {
			for (var i = 0; i < hearts.length; i++) {
				if (hearts[i].alpha <= 0) {
					document.body.removeChild(hearts[i].el);
					hearts.splice(i, 1);
					continue;
				}
				hearts[i].y--;
				hearts[i].scale += 0.004;
				hearts[i].alpha -= 0.013;
				hearts[i].el.style.cssText = "left:" + hearts[i].x + "px;top:" + hearts[i].y + "px;opacity:" + hearts[i].alpha + ";transform:scale(" + hearts[i].scale + "," + hearts[i].scale + ") rotate(45deg);background:" + hearts[i].color;
			}
			requestAnimationFrame(gameloop);
		}
		function attachEvent() {
			var old = typeof window.onclick === "function" && window.onclick;
			window.onclick = function (event) {
				old && old();
				createHeart(event);
			}
		}
		function createHeart(event) {
			var d = document.createElement("div");
			d.className = "heart";
			hearts.push({
				el: d,
				x: event.clientX - 5,
				y: event.clientY - 5,
				scale: 1,
				alpha: 1,
				color: randomColor()
			});
			document.body.appendChild(d);
		}
		function css(css) {
			var style = document.createElement("style");
			style.type = "text/css";
			try {
				style.appendChild(document.createTextNode(css));
			} catch (ex) {
				style.styleSheet.cssText = css;
			}
			document.getElementsByTagName('head')[0].appendChild(style);
		}
		function randomColor() {
			return "rgb(" + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + ")";
		}
	})(window, document);

canvas绘制爱心

css

* {
		padding: 0;
		margin: 0;
	}

	html,
	body {
		height: 100%;
		padding: 0;
		margin: 0;
		background: #000;
	}

	canvas {
		position: absolute;
		width: 100%;
		height: 100%;
	}

	.aa {
		position: fixed;
		left: 50%;
		bottom: 10px;
		color: #ccc
	}

html

<canvas id="pinkboard"></canvas>

js

<script>

		/*
		 * Settings
		 */
		var settings = {
			particles: {
				length: 500, // maximum amount of particles
				duration: 2, // particle duration in sec
				velocity: 100, // particle velocity in pixels/sec
				effect: -0.75, // play with this for a nice effect
				size: 30, // particle size in pixels
			},
		};

		/*
		 * Point class
		 */
		var Point = (function () {
			function Point(x, y) {
				this.x = (typeof x !== 'undefined') ? x : 0;
				this.y = (typeof y !== 'undefined') ? y : 0;
			}
			Point.prototype.clone = function () {
				return new Point(this.x, this.y);
			};
			Point.prototype.length = function (length) {
				if (typeof length == 'undefined')
					return Math.sqrt(this.x * this.x + this.y * this.y);
				this.normalize();
				this.x *= length;
				this.y *= length;
				return this;
			};
			Point.prototype.normalize = function () {
				var length = this.length();
				this.x /= length;
				this.y /= length;
				return this;
			};
			return Point;
		})();

		/*
		 * Particle class
		 */
		var Particle = (function () {
			function Particle() {
				this.position = new Point();
				this.velocity = new Point();
				this.acceleration = new Point();
				this.age = 0;
			}
			Particle.prototype.initialize = function (x, y, dx, dy) {
				this.position.x = x;
				this.position.y = y;
				this.velocity.x = dx;
				this.velocity.y = dy;
				this.acceleration.x = dx * settings.particles.effect;
				this.acceleration.y = dy * settings.particles.effect;
				this.age = 0;
			};
			Particle.prototype.update = function (deltaTime) {
				this.position.x += this.velocity.x * deltaTime;
				this.position.y += this.velocity.y * deltaTime;
				this.velocity.x += this.acceleration.x * deltaTime;
				this.velocity.y += this.acceleration.y * deltaTime;
				this.age += deltaTime;
			};
			Particle.prototype.draw = function (context, image) {
				function ease(t) {
					return (--t) * t * t + 1;
				}
				var size = image.width * ease(this.age / settings.particles.duration);
				context.globalAlpha = 1 - this.age / settings.particles.duration;
				context.drawImage(image, this.position.x - size / 2, this.position.y - size / 2, size, size);
			};
			return Particle;
		})();

		/*
		 * ParticlePool class
		 */
		var ParticlePool = (function () {
			var particles,
				firstActive = 0,
				firstFree = 0,
				duration = settings.particles.duration;

			function ParticlePool(length) {
				// create and populate particle pool
				particles = new Array(length);
				for (var i = 0; i < particles.length; i++)
					particles[i] = new Particle();
			}
			ParticlePool.prototype.add = function (x, y, dx, dy) {
				particles[firstFree].initialize(x, y, dx, dy);

				// handle circular queue
				firstFree++;
				if (firstFree == particles.length) firstFree = 0;
				if (firstActive == firstFree) firstActive++;
				if (firstActive == particles.length) firstActive = 0;
			};
			ParticlePool.prototype.update = function (deltaTime) {
				var i;

				// update active particles
				if (firstActive < firstFree) {
					for (i = firstActive; i < firstFree; i++)
						particles[i].update(deltaTime);
				}
				if (firstFree < firstActive) {
					for (i = firstActive; i < particles.length; i++)
						particles[i].update(deltaTime);
					for (i = 0; i < firstFree; i++)
						particles[i].update(deltaTime);
				}

				// remove inactive particles
				while (particles[firstActive].age >= duration && firstActive != firstFree) {
					firstActive++;
					if (firstActive == particles.length) firstActive = 0;
				}


			};
			ParticlePool.prototype.draw = function (context, image) {
				// draw active particles
				if (firstActive < firstFree) {
					for (i = firstActive; i < firstFree; i++)
						particles[i].draw(context, image);
				}
				if (firstFree < firstActive) {
					for (i = firstActive; i < particles.length; i++)
						particles[i].draw(context, image);
					for (i = 0; i < firstFree; i++)
						particles[i].draw(context, image);
				}
			};
			return ParticlePool;
		})();

		/*
		 * Putting it all together
		 */
		(function (canvas) {
			var context = canvas.getContext('2d'),
				particles = new ParticlePool(settings.particles.length),
				particleRate = settings.particles.length / settings.particles.duration, // particles/sec
				time;

			// get point on heart with -PI <= t <= PI
			function pointOnHeart(t) {
				return new Point(
					160 * Math.pow(Math.sin(t), 3),
					130 * Math.cos(t) - 50 * Math.cos(2 * t) - 20 * Math.cos(3 * t) - 10 * Math.cos(4 * t) + 25
				);
			}

			// creating the particle image using a dummy canvas
			var image = (function () {
				var canvas = document.createElement('canvas'),
					context = canvas.getContext('2d');
				canvas.width = settings.particles.size;
				canvas.height = settings.particles.size;
				// helper function to create the path
				function to(t) {
					var point = pointOnHeart(t);
					point.x = settings.particles.size / 2 + point.x * settings.particles.size / 350;
					point.y = settings.particles.size / 2 - point.y * settings.particles.size / 350;
					return point;
				}
				// create the path
				context.beginPath();
				var t = -Math.PI;
				var point = to(t);
				context.moveTo(point.x, point.y);
				while (t < Math.PI) {
					t += 0.01; // baby steps!
					point = to(t);
					context.lineTo(point.x, point.y);
				}
				context.closePath();
				// create the fill
				context.fillStyle = '#ea80b0';
				context.fill();
				// create the image
				var image = new Image();
				image.src = canvas.toDataURL();
				return image;
			})();

			// render that thing!
			function render() {
				// next animation frame
				requestAnimationFrame(render);

				// update time
				var newTime = new Date().getTime() / 1000,
					deltaTime = newTime - (time || newTime);
				time = newTime;

				// clear canvas
				context.clearRect(0, 0, canvas.width, canvas.height);

				// create new particles
				var amount = particleRate * deltaTime;
				for (var i = 0; i < amount; i++) {
					var pos = pointOnHeart(Math.PI - 2 * Math.PI * Math.random());
					var dir = pos.clone().length(settings.particles.velocity);
					particles.add(canvas.width / 2 + pos.x, canvas.height / 2 - pos.y, dir.x, -dir.y);
				}

				// update and draw particles
				particles.update(deltaTime);
				particles.draw(context, image);
			}

			// handle (re-)sizing of the canvas
			function onResize() {
				canvas.width = canvas.clientWidth;
				canvas.height = canvas.clientHeight;
			}
			window.onresize = onResize;

			// delay rendering bootstrap
			setTimeout(function () {
				onResize();
				render();
			}, 10);
		})(document.getElementById('pinkboard'));

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现canvas爱心点赞动画效果的步骤如下: 1. 创建一个canvas元素,并设置其宽高和背景色。 2. 在canvas绘制一个爱心图案,可以使用二次贝塞尔曲线来绘制。 3. 监听鼠标点击事件,当用户点击canvas时,获取鼠标点击的坐标,并在该位置绘制一个爱心。 4. 使用requestAnimationFrame()方法实现动画效果,每一帧都将所有爱心的位置向上移动一定距离,并且缩小其大小,直到其大小为0时,将其从数组中删除。 以下是实现canvas爱心点赞动画效果的示例代码: ```html <canvas id="canvas" width="500" height="500" style="background-color: #f5f5f5;"></canvas> ``` ```javascript const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const hearts = []; function drawHeart(x, y, size) { ctx.beginPath(); ctx.moveTo(x, y); ctx.bezierCurveTo(x + size / 2, y - size / 2, x + size, y, x + size, y + size / 2); ctx.bezierCurveTo(x + size, y + size, x + size / 2, y + size * 1.5, x, y + size * 1.5); ctx.bezierCurveTo(x - size / 2, y + size * 1.5, x - size, y + size, x - size, y + size / 2); ctx.bezierCurveTo(x - size, y, x - size / 2, y - size / 2, x, y); ctx.fillStyle = '#e74c3c'; ctx.fill(); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); hearts.forEach((heart, index) => { if (heart.size <= 0) { hearts.splice(index, 1); return; } heart.y -= heart.speed; heart.size -= heart.speed / 10; drawHeart(heart.x, heart.y, heart.size); }); requestAnimationFrame(draw); } canvas.addEventListener('click', (event) => { const x = event.clientX - canvas.offsetLeft; const y = event.clientY - canvas.offsetTop; hearts.push({ x, y, size: 30, speed: Math.random() * 5 + 5 }); }); draw(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值