❤521到了, 码农翻身;
模仿微信聊天发送关键字 么么哒
触发表情包雨😘
的效果;
520遇见你
开始
使用了parcel;
其实不要也可以,并没有用到什么,主要是自己想使用sass
预编译语法,嵌套使用;
这次分享主要是如何实现这个动画效果的;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <body> <div id="root"> <div id="phone"> <div id="header">宝贝❤</div> <div id="main"> <div id="keyword"> <p class="myself" style="--name:'我'">在吗?</p> <br> <p class="myself" style="--name:'我'">在干嘛?</p> <p class="opposite" style="--name:'宝贝'">多喝烫水!</p> </div> <div class="bg theme"></div> <div id="animation"></div> </div> <div id="footer"> <input type="text" id="message" maxlength="255" /> <button id="send">发送</button> </div> </div> </div> </body>
|
1 2 3 4 5 6 7 8 9
| const $ = str => document.querySelector(str); const myRandom = (min = 0, max = min + 1) => Math.random() * (max - min + 1) + min; const elObj = { root: $('#root'), animation: $('#animation'), message: $('#message'), send: $('#send') }
|
实现动画 createAnimation
方法
1 2 3 4 5 6 7 8
| const createAnimation = icon => { let logo = icon; if (Array.isArray(icon)) { const index = myRandom(0, icon.length - 1) logo = icon[Math.floor(index)]; } }
|
1 2 3 4
| const { width, height, top, bottom } = elObj.main.getBoundingClientRect(); const count = Math.round(width * height / 5000); const averageCount = Math.round(width / 65); const fw = width / averageCount;
|
1 2 3 4 5 6
| [...Array(count).keys()].forEach(index => { let childEl = document.createElement('i'); const left = (myRandom(1, fw) + fw) * (index % averageCount) + 'px'; })
|
1 2 3 4 5 6 7 8
| childEl.classList = 'icon-itme'; childEl.innerText = logo || '😘' childEl.style.left = left childEl.style.position = 'absolute' childEl.style.fontSize = '32px'; childEl.style.transform = `translate(${left},${-50}px)`;
childEl.style.transition = `transform ${myRandom(3, 6)}s linear ${myRandom(1, 2)}s`;
|
1 2 3 4 5
| setTimeout(() => { childEl.style.transform = `translate(${myRandom(1, fw)}px,${height + 50}px) rotate(${myRandom(-90, 90)}deg)` }, 0)
|
这里不用setTimeout
浏览器会默认使用第二个动画,使用就不会有动画效果实现;
大家可以先去了解浏览器event-loop
;
这里有一篇文章可以参考一下【第1405期】浏览器的 Event Loop
1 2 3 4 5
| childEl.addEventListener('transitionend', ({ target }) => { target.parentNode.removeChild(target); }) elObj.animation.appendChild(childEl);
|
到这里,我的整个创建表情包雨的效果已近完成了;
至于如何通过发送消息匹配关键字我使用了正则表达式;
触发关键字
1 2 3 4 5 6
| export default { '么么哒': '😘', '猪': ['🐖', '🐽', '🐷', '🐗'], '爱|love': ['❤', '💕'], '大便|粑粑': '💩', }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const HTMLEncode = html => { const el = document.createElement("div"); el.textContent ? el.textContent = html : el.innerText = html return el.innerHTML; }
const pushMessage = (str, name, ismyself) => { if (!str) return false; var html = ` <p class="${ismyself ? 'myself' : 'opposite'}" style="--name:'${name}'">${HTMLEncode(str)} </p> ` elObj.keyword.innerHTML += html; elObj.main.scrollTop = elObj.keyword.scrollHeight const find = Object.keys(keyword).find(key => new RegExp(key, 'ig').test(str)) const icon = keyword[find]; icon && createAnimation(icon) }
|
1 2 3 4 5
| elObj.send.addEventListener('click', () => { const inputval = elObj.message.value; inputval && pushMessage(inputval, '我', true); elObj.message.value = ''; })
|
到这里整个项目的代码就完成了;有一些样式我偷懒了还有些问题;
但今天我和大家分享的是动画效果的实现;
明年520在修复;
代码我放到了GitHub上了项目代码;
我建立了第一个issues
欢迎大家帮助我;
很多关键字匹配表情包没有完成,欢迎大家Fork
和pull requests
完善我们的项目;
在这里你可以添加你的代码;
🌰example
我需要添加一个 男人
和 man
key
是关键字,多个可以用 |
区分
value
是匹配的表情包,多个可以用 Array
类型,如果就一个可以直接添加Emoji
1 2 3 4 5
| export default { '男人|man': '👨', '女人|girl': ['👧', '👧🏻'] }
|