情人节H5页面,一个程序猿的小小心意

阅读: 评论:0

情人节H5页面,一个程序猿的小小心意

情人节H5页面,一个程序猿的小小心意

初衷

情人节快到了,本人一直在外地,没能回家,和女友也无法dating,于是想给她一点特别的小惊喜。不知怎么想的,写个H5吧,女友在这方面见识得不多,应该会喜欢吧。

调了几个元素:雪花(最后并没有具象成雪花状,用了白色半透明圆点来替代)、文字粒子化。

这个创意很早以前就有了,13年HTML5刚风行的时候,就有google的大神写了一个粒子化的神作,后来也不断有人模仿。

原理

利用canvas 的 imageData 这个对象,我们可以取到当前canvas 里面具有rgba信息的点。有着这个,我们就可以操控已有的粒子去填充那些点,这样我们不但可以粒子化文字,图片、符号等等,只要是能画上canvas 的,都可以用这种方法粒子化。

实现思路

首先我们初始化一堆粒子,并让它们在canvas里面以不同的速度不同的角度运动。 变量定义:

data: function () {return {context: "HAPPY Valentine's DAY", // 文字内容can: null, // canvascxt: null, // canvas contextwidth: window.innerWidth, // 屏幕宽度height: window.innerHeight, // 屏幕高度particles: [],  //在背景中运动的粒子particlesToBeMoved: [],  //被选中去填充文字的粒子points: [], //imageData中选出来的电particleNum: 1500, //可用的粒子数,可以自定义intervalId: 0, // setinterval id,方便取消power: 1  //  倍率}},
复制代码

功能函数:

1、initBackground 是用来初始化particles 给每个粒子都随机化赋予了坐标、弧度、透明度等等,这里的moveDirec 是它之后运动的方向 2、draw 函数是用来绘制particles中的粒子 3、moveRestParticles实现按照moveDirect进行移动的功能。我们还做了判断,如果遇到墙壁,则反弹。

    initBackground: function () {this.can = ElementById('canvas') = this .Context('2d')for (let i = 0; i < this.particleNum; i++) {this.particles.push({position: {x: Random(this.width), y: Random(this.height)},moveDirec: {x: Math.random() > 0.5 ? Math.random() * 5 : -Math.random() * 5, y: Math.random() > 0.5 ? Math.random() * 5 : -Math.random() * 5},size: Random(1) * 0.5,opacity: Random(1)})}},draw: function () {learRect(0, 0, this.can.width, this.can.height)at(this.particlesToBeMoved).forEach(p => {fillStyle = 'rgba(255, 255, 255, ' + p.opacity + ')&#beginPath()arc(p.position.x, p.position.y, p.size * 10, 0, 2 * Math.PI, fill()})},moveRestParticles: function () {this.particles.forEach(p => {p.position.x += p.moveDirec.xp.position.y += p.moveDirec.yif (p.position.x > this.width || p.position.x <= 0) {p.moveDirec.x = -p.moveDirec.x}if (p.position.y > this.height || p.position.y <= 0) {p.moveDirec.y = -p.moveDirec.y}})this.draw()}
复制代码

我们只要用 veRestParticles, 10) 就能让粒子动起来了。

第一步就完成了,下面要完成文字像素提取,并且移动粒子到像素点。

makeWords 是将文字显示在canvas 上 getPoint 是获取刚在画在canvas 上的文字的像素信息,也就是开头提到的 imageData 我们把符合条件的点(point) 放在数组里。这里的筛选方法是不完全的,也就是,我们并没有把全部点都筛选出来,而是筛选了一部分,因为如果全部筛选的话,会使得粒子数量庞大,在视觉上显得是很凌乱。如果你想的话,可以吧 x+=4 y+=4 修改成 x+=1 y+=1

    makeWords: function (word, cxt) {cxt.font = '80px Adele bold'cxt.fillStyle = 'rgba(100, 100, 100, 256)'cxt.fillText(word, this.can.width / 10, this.can.height / 4)cxt.save()},getPoint: function (can) {let cxt = Context('2d')let imgData = ImageData(0, 0, can.width, can.height)let points = []for (let x = 0; x < imgData.width; x += 4) {for (let y = 0; y < imgData.height; y += 4) {let i = (y * imgData.width + x) * 4if (imgData.data[i] <= 128 && imgData.data[i + 1] <= 128 && imgData.data[i + 2] <= 128 && imgData.data[i + 3] >= 128) {let point = new Point(x - 3, y - 3, cxt)points.push(point)}}}return points}
复制代码

showWords 是入口函数,用了Promise 是方便后面控制多个语句的显示。

makeAnitation 是移动像素点,我们先打乱了粒子,让画面看上去更自然。后面的移动函数就很简单了,一看就能懂。

    showWords: function () {return new Promise((resolve, reject) => {this.t, )this.points = Point(this.learRect(0, 0, this.can.width, this.can.height)if (this.points.length > this.particleNum) {console.log(this.points.length)console.log('超出数量')resolve()} else {this.makeAnimation()setTimeout(resolve, 10000)}})},makeAnimation: function () {this.shuffleParticle()ParticlesToBeMoved()this.judgeTheDirect()this.intervalId = veParticles, 10)},clearAnimation: function () {clearInterval(this.intervalId)this.particles.push(...this.particlesToBeMoved)this.particlesToBeMoved = []this.intervalId = veRestParticles, 10)},shuffleParticle: function () {this.particles = _.shuffle(this.particles)},getParticlesToBeMoved: function () {for (let i = 0; i < this.points.length; i++) {this.particlesToBeMoved.push(this.particles.shift())}},judgeTheDirect: function () {for (let i = 0; i < this.points.length; i++) {if (this.points[i].x - this.particlesToBeMoved[i].position.x < 0) {this.points[i].dx = -this.points[i].dx}if (this.points[i].y - this.particlesToBeMoved[i].position.y < 0) {this.points[i].dy = -this.points[i].dy}if (this.points[i].size - this.particlesToBeMoved[i].size < 0) {this.points[i].ds = -this.points[i].ds}if (this.points[i].opacity - this.particlesToBeMoved[i].opacity < 0) {this.points[i].do = -this.points[i].do}}},moveParticles: function () {for (let i = 0; i < this.points.length; i++) {if (Math.abs(this.points[i].x - this.particlesToBeMoved[i].position.x) <= Math.abs(this.points[i].dx) || this.particlesToBeMoved[i].position.x < 0) {this.particlesToBeMoved[i].position.x = this.points[i].x} else {this.particlesToBeMoved[i].position.x += this.points[i].dx}if (Math.abs(this.points[i].y - this.particlesToBeMoved[i].position.y) <= Math.abs(this.points[i].dy) || this.particlesToBeMoved[i].position.y < 0) {this.particlesToBeMoved[i].position.y = this.points[i].y} else {this.particlesToBeMoved[i].position.y += this.points[i].dy}if (Math.abs(this.points[i].size - this.particlesToBeMoved[i].size) <= Math.abs(this.points[i].ds) || this.particlesToBeMoved[i].size < 0) {this.particlesToBeMoved[i].size = this.points[i].size} else {this.particlesToBeMoved[i].size += this.points[i].ds}if (Math.abs(this.points[i].opacity - this.particlesToBeMoved[i].opacity) <= Math.abs(this.points.do) || this.particlesToBeMoved[i].opacity < 0) {this.particlesToBeMoved[i].opacity = this.points[i].opacity} else {this.particlesToBeMoved[i].opacity += this.points[i].do}}veRestParticles()//  this.draw()},
复制代码

最后放一下效果图:

完整代码详见github

本文发布于:2024-01-28 06:16:08,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063937715396.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:情人节   心意   页面   程序
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23