用canvas实现节日孔明灯放飞功能

您所在的位置:网站首页 canvas代码无用 用canvas实现节日孔明灯放飞功能

用canvas实现节日孔明灯放飞功能

2023-03-13 10:44| 来源: 网络整理| 查看: 265

做一个在线的孔明灯许愿,既环保又绿化,又可以寄托许愿者的美好愿望,先看效果:

1.gif

制作思路:

孔明灯有二种:第一种,背景飘动的一群假孔明灯,第二种,是一个图片,用户实际放飞的孔明灯

制作背景孔明灯思路

2.png

1、轮廓制作思路:画一个孔明灯,计算每个点的坐标值,划线,最下面的线是有一点弧度的,用了赛贝尔曲线,整体颜色使用渐变填充

2、文字制作思路:给孔明灯加上随机文字,文字我用了一个数组,里面存了几个默认的祝福语,随机赋值给不同的孔明灯

3、飞行思路:根据屏幕宽度,计算需要多少孔明灯,给这些孔明灯定制:随机大小,随机轨迹,随机速度,和随机透明度,遇到屏幕方向变化的处理

制作点击放飞的前景孔明灯思路

3.png

1、图片:在网上找一个喜欢的孔明灯图片,photoshop抠图切割,以canvas加载图片方式加入

2、输入框:制作屏幕左下角的输入框和放飞按钮,输入文字字数限制

3、dom点击:输入框许愿文字赋值给孔明灯,调整文字在孔明灯上的大小和位置调整

4、飞行轨迹:起始位置高度在屏幕最下方,宽度中间,缓慢上升,左右方向随机,飞行速度随机,为了实现飞远效果,设置了上升过程逐渐变小,设置了最小值,达到最小值就不会再变小了,设置遇到屏幕边界处理方法。

剩余细节处理

1、背景夜色图片

2、飘动的小光点

github地址

代码我用vue写的,下载后,npm i 一下,就可以运行,直属代码在Test.vue里面了

github.com/alian1128/k…

代码解析 1、画背景孔明灯

分析孔明灯的形状:设置点坐标,最下面的边是弧度的,中间有一条分割线,标明了坐标的位置

4.png

代码如下:

moveto 是把画笔移动某个坐标,lineto是划线,赛贝尔曲线三个参数的意义我就不说了,有在线测试赛贝尔曲线的,可以搜一下在上面感受学习。

//---------画孔明灯外形 begin this.ctx.beginPath(); this.ctx.moveTo(x + 10 * scale, y + 10 * scale); //左上 this.ctx.lineTo(x + 20 * scale, y + 38 * scale); //左下 this.ctx.quadraticCurveTo( x + 25 * scale, y + 41 * scale, x + 30 * scale, y + 38 * scale ); //赛贝尔曲线给最下面边,增加弧度 this.ctx.lineTo(x + 30 * scale, y + 38 * scale); //右下 this.ctx.lineTo(x + 40 * scale, y + 10 * scale); //右上 this.ctx.lineTo(x + 25 * scale, y); //顶部 this.ctx.closePath(); this.ctx.fill(); //画中间的那一条分割线, this.ctx.moveTo(x + 25 * scale, y); //顶部 this.ctx.lineTo(x + 25 * scale, y + 38 * scale); //顶部中间 var lingrad2 = this.ctx.createLinearGradient( x + 25 * scale, y + 0 * scale, x + 40 * scale, y + 30 * scale ); lingrad2.addColorStop(0, "#000"); lingrad2.addColorStop(1, "#ff8d1a"); this.ctx.strokeStyle = lingrad2; //增加渐变 this.ctx.lineWidth = 0.3; this.ctx.stroke(); //---------孔明灯外形 end 复制代码

2、给孔明灯加文字:使用filltext,四个参数,分别是文字内容,x轴位置,y轴位置,文字大小, 文字内容从数组下标0-10随机拿,文字大小我使用了0-1之间随机数乘以19

const textarr = ["股票", "回本","祖国","统一","国庆","快乐", "安康", "涨薪","平安", "如意", "暴富", "不卷"]; const randomtext = Math.ceil(p.scaleText * 10); //随机取一个词 //赋值给孔明灯文字 this.ctx.fillText( textarr[randomtext], x + 15 * scale, y + 22 * scale, scale * 19 ); 复制代码

3、循环:循环出很多灯,并且让这些灯动起来,这就需要requestAnimationFrame函数,用于实现动画效果。

requestAnimationFrame 我是这样理解的,每秒钟大概执行60次左右它的回调函数,只要我们随机加减x和y的位置,就看起来像是在动移动,实际上不是真的在移动,而是像电影一样一帧一帧的刷新

前景孔明灯

先声明好image,然后用drawImage 来画图,

mounted() { this.imageObj = new Image(); this.imageObj.src = "/44.png"; requestAnimationFrame(this.drawOneLine); // 在此调用requestAnimationFrame回调单个大孔明灯的函数 } methods: { fly() { const one ={} //存放灯的变量 this.arrclickFly.push(one); //点击一次存入数组一个变量 }, drawOneLine(timer) { this.arrclickFly.forEach((item) => { //循环许愿灯的数组,画图 this.ctx.drawImage( this.imageObj, item.p.x, item.p.y, item.size, item.size ); }, } 复制代码

点击放飞按钮的时候,调用fly方法,给数组增加arrclickFly孔明灯的数量。在drawOneLine回调函数中回循环这个数组,然后给每个孔明灯计算位置,速度,缩放大小。

mounted() { this.imageObj = new Image(); this.imageObj.src = "/44.png"; requestAnimationFrame(this.drawOneLine); // 在此调用requestAnimationFrame回调单个大孔明灯的函数 } methods: { fly() { const text = this.$refs.text.value; if (text.length > 10) { this.message = "请输入10个字符以内的祝福"; return; } const rany = this.binRandom(0.5); const one = { p: { x: this.width / 2, y: this.height - 200 }, v: { x: this.binRandom(0.5) ? this.random(1) : this.random(-1), y: rany < 0.2 ? 0.2 : rany, }, o: this.random(1) + 0.3, scale: 5, scaleText: text, size: 200, }; this.arrclickFly.push(one); this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); }, drawOneLine(timer) { this.arrclickFly.forEach((item) => { this.ctx.drawImage( this.imageObj, item.p.x, item.p.y, item.size, item.size ); item.p.x += item.v.x; item.p.y -= item.v.y; item.size = item.size - 0.05; //孔明灯越飞越远, if (item.p.x > this.width + 20 || item.p.x < -60) item.v.x *= -1; //x轴的位置乘以速度,碰到浏览器边缘返回 if (item.p.y > this.height || item.p.y < -60) item.v.y *= -1; //y轴的位置乘以速度,碰到浏览器边缘返回 if (item.size


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3