事情是这样的,前天上午产品经理说想要做一个心愿墙,问我能不能行
我心想,这太容易了,但为了多摸一天鱼,我说还是有点挑战 的
结果下午,产品经理和设计师就给我发来了设计参考
他们说,心愿墙的设计大致是这样的,每个用户的心愿都是一个气泡,而客户的品牌是”龙“,我们希望在前端页面里用气泡呈现一个龙形的设计,每个气泡都会浮动,鼠标移上去变大,点击后展示心愿详情。
当时我的内心是这样的
我摸鱼的一天要泡汤了吗?
谁都不能阻止我摸鱼
但首先要解决最核心的问题
龙从哪里来? 设计师说了,他可以给我一条由气泡组成的龙的设计稿,我说那等你设计稿给我,我再研究把。结果他说,已经有了,你就用这个吧
我的刀呢?
互动问题
请在评论区留下你遇到过的最奇葩的需求
拆解需求 遇到不靠谱的产品经理和设计师,前端工程师真是惨。我们顶着最后交付成品的巨锅
,所有deadline
感觉都只是用来压榨前端工程师的。
我们只能靠自己,因为
谁都不能阻止我摸鱼
需求1:有鼠标交互效果(太简单)
需求2:气泡要浮动(css动画,easy)
需求3:气泡组成一条龙
此时我脑海里响起这首烂大街的歌
左边跟我一起画个龙,在你右边画一道彩虹~
1 2 3 诶,画个龙 用什么画,canvas canvas能获得指定区域的像素点阵
卧槽,有招儿了
代码时间 先用图片搜索找一张龙的剪影
将图片绘制到canvas中 1 2 3 4 5 6 7 8 9 10 11 12 var canvas = document .getElementById("canvas" );var ctx = canvas.getContext("2d" );var image = new Image();image.src = "dragon.jpg" ; image.onload = function ( ) { canvas.width = image.width; canvas.height = image.height; ctx.drawImage(image,0 ,0 ); } 复制代码
获取并裁剪画布的点阵信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 var imageData = ctx.getImageData(0 ,0 ,image.width,image.height).data;ctx.fillStyle = "#ffffff" ; ctx.fillRect(0 ,0 ,image.width,image.height); var gap = 6 ;for (var h = 0 ; h < image.height; h+=gap) { for (var w = 0 ; w < image.width; w+=gap){ var position = (image.width * h + w) * 4 ; var r = imageData[position], g = imageData[position + 1 ], b = imageData[position + 2 ]; if (r+g+b==0 ){ ctx.fillStyle = "#000" ; ctx.fillRect(w,h,4 ,4 ); } } } 复制代码
现在我们获得了这样一条龙的点阵信息
通过点阵信息生成气泡dom 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var dragonContainer = document .getElementById("container" );var dragonScale = 2 ;for (var h = 0 ; h < image.height; h+=gap) { for (var w = 0 ; w < image.width; w+=gap){ var position = (image.width * h + w) * 4 ; var r = imageData[position], g = imageData[position + 1 ], b = imageData[position + 2 ]; if (r+g+b==0 ){ var bubble = document .createElement("img" ); bubble.src = "bubble.png" ; bubble.setAttribute("class" ,"bubble" ); var bubbleSize = Math .random()*10 +20 ; bubble.style.left = (w*dragonScale-bubbleSize/2 ) + "px" ; bubble.style.top = (h*dragonScale-bubbleSize/2 ) + "px" ; bubble.style.width = bubble.style.height = bubbleSize+"px" ; bubble.style.animationDuration = Math .random()*6 +4 + "s" ; dragonContainer.appendChild(bubble); } } } 复制代码
作者:大帅老猿链接:https://juejin.cn/post/6963476650356916254 来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
关于疑问 var position = (image.width * h + w) * 4; 公式获取当前点?
参考原码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" /> <meta http-equiv ="X-UA-Compatible" content ="IE=edge" /> <meta name ="viewport" content ="width=device-width, initial-scale=1.0" /> <title > Document</title > <style > * { margin : 0 ; padding : 0 ; } .bubble { position : absolute; background-color : red; } .wrap { position : relative; position : absolute; top : 0 ; } canvas { box-sizing : border-box; } .wrap > div { position : absolute; transition : all 0.5s ; cursor : pointer; } .wrap > div :hover { transform : scale (20 ); z-index : 999 ; } </style > </head > <body > <canvas id ="canvas" > </canvas > <div class ="wrap" > </div > </body > </html > <script > var canvas = document .getElementById("canvas" ); var ctx = canvas.getContext("2d" ); var list = [{ x : -100 , y : -100 }]; var image = new Image(); image.src = "dragon.jpg" ; image.onload = function ( ) { canvas.width = image.width; canvas.height = image.height; ctx.drawImage(image, 0, 0); var imageData = ctx.getImageData(0 , 0 , image.width, image.height).data; function fn ( ) { var gap = 6 ; var dragonScale = 2 ; for (var h = 0 ; h < image.height; h += gap) { for (var w = 0 ; w < image.width; w += gap) { var position = (image.width * h + w) * 4 ; var r = imageData[position], g = imageData[position + 1], b = imageData[position + 2]; if (r + g + b >= 0 && r + g + b <= 159) { let w1 = w - 10 ; let h1 = h - 10 ; var fillStyle = `rgba(${parseInt (Math .random() * 255 )} ,${parseInt ( Math .random() * 255 )},${parseInt (Math .random() * 255 )})`; var bubble = document .createElement("div" ); var bubbleSize = Math .random() * 10 + 20 ; bubble.style.left = w1 + "px" ; bubble.style.top = h1 + "px" ; bubble.style.width = "5px" ; bubble.style.height = "5px" ; bubble.style.animationDuration = Math .random() * 6 + 4 + "s" ; bubble.style.backgroundColor = fillStyle; console .log(document .getElementsByClassName("wrap" )[0 ]); document .getElementsByClassName("wrap" )[0 ].appendChild(bubble); } } } } fn(); setInterval (() => { fn(); }, 3000); ctx.clearRect(0, 0, image.width, image.height); }; </script >
效果图