评论区表情包放大
一般情况下评论区的表情宽和高是固定显示,所以有些尺寸相对较大的表情包是缩放显示的,模糊不说还可能导致误解表情包的含义,本教程为表情图案添加了一个简单的放大弹出层,非常的实用。
教程 其实实现的原理很简单,就是创建一个盒子,将表情包的内容放在盒子里面,再读取图片的 Alt 等描述属性现在在盒子中,最后控制盒子位置和显示隐藏即可。而在表情包放大逻辑方面,基本属性为:2 倍放大显示,最大显示宽高为 200px(如若超过,按比例对应缩小)。
实现 具体到实现,就是利用 observer
观察评论区元素新增的节点,根据相关选择器过滤出含表情包的节点,添加对应的事件,以 Artalk 评论系统为例处理到的选择器为:
const dom = mutations[i].addedNodes if (dom[0 ]?.classList ?.contains ('atk-grp' ) || dom[0 ]?.classList ?.contains ('atk-comment-wrap' ) || (!!dom[0 ]?.attributes && !!dom[0 ]?.attributes ['atk-emoticon' ]) || (typeof dom[0 ]?.querySelector === 'function' && dom[0 ]?.querySelector ('img[atk-emoticon]' ))) { dom[0 ].onmouseover = (e ) => { } }
对应的,如果是 Twikoo 评论系统,相应需要修改为:
let owo_body = '' const dom = mutations[i].addedNodes if (dom.length == 2 && dom[1 ].className == 'OwO-body' ) owo_body = dom[1 ]else if (dom.length == 1 && dom[0 ].className == 'tk-comment' ) owo_body = dom[0 ]else continue owo_body.onmouseover = (e ) => { }
代码 JavaScript 以下代码适用于 Artalk,需要自行调用。 function showOwoBig (target ) { const ratio = 2 const maxLength = 200 const body = document .querySelector ('body' ) let div = document .createElement ('div' ) if (document .querySelector ('#owo-big' )) { div = document .querySelector ('#owo-big' ) } else { div.id = 'owo-big' body.appendChild (div) } const observer = new MutationObserver (mutations => { for (let i = 0 ; i < mutations.length ; i++){ let flag = 1 let owoTime = 0 const dom = mutations[i].addedNodes if (dom[0 ]?.classList ?.contains ('atk-grp' ) || dom[0 ]?.classList ?.contains ('atk-comment-wrap' ) || (!!dom[0 ]?.attributes && !!dom[0 ]?.attributes ['atk-emoticon' ]) || (typeof dom[0 ]?.querySelector === 'function' && dom[0 ]?.querySelector ('img[atk-emoticon]' ))) { dom[0 ].onmouseover = (e ) => { if (flag && e.target .tagName === 'IMG' ) { flag = 0 ; owoTime = setTimeout (() => { const alt = e.path [0 ].alt || '' ; const clientHeight = e.path [0 ].clientHeight const clientWidth = e.path [0 ].clientWidth if (clientHeight <= maxLength && clientWidth <= maxLength) { const naturalHeight = e.path [0 ].naturalHeight const naturalWidth = e.path [0 ].naturalWidth const zoomHeight = clientHeight * ratio const zoomWidth = clientWidth * ratio const height = naturalHeight > clientHeight ? zoomHeight < naturalHeight && naturalHeight < maxLength ? zoomHeight : naturalHeight : clientHeight const width = naturalWidth > clientWidth ? zoomWidth < naturalWidth && naturalWidth < maxLength ? zoomWidth : naturalWidth : clientWidth let tempWidth = 0 ; let tempHeight = 0 ; if (width / height >= 1 ) { if (width >= maxLength) { tempWidth = maxLength tempHeight = (height * maxLength) / width } else { tempWidth = width tempHeight = height } } else { if (height >= maxLength) { tempHeight = maxLength tempWidth = (width * maxLength) / height } else { tempWidth = width tempHeight = height } } const top = e.y - e.offsetY let left = (e.x - e.offsetX ) - (tempWidth - e.path [0 ].clientWidth ) / 2 if ((left + tempWidth) > body.clientWidth ) left -= ((left + tempWidth) - body.clientWidth + 10 ) if (left < 0 ) left = 10 if (alt !== '' ) tempHeight += 10 div.style .cssText = `display:block;height:${tempHeight+34 } px;width:${tempWidth+34 } px;left:${left} px;top:${top} px;` ; div.innerHTML = `<img src="${e.target.src} "><p>${alt} </p>` } }, 300 ); } }; dom[0 ].onmouseout = () => { flag = 1 div.style .display = 'none' clearTimeout (owoTime) } } } }) observer.observe (target, { subtree : true , childList : true }) }
CSS #owo-big { position : fixed; align-items : center; background-color : #ffffff ; border : 1px #aaa solid; border-radius : 10px ; z-index : 9999 ; display : none; transform : translate (0 , -105% ); overflow : hidden; animation : owoIn 0.3s cubic-bezier (0.42 , 0 , 0.3 , 1.11 ); padding : 16px ; } #owo-big img { width : 100% ; border-radius : 10px ; } #owo-big p { text-overflow : ellipsis; white-space : nowrap; overflow : hidden; text-align : center; font-size : 12px ; margin : 0 ; } @keyframes owoIn { 0% { transform : translate (0 , -95% ); opacity : 0 ; } 100% { transform : translate (0 , -105% ); opacity : 1 ; } }