前言 美化之前 美化的时候需要修改网站的源文件、添加样式、js之类的,需要一点基础,可以参考
引用站外地址
Hexo博客添加自定义css和js文件
Leonus
在添加完js、css后,一定要记得在_config.butterfly.yml 的inject 里引用
引用站外地址
Butterfly自用全局变量
June's Blog
效果
参考链接
引用站外地址
引用站外地址
Butterfly主题的留言弹幕界面增强版(支持Twikoo、Waline、Valine)
Ariasakaの小窝
修改方案 1. 获取Twikoo
和TwikooUrl
仅提供Vercel部署
的获取方式
腾讯云部署方式请参考Butterfly主题的留言弹幕界面增强版(支持Twikoo、Waline、Valine)
在开发人员工具
->应用程序
->本地存储空间
->自己的网址
->twikoo-access-token
里面即可看到对应的值
2. 修改layout.pug
修改[blogRoot]\butterfly\layout\includes\layout.pug
1 2 3 4 5 6 7 8 9 10 11 ... main#content-inner.layout(class=hideAside) if body div!= body else block content if theme.aside.enable && page.aside !== false include widget/index.pug + .comment-barrage ...
小改动
因为我的侧栏aside
在左边,所以弹幕会和文章页有重合
又因为原本的教程里,#post
是.comment-barrage
的祖先,所以当我hover
弹幕.comment-barrage
元素的时候,会触发祖先#post
的hover
效果,这样会显得怪怪的,然后我想着调整一下,看有没有办法不这样
在.comment-barrage-item
元素上添加一个事件处理程序,阻止事件冒泡到其祖先元素(包括post
元素)上。修改popCommentBarrage
函数,为新创建的barrage
元素添加事件处理程序来阻止事件冒泡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function popCommentBarrage (data ) { let barrage = document .createElement ('div' ); let width = commentBarrageConfig.dom .clientWidth ; let height = commentBarrageConfig.dom .clientHeight ; barrage.className = 'comment-barrage-item' ; barrage.innerHTML = ` <div class="barrageHead"> <a class="barrageTitle">热评</a> <div class="barrageNick">${data.nick} </div> <img class="barrageAvatar" src="https://cravatar.cn/avatar/${data.mailMd5} "/> <a class="comment-barrage-close" href="javascript:hotreview.switchCommentBarrage()"><i class="iconfont icat-close"></i></a> </div> <a class="barrageContent" href="javascript:hotreview.scrollTo('${data.id} ');">${data.comment} </a> ` ; barrage.addEventListener ('mouseenter' , function (event ) { event.stopPropagation (); }); commentBarrageConfig.barrageTimer .push (barrage); commentBarrageConfig.dom .append (barrage); }
用这种方法,可以监听到,但是阻止不了,我感觉像是hover
并不是一个事件,阻止不了
css 子元素hover时不触发父元素hover - 珞珞9527 - 博客园 (cnblogs.com)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function popCommentBarrage (data ) { let barrage = document .createElement ('div' ); let width = commentBarrageConfig.dom .clientWidth ; let height = commentBarrageConfig.dom .clientHeight ; barrage.className = 'comment-barrage-item' ; barrage.innerHTML = ` <div class="barrageHead"> <a class="barrageTitle">热评</a> <div class="barrageNick">${data.nick} </div> <img class="barrageAvatar" src="https://cravatar.cn/avatar/${data.mailMd5} "/> <a class="comment-barrage-close" href="javascript:hotreview.switchCommentBarrage()"><i class="iconfont icat-close"></i></a> </div> <a class="barrageContent" href="javascript:hotreview.scrollTo('${data.id} ');">${data.comment} </a> ` ; let mask = document .createElement ('div' ); mask.className = 'barrage-mask' ; barrage.appendChild (mask); commentBarrageConfig.barrageTimer .push (barrage); commentBarrageConfig.dom .append (barrage); }
1 2 3 4 5 6 7 8 9 .barrage-mask { position : absolute; top : 0 ; left : 0 ; width : 100% ; height : 100% ; background-color : transparent; pointer-events : none; }
问了chat
,感觉没啥用,就没有细去研究😓
后面和鹊楠 讨论的时候,给了个思路,既然#post
是.comment-barrage
的祖先,而且参考了其他佬的源码(#post
并不是.comment-barrage
的祖先)那就干脆把.comment-barrage
移到#post
外面,所以就有了上面的方案
barrage.js
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 var hotreview = { switchCommentBarrage : function ( ) { var commentBarrage = document .querySelector (".comment-barrage" ); if (commentBarrage) { if ($(commentBarrage).is (":visible" )) { $(commentBarrage).hide (); $(".menu-commentBarrage-text" ).text ("显示热评" ); localStorage .setItem ("commentBarrageSwitch" , "false" ); } else if ($(commentBarrage).is (":hidden" )) { $(commentBarrage).show (); $(".menu-commentBarrage-text" ).text ("关闭热评" ); localStorage .removeItem ("commentBarrageSwitch" ); } } }, scrollTo : function (e ) { const t = document .getElementById (e); if (t) { const e = t.getBoundingClientRect ().top + window .pageYOffset - 80 , o = window .pageYOffset , n = e - o; let a = null ; window .requestAnimationFrame ((function e (t ) { a || (a = t); const i = t - a, l = (c = Math .min (i / 0 , 1 )) < .5 ? 2 * c * c : (4 - 2 * c) * c - 1 ; var c; window .scrollTo (0 , o + n * l), i < 600 && window .requestAnimationFrame (e) })) } } , }
commentBarrage.js
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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 var postCommentElement = document .getElementById ("post-comment" );if (postCommentElement) { var commentBarrageConfig = { maxBarrage : 1 , initialBarrageTime : 500 , barrageTime : 4000 , twikooUrl : "{envId}" , accessToken : "{YOUR_TOKEN}" , pageUrl : window .location .pathname , barrageTimer : [], barrageList : [], barrageIndex : 0 , dom : document .querySelector ('.comment-barrage' ), }; var commentInterval = null ; var hoverOnCommentBarrage = false ; $(".comment-barrage" ).hover (function ( ) { hoverOnCommentBarrage = true ; console .log ("热评悬浮" ); }, function ( ) { hoverOnCommentBarrage = false ; console .log ("停止悬浮" ); }); function initCommentBarrage ( ){ var data = JSON .stringify ({ "event" : "COMMENT_GET" , "commentBarrageConfig.accessToken" : commentBarrageConfig.accessToken , "url" : commentBarrageConfig.pageUrl }); var xhr = new XMLHttpRequest (); xhr.withCredentials = true ; xhr.addEventListener ("readystatechange" , function ( ) { if (this .readyState === 4 ) { commentBarrageConfig.barrageList = commentLinkFilter (JSON .parse (this .responseText ).data ); commentBarrageConfig.dom .innerHTML = '' ; } }); xhr.open ("POST" , commentBarrageConfig.twikooUrl ); xhr.setRequestHeader ("Content-Type" , "application/json" ); xhr.send (data); clearInterval (commentInterval); commentInterval = null ; commentInterval = setInterval (() => { if (commentBarrageConfig.barrageList .length && !hoverOnCommentBarrage) { popCommentBarrage (commentBarrageConfig.barrageList [commentBarrageConfig.barrageIndex ]); commentBarrageConfig.barrageIndex += 1 ; commentBarrageConfig.barrageIndex %= commentBarrageConfig.barrageList .length ; } if ((commentBarrageConfig.barrageTimer .length > (commentBarrageConfig.barrageList .length > commentBarrageConfig.maxBarrage ? commentBarrageConfig.maxBarrage : commentBarrageConfig.barrageList .length )) && !hoverOnCommentBarrage) { removeCommentBarrage (commentBarrageConfig.barrageTimer .shift ()) } }, commentBarrageConfig.initialBarrageTime ); } function commentLinkFilter (data ) { data.sort ((a, b ) => { return a.created - b.created ; }); let newData = []; data.forEach (item => { newData.push (...getCommentReplies (item)); }); return newData; } function getCommentReplies (item ) { if (item.replies ) { let replies = [item]; item.replies .forEach (item => { replies.push (...getCommentReplies (item)); }); return replies; } else { return []; } } function popCommentBarrage (data ) { let barrage = document .createElement ('div' ); let width = commentBarrageConfig.dom .clientWidth ; let height = commentBarrageConfig.dom .clientHeight ; barrage.className = 'comment-barrage-item' ; barrage.innerHTML = ` <div class="barrageHead"> <a class="barrageTitle">热评</a> <div class="barrageNick">${data.nick} </div> <img class="barrageAvatar" src="https://cravatar.cn/avatar/${data.mailMd5} "/> <a class="comment-barrage-close" href="javascript:hotreview.switchCommentBarrage()"><i class="iconfont icat-close"></i></a> </div> <a class="barrageContent" href="javascript:hotreview.scrollTo('${data.id} ');">${data.comment} </a> ` ; commentBarrageConfig.barrageTimer .push (barrage); commentBarrageConfig.dom .append (barrage); clearInterval (commentInterval); commentInterval = setInterval (() => { if (commentBarrageConfig.barrageList .length && !hoverOnCommentBarrage) { popCommentBarrage (commentBarrageConfig.barrageList [commentBarrageConfig.barrageIndex ]); commentBarrageConfig.barrageIndex += 1 ; commentBarrageConfig.barrageIndex %= commentBarrageConfig.barrageList .length ; } if ((commentBarrageConfig.barrageTimer .length > (commentBarrageConfig.barrageList .length > commentBarrageConfig.maxBarrage ? commentBarrageConfig.maxBarrage : commentBarrageConfig.barrageList .length )) && !hoverOnCommentBarrage) { removeCommentBarrage (commentBarrageConfig.barrageTimer .shift ()) } }, commentBarrageConfig.barrageTime ); } function removeCommentBarrage (barrage ) { barrage.className = 'comment-barrage-item out' ; setTimeout (() => { commentBarrageConfig.dom .removeChild (barrage); }, 1000 ); } document .addEventListener ('scroll' , btf.throttle (function ( ) { var visibleBottom = window .scrollY + document .documentElement .clientHeight ; var visibleTop = window .scrollY ; var pagination = document .querySelector ('.comment-barrage' ); var eventlistner = document .getElementById ('post-comment' ); if (eventlistner && pagination) { var centerY = eventlistner.offsetTop + (eventlistner.offsetHeight / 2 ); if (document .body .clientWidth > 768 ) { if (centerY > visibleBottom) { pagination.style .bottom = '40px' ; } else { pagination.style .bottom = '-200px' ; } } } }, 200 )) initCommentBarrage (); document .addEventListener ('pjax:send' , function ( ) { clearInterval (commentInterval); }); }
4. 创建barrage.css
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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 .comment-barrage { position : fixed; bottom : 40px ; right : 68px ; display : flex; flex-direction : column; justify-content : end; align-items : flex-end; z-index : 999 ; transition : 0.3s ; user-select: none; -webkit-user-select: none; } @media screen and (max-width : 768px ){ .comment-barrage { display : none!important ; } } .comment-barrage-item { min-width : 286px ; max-width : 286px ; width : fit-content; min-height : 80px ; max-height : 150px ; margin : 4px ; padding : 8px 14px ; background : var (--june-maskbgdeep); border-radius : 8px ; color : var (--june-fontcolor); animation : barrageIn 0.6s cubic-bezier (0.42 , 0 , 0.3 , 1.11 ); transition : 0.3s ; display : flex; flex-direction : column; border : var (--style-border-always); backdrop-filter : saturate (180% ) blur (20px ); -webkit-backdrop-filter : blur (20px ); position : fixed; box-shadow : var (--june-shadow-border); overflow : hidden; } .comment-barrage-item :hover { border : 1px solid var (--june-border); box-shadow : var (--june-shadow-black); } .comment-barrage-item .out { opacity : 0 ; animation : barrageOut 0.6s cubic-bezier (0.42 , 0 , 0.3 , 1.11 ); } .comment-barrage-item .hovered { opacity : 0 ; } .comment-barrage-item .comment-barrage-close { color : var (--june-secondtext); cursor : pointer; line-height : 1 ; margin : 4px ; } .comment-barrage-item .comment-barrage-close .junefont { font-size : 18px !important ; } .comment-barrage-item pre { display : none; } .comment-barrage-item li { display : none; } .comment-barrage-item p img :not (.tk-owo-emotion ) { display : none; } .comment-barrage-item p img .tk-owo-emotion { width : 16px ; padding : 0 ; margin : 0 ; transform : translateY (2px ); } .comment-barrage-item blockquote { display : none; } .comment-barrage-item br { display : none; } .comment-barrage-item .barrageHead { height : 30px ; padding : 0 ; line-height : 30px ; font-size : 12px ; border-bottom : var (--style-border); display : flex; justify-content : space-between; align-items : center; font-weight : bold; padding-bottom : 6px ; } .comment-barrage-item .barrageHead .barrageTitle { background : var (--june); color : var (--june-white); margin-right : 8px ; line-height : 1 ; padding : 4px ; border-radius : 4px ; white-space :nowrap; } .comment-barrage-item .barrageAvatar { width : 18px ; height : 18px ; margin : 0 ; margin-left : auto; margin-right : 8px ; border-radius : 50% ; background : var (--june-secondbg); cursor : url (https://img.june-pj.cn/img/default.cur ), default; } .comment-barrage-item .barrageContent { font-size : 14px !important ; font-weight : normal!important ; height : calc (100% - 30px ); overflow : hidden; width : fit-content; max-height : 48px ; } .comment-barrage-item .barrageContent a { pointer-events :none; font-size : 14px !important ; } .comment-barrage-item .barrageContent ::-webkit-scrollbar{ height : 0 ; width : 4px ; } .comment-barrage-item .barrageContent ::-webkit-scrollbar-button{ display : none; } .barrageHead .comment-barrage-close i { color : var (--june-fontcolor); } .comment-barrage-item p { color : var (--june-fontcolor); margin : 8px 0 0 ; line-height : 1.2 ; -webkit-line-clamp: 2 ; display : -webkit-box; -webkit-box-orient: vertical; font-size : 12px ; font-weight : bold; overflow : hidden; -o-text-overflow : ellipsis; text-overflow : ellipsis; } .comment-barrage-item p :hover ,.barrageHead .comment-barrage-close i :hover { color : var (--june); }
修改 [blogRoot]\themes\butterfly\layout\includes\rightmenu.pug
1 2 3 4 5 6 7 8 9 ... .rightMenu-group.rightMenu-line.hide#menu-post a.rightMenu-item(href="#post-comment") i.fas.fa-comment span='空降评论' + a.rightMenu-item(href="javascript:hotreview.switchCommentBarrage()") + i.iconfont.icon-danmu + span.menu-commentBarrage-text 关闭热评 ...