本文章首发于语雀 ! 通过各种高科技功能同步到Hajeekn 的博客
本文章大部分功能涉及到魔改,如果您无法掌握 pug、stylus 等文件的缩进格式,可以直接前往我的博客源码拿取。
这里是我的博客源码哦~ 由于每个人的博客目录都不相同,这里博客目录使用%brt%代替
本文章除 Pace wowjs 普通引入法以外,其他魔改都不适合 Butterfly3.6.0 及以上
通过 wowjs 给博客添加好看的样式 基础样式篇 前往%brt%\themes\butterfly\source\js\
新建一个 js,名称为wow-init.js
其 JS 内部写入如下内容
1 2 3 4 5 6 7 8 9 10 11 12 13 wow = new WOW({ boxClass: "wow" , animateClass: "animate__animated" , offset: 0 , live: true , }); wow.init();
如果您觉得不想出现注释,也可以删掉注释。
2.前往%brt%\themes\butterfly\layout\includes\third-party\
目录,新建一个名为wow-js.pug
的文件 其文件内部写入如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 .pjax-reload if theme.wowjs.animateitem each item in theme.wowjs.animateitem script(async ). var arr = document.getElementsByClassName('!{item.class}' ); for (var i = 0 ;i<arr.length;i++){ arr[i].classList.add('wow' ); arr[i].classList.add('!{item.style}' ); arr[i].setAttribute('data-wow-duration' , '!{item.duration}' ); arr[i].setAttribute('data-wow-delay' , '!{item.delay}' ); arr[i].setAttribute('data-wow-offset' , '!{item.offset}' ); arr[i].setAttribute('data-wow-iteration' , '!{item.iteration}' ); } script(defer src=url_for(theme.CDN.wowjs)) script(defer src=url_for(theme.CDN.wowjs_init))
3.修改%brt%\themes\butterfly\layout\includes\head.pug
的内容 在 //- font 的配置下 //- global config 的配置上的空白部分写入以下代码(请直接复制粘贴,避免出现缩进错误 ❌)
1 2 3 //- animate_css if theme.wowjs.enable link(rel='stylesheet' href=url_for(theme.CDN.animate_css) media="print" onload="this.media='all'")
4.修改%brt&\themes\butterfly\layout\includes\additional-js.pug
文件内部的内容 在 if theme.pjax.enable 配置大项的 baidu-push 小项下写入一下代码(请直接复制粘贴,避免出现缩进错误 ❌) V3.4.0 以下(不包括 3.4.0): 将其中的
1 $('script[data-pjax]' ).each(function ( ) {
删除,并修改为:
1 2 3 $("script[data-pjax], .pjax-reload script" ).each(function ( ) { $(this ).parent().append($(this ).remove()); });
V3.4.0 以上(包括 3.4.0): 找到
1 document .querySelectorAll('script[data-pjax]' ).forEach(item => {
删除它,并写入以下代码(请直接复制粘贴,避免缩进错误 ❌)
1 2 3 4 5 6 7 8 9 10 11 document .querySelectorAll("script[data-pjax], .pjax-reload script" ) .forEach((item ) => { const newScript = document .createElement("script" ); const content = item.text || item.textContent || item.innerHTML || "" ; Array .from(item.attributes).forEach((attr ) => newScript.setAttribute(attr.name, attr.value) ); newScript.appendChild(document .createTextNode(content)); item.parentNode.replaceChild(newScript, item); });
5.修改%brt\%config%\_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视) 找到 CDN 配置项 在
的配置项下添加 wowjs、wowjs-init、animate 的库(请直接复制粘贴以下代码,避免格式缩进导致的错误 ❌)
1 2 3 wowjs: https://cdn.jsdelivr.net/gh/graingert/wow@1.3.0/dist/wow.min.js wowjs_init: /js/wow_init.js animate_css: https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css
6.修改%brt\%config%\_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视) 在该配置文件内部添加 wow 的开关,其中 class 和 style 配置为必填项
1 2 3 4 5 6 7 8 9 10 11 wowjs: enable: true animateitem: - class: recent-post-item style: animate__zoomIn duration: 3s delay: 1s offset: 100 iteration: 2 - class: CoolButton style: animate__zoomIn
运行hexo clean && hexo g
后方可看到效果,更多 animate 动画样式可查看animate 官方文档
浮动样式篇 1.前往%brt%\themes\butterfly\source\js\
目录,新建一个名为floatpanel.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 var ANGLE = 45 ; var panel = document .getElementsByClassName("wowpanels" );for (var i = 0 ; i < panel.length; i++) { floatable(panel[i]); } function floatable (content ) { content.addEventListener("mouseout" , (e ) => { content.style.transform = `perspective(300px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)` ; }); content.addEventListener("mousemove" , (e ) => { var w = content.clientWidth; var h = content.clientHeight; var y = ((e.offsetX - w * 0.5 ) / w) * ANGLE; var x = ((1 - (e.offsetY - h * 0.5 )) / h) * ANGLE; content.style.transform = `perspective(300px) rotateX(${x} deg) rotateY(${y} deg)` ; }); }
2.修改%brt\%config%\_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视) 在 inject 大项的 bottom 小项中添加 script 引入项:
1 - <script async data-pjax src="/js/floatpanel.js"></script>
3.给你想要特效的类元素添加 wowpanels 属性,修改 floatpanel.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 // 新增的内容 var arr = document.getElementsByClassName('element-class'); //把element-class替换成你想要添加特效的元素的类名 for(var i = 0 ;i<arr.length;i++){ arr[i].classList.add('wowpanels'); } // 原来的内容 var ANGLE = 45 ; //控制浮动角度,数值越大,浮动幅度越大。 var panel= document.getElementsByClassName('wowpanels'); for(var i = 0 ;i<panel.length;i++){ floatable(panel[i]); } function floatable (content) {content.addEventListener('mouseout' , e => {content.style.transform = `perspective(300px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)`; }); content.addEventListener('mousemove' , e => {var w = content.clientWidth; var h = content.clientHeight; var y = (e.offsetX - w * 0.5 ) / w * ANGLE; var x = (1 - (e.offsetY - h * 0.5 )) / h * ANGLE; content.style.transform = `perspective(300px) rotateX($ {x }deg) rotateY($ {y }deg)`; }); }
当你完成了基础样式篇时,其实你可以直接将浮动效果看成一个动画样式 在之前的配置下直接添加以下配置项:
1 2 - class: style: wowpanels
添加完成后 wowjs 的配置项应该与下面的截图类似 如果报错,请检查你的配置缩进是否正确 ✔,这里博主推荐使用微软爸爸出品的 VSC 编辑对于缩进格式邀请很强的文件格式 以下代码供您用来参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 wowjs: enable: true animateitem: - class: recent-post-item style: animate__zoomIn duration: 3s delay: 0. 5s offset: 100 iteration: 1 - class: card-widget style: animate__zoomInUp duration: 3s delay: 0. 5s offset: 100 iteration: 1 - class: layout hide-aside style: animate__flipInY duration: 3s delay: 0. 5s offset: 100 iteration: 1 - class: CoolButton style: wowpanels
如果您想让动画更滑丝滑流畅,可以新建 css,在内部写入以下代码:
1 2 3 .wowpanels { transition : all 0.4s cubic-bezier (0.39 , 0.575 , 0.565 , 1 ); }
添加 BiliBili 同款的动态 Banner 由于每个人的博客目录都不相同,这里博客目录使用%brt%代替
1.前往%brt%\themes\butterfly\layout\includes\header\
新建一个名为bilibili-banner.pug
的文件 在其内部写入
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 if (!is_home()) - var banner_style = (typeof (page.bilibili_banner) != "undefined" && page.bilibili_banner!=null ) ? page.bilibili_banner : theme.bilibili_banner.style if (banner_style === 'autumn' ) #autumnBanner div img(src='/bilibiliBanner/autumn/bilibili-autumn-1.png' ) div img(src='/bilibiliBanner/autumn/bilibili-autumn-2.png' ) div img(src='/bilibiliBanner/autumn/bilibili-autumn-3.png' ) div img(src='/bilibiliBanner/autumn/bilibili-autumn-4.png' ) div img(src='/bilibiliBanner/autumn/bilibili-autumn-5.png' ) div img(src='/bilibiliBanner/autumn/bilibili-autumn-6.png' ) else if (banner_style === 'winter' ) #winterBanner .view img.morning(src='/bilibiliBanner/winter/bilibili-winter-view-1.png' alt='' ) img.afternoon(src='/bilibiliBanner/winter/bilibili-winter-view-2.png' alt='' ) video.evening(autoplay='' loop='' muted='' ) source(src='/bilibiliBanner/winter/bilibili-winter-view-3.webm' type='video/webm' ) img.window-cover(src='/bilibiliBanner/winter/bilibili-winter-view-3-snow.png' alt='' ) .tree img.morning(src='/bilibiliBanner/winter/bilibili-winter-tree-1.png' alt='' ) img.afternoon(src='/bilibiliBanner/winter/bilibili-winter-tree-2.png' alt='' ) img.evening(src='/bilibiliBanner/winter/bilibili-winter-tree-3.png' alt='' ) script(async data-pjax src=url_for(theme.CDN.bilibili_banner))
2.前往%brt%\themes\butterfly\source\css\
新建一个名为bilibiliBanner.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 @media screen and (max-width: 1000px ) { #autumnBanner { display : none !important ; } } #autumnBanner { height : 100% ; position : relative; overflow : hidden; filter : brightness (70% ); } #autumnBanner > div { position : absolute; top : 0 ; left : 0 ; width : 100% ; height : 100% ; display : flex; justify-content : center; align-items : center; --offset : 0px ; --blur : 2px ; } #autumnBanner > div > img { display : block; width : 110% ; height : 100% ; object-fit : cover; transform : translatex (var(--offset)); filter : blur (var(--blur)); } @media screen and (max-width: 1000px ) { #winterBanner { display : none !important ; } } #winterBanner { height : 100% ; position : relative; width : 100% ; overflow : hidden; --percentage : 0.5 ; } #winterBanner .view ,#winterBanner .tree { position : absolute; top : 0 ; right : 0 ; bottom : 0 ; left : 0 ; display : flex; justify-content : center; align-items : center; } #winterBanner img ,#winterBanner video { position : absolute; display : block; max-width : 120% !important ; width : 120% !important ; height : 100% ; object-fit : cover; filter : brightness (70% ); } #winterBanner .morning { z-index : 20 ; opacity : calc (1 - (var(--percentage) - 0.25 ) / 0.25 ); } #winterBanner .afternoon { z-index : 10 ; opacity : calc (1 - (var(--percentage) - 0.5 ) / 0.5 ); } #winterBanner .view { transform : translatex (calc(var(--percentage) * 100px )); } #winterBanner .tree { transform : translatex (calc(var(--percentage) * 50px )); filter : blur (3px ); } #winterBanner .view ,#winterBanner .tree ,#winterBanner .morning ,#winterBanner .afternoon { transition : 0.2s all ease-in; } #winterBanner .moving .view ,#winterBanner .moving .tree ,#winterBanner .moving .morning ,#winterBanner .moving .afternoon { transition : none; } #winterBanner .window-cover { opacity : calc ((var(--percentage) - 0.9 ) / 0.1 ); }
3.前往%brt%\themes\butterfly\source\js\
新建一个名为bilibili-banner.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 var autumnBanner = document .querySelector("#autumnBanner" );if (autumnBanner) { var images = document .querySelectorAll("#autumnBanner > div > img" ); autumnBanner.addEventListener("mousemove" , (e ) => { let percentage = e.clientX / window .outerWidth; let offset = 10 * percentage; let blur = 20 ; for (let [index, image] of images.entries()) { offset *= 1.3 ; let blurValue = Math .pow(index / images.length - percentage, 2 ) * blur; image.style.setProperty("--offset" , `${offset} px` ); image.style.setProperty("--blur" , `${blurValue} px` ); } }); } var winterBanner = document .querySelector("#winterBanner" );if (winterBanner) { var startingPoint; winterBanner.addEventListener("mouseenter" , (e ) => { startingPoint = e.clientX; winterBanner.classList.add("moving" ); }); winterBanner.addEventListener("mouseout" , (e ) => { winterBanner.classList.remove("moving" ); winterBanner.style.setProperty("--percentage" , 0.5 ); }); winterBanner.addEventListener("mousemove" , (e ) => { let percentage = (e.clientX - startingPoint) / window .outerWidth + 0.5 ; winterBanner.style.setProperty("--percentage" , percentage); }); }
4.在主题的 source 文件夹下新建bilibiliBanner
文件夹,将我所提供的资源解压,直接放入进去(里面一定只有两个目录) 5.进入%brt%\themes\butterfly\layout\includes\header\
文件夹,找到index.pug
在内部注入 bilibili_banner 组件 在 include ./nav.pug 配置下 if is_post()配置上添加以下配置(请直接复制粘贴,避免代码缩进导致的错误 ❌)
1 2 3 - var bilibili_banner = (typeof (page.bilibili_banner) != "undefined" && page.bilibili_banner!=null ) ? page.bilibili_banner : theme.bilibili_banner.enable if (bilibili_banner) include ./bilibili-banner.pug
6.修改%brt\%config%\_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视) 找到 CDN 配置,在 utils: /js/utils.js 配置的后面添加以下配置
1 bilibili_banner: /js/bilibili-banner.js
添加 ** css
** 配置项。此处使用了异步加载,同时做了媒体选择,对手机是不会生效的。因为手机的 ** banner
** 高度会导致适配效果很差。 我们找到 inject 配置大项的 head 小项,在其内部添加以下配置:
1 - <link rel="stylesheet" href="/css/bilibiliBanner.css" media="defer" onload="this.media='screen'">
在 butterfly 主题配置中添加以下配置:
1 2 3 4 bilibili_banner: enable: true style: winter
除了在主题配置文件通过配置 bilibili_banner:
的默认项,还可以在每个页面的 markdown
文件中通过 front-matter
控制单页配置。提供了三个选项 : false
: 关闭该页面的动态 banner
显示autumn
: 开启该页面的动态 banner
,并设置主题为秋季winter
: 开启该页面的动态 banner
,并设置主题为冬季 页面配置项优先级高于主题配置悬停左上角时在网站顶部中间位置会出现描述 1.进入%brt%\themes\butterfly\layout\includes\header\
修改名为nav.pug
的文件 找到
1 2 span#blog_name a#site-name(href=url_for('/' )) #[=config.title]
将它们删除,并替换为以下代码(请直接复制粘贴,避免缩进错误 ❌):
1 2 3 4 5 6 7 8 9 10 - var pagedescr = (typeof (page.description) != "undefined" && page.description!=null ) ? page.description : '欢迎您来到了Hajeekn的小木屋呢,不过看起来有点漏水🐕' if is_post() span#blog_name a#site-name(onclick='btf.scrollToDest(0,500)' data-title=pagedescr) #[=config.title] else if is_page() span#blog_name a#site-name(href=url_for('/' ) data-title=pagedescr) #[=page.title] else span#blog_name a#site-name(href=url_for('/' ) data-title=pagedescr) #[=config.title]
2.因为 hexo
自带缓存的关系,如果我们用的是缓存式引入的话,nav
的刷新是惰性的,我们需要它根据文章和页面的切换实时变动。所以需要改动一下引入逻辑。打开%brt%\themes\butterfly\layout\includes\header\index.pug
找到
1 !=partial('includes/header/nav' , {}, {cache :theme.fragment_cache})
删除,并将它修改为以下代码(请直接复制粘贴,避免缩进错误 ❌):
1 2 3 4 include ./nav.pug if top_img !== false if is_post() include ./post-info.pug
(如果您添加了 BiliBili 动态 banner,请将它放置在在 if is_post()的前面 if top_img !== false 的后面,避免报错)
3.进入%brt%\themes\butterfly\source\css\_layout\
新建_custom.styl 在其内部输入以下代码(请直接复制粘贴,避免缩进错误 ❌):
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 #site-name &:hover &:before position : fixed width :fit-content margin :auto left :0 ; right :0 top :10 % border-radius : 10px text-align : center z-index : 100 content : attr (data-title ) font-size : 20px color : #fff padding : 10px background-color : rgba (#49B1F5 ,0.9) [data-theme=dark] a #site-name &:hover &:before background-color : rgba (#121212 ,0.8) @media screen and (max-width: 768px ) a#site-name -webkit-line-clamp 1 word-break break-all display -webkit-box -webkit-box-orient vertical overflow hidden
主页置顶的 ♂gitcalendar♂ 哪个男孩纸不想拥有一个状态显示呢? 这个模块就会教大家在 Butterfly 使用 gitcalendar
准备好了吗?Go Go! 1.前往%brt\themes\butterfly\layout\includes\
新建一个名为gitcalendar.pug
的文件 在其内部添加以下代码(请直接复制粘贴,避免缩进错误 ❌):
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 #gitcalendar.gitcalendar #gitmessage(:style='{top:y+px,left:x+px,position: fixed,zIndex:9999}' ) .angle-wrapper span {{span1}} span {{span2}} 次上传 .position-relative .border.py-2. graph-before-activity-overview .js-gitcalendar-graph.mx-md-2. mx-3. d-flex.flex-column.flex-items-end.flex-xl-items-center.overflow-hidden.pt-1. is-graph-loading.graph-canvas.gitcalendar-graph.height-full.text-center #gitcalendarcanvasbox(v-if ='simplemode' ) canvas#gitcanvas(style='animation: none;' ) svg.js-gitcalendar-graph-svg(width='100%' , viewBox='0 0 770 128' , v-if ='!simplemode' ) text.month(:x='32 + monthindex*64' , y='20' , v-for ='(month,monthindex) in monthchange' ) {{month}} text.wday(text-anchor='start' , dx='0' , dy='40' ) 日 text.wday(text-anchor='start' , dx='0' , dy='65' ) 二 text.wday(text-anchor='start' , dx='0' , dy='90' ) 四 text.wday(text-anchor='start' , dx='0' , dy='115' ) 六 g(v-for ='(weekitem,weekIndex) in data' , :transform='\'translate(\'+ (16 + weekIndex*14) + \',\' + \'0)\'' ) rect(@mouseover="selectStyle(dayitem,$event)" @mouseleave="outStyle()" v-for ='(dayitem,dayIndex) in weekitem' , :style='{fill:thiscolor(dayitem.count),shapeRendering:crispedges}' , :data-score='dayitem.count' , :data-date='dayitem.date' , x='0' , :y=' 30 + dayIndex*13 ' , width='11' , height='11' ) .contrib-footer.clearfix.mt-1. mx-3. px-3. pb-1 .float-left.text-gray | 数据来源 a(:href="'https://github.com/'+ user " , target='blank' ) @{{user}} .contrib-legend.text-gray | Less ul.legend li(:style='{backgroundColor:color[0]}' ) li(:style='{backgroundColor:color[2]}' ) li(:style='{backgroundColor:color[4]}' ) li(:style='{backgroundColor:color[6]}' ) li(:style='{backgroundColor:color[8]}' ) | More .contrib-column.contrib-column-first.table-column span.text-muted 过去一年提交 span.contrib-number {{total}} span.text-muted {{oneyearbeforeday}} - {{thisday}} .contrib-column.table-column span.text-muted 最近一月提交 span.contrib-number {{thisweekdatacore}} span.text-muted {{amonthago}} - {{thisday}} .contrib-column.table-column span.text-muted 最近一周提交 span.contrib-number {{weekdatacore}} span.text-muted {{aweekago}} - {{thisday}}
2.继续在这个目录下新建一个名为gitcalendar-js.pug
的文件 在内部写入以下代码(请直接复制粘贴,避免缩进错误 ❌):
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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 script. var gitcalendar = new Vue({ el: '#gitcalendar' , data: { simplemode: !{theme.gitcalendar.simplemode}, user: '!{theme.gitcalendar.user}' , fixed: 'fixed' , px: 'px' , x: '' , y: '' , span1: '' , span2: '' , month: ['一月' , '二月' , '三月' , '四月' , '五月' , '六月' , '七月' , '八月' , '九月' , '十月' , '十一月' , '十二月' ], monthchange: [], oneyearbeforeday: '' , thisday: '' , amonthago: '' , aweekago: '' , weekdatacore: 0 , datacore: 0 , total: 0 , datadate: '' , data: [], positionplusdata: [], firstweek: [], lastweek: [], beforeweek: [], thisweekdatacore: 0 , mounthbeforeday: 0 , mounthfirstindex: 0 , crispedges: 'crispedges' , thisdayindex: 0 , amonthagoindex: 0 , amonthagoweek: [], firstdate: [], first2date: [], montharrbefore: [], monthindex: 0 , color: !{theme.gitcalendar.color} }, methods: { selectStyle (data, event ) { document .querySelector('.angle-wrapper' ).style.display = 'block' this .span1 = data.date; this .span2 = data.count; this .x = event.clientX - 100 ; this .y = event.clientY - 60 }, outStyle ( ) { document .querySelector('.angle-wrapper' ).style.display = 'none' }, thiscolor (x ) { if (x === 0 ) { let i = parseInt (x / 2 ); return this .color[0 ] } else if (x < 2 ) { return this .color[1 ] } else if (x < 20 ) { let i = parseInt (x / 2 ); return this .color[i] } else { return this .color[9 ] } }, } }); var apiurl = '!{theme.gitcalendar.apiurl}' ? 'https://!{theme.gitcalendar.apiurl}/api?' : 'https://githubapi.ryanchristian.dev/user/' var githubapiurl = apiurl + gitcalendar.user; function responsiveChart ( ) { let c = document .getElementById("gitcanvas" ); if (c) { let cmessage = document .getElementById("gitmessage" ); let ctx = c.getContext("2d" ); c.width = document .getElementById("gitcalendarcanvasbox" ).offsetWidth; let linemaxwitdh = 0.96 * c.width / gitcalendar.data.length; c.height = 9 * linemaxwitdh; let lineminwitdh = 0.8 * linemaxwitdh; let setposition = { x: 0.02 * c.width, y: 0.025 * c.width }; for (let week in gitcalendar.data) { weekdata = gitcalendar.data[week]; for (let day in weekdata) { let dataitem = { date: "" , count: "" , x: 0 , y: 0 }; gitcalendar.positionplusdata.push(dataitem); ctx.fillStyle = gitcalendar.thiscolor(weekdata[day].count); setposition.y = Math .round(setposition.y * 100 ) / 100 ; dataitem.date = weekdata[day].date; dataitem.count = weekdata[day].count; dataitem.x = setposition.x; dataitem.y = setposition.y; ctx.fillRect(setposition.x, setposition.y, lineminwitdh, lineminwitdh); setposition.y = setposition.y + linemaxwitdh }; setposition.y = 0.025 * c.width; setposition.x = setposition.x + linemaxwitdh }; ctx.font = "600 Arial" ; ctx.fillStyle = '#aaa' ; ctx.fillText("日" , 0 , 1.9 * linemaxwitdh); ctx.fillText("二" , 0 , 3.9 * linemaxwitdh); ctx.fillText("四" , 0 , 5.9 * linemaxwitdh); ctx.fillText("六" , 0 , 7.9 * linemaxwitdh); let monthindexlist = c.width / 24 ; for (let index in gitcalendar.monthchange) { ctx.fillText(gitcalendar.monthchange[index], monthindexlist, 0.7 * linemaxwitdh); monthindexlist = monthindexlist + c.width / 12 }; cmessage.onmousemove = function (event ) { document .querySelector('.angle-wrapper' ).style.display = 'none' }; c.onmousemove = function (event ) { document .querySelector('.angle-wrapper' ).style.display = 'none' getMousePos(c, event); }; function getMousePos (canvas, event ) { var rect = canvas.getBoundingClientRect(); var x = event.clientX - rect.left * (canvas.width / rect.width); var y = event.clientY - rect.top * (canvas.height / rect.height); for (let item of gitcalendar.positionplusdata) { let lenthx = x - item.x; let lenthy = y - item.y; if (0 < lenthx && lenthx < lineminwitdh) { if (0 < lenthy && lenthy < lineminwitdh) { document .querySelector('.angle-wrapper' ).style.display = 'block' gitcalendar.span1 = item.date; gitcalendar.span2 = item.count; gitcalendar.x = event.clientX - 100 ; gitcalendar.y = event.clientY - 60 } } } } } } function addlastmonth ( ) { if (gitcalendar.thisdayindex === 0 ) { thisweekcore(52 ); thisweekcore(51 ); thisweekcore(50 ); thisweekcore(49 ); thisweekcore(48 ); gitcalendar.thisweekdatacore += gitcalendar.firstdate[6 ].count; gitcalendar.amonthago = gitcalendar.firstdate[6 ].date } else { thisweekcore(52 ); thisweekcore(51 ); thisweekcore(50 ); thisweekcore(49 ); thisweek2core(); gitcalendar.amonthago = gitcalendar.first2date[gitcalendar.thisdayindex - 1 ].date } }; function thisweek2core ( ) { for (let i = gitcalendar.thisdayindex - 1 ; i < gitcalendar.first2date.length; i++) { gitcalendar.thisweekdatacore += gitcalendar.first2date[i].count } }; function thisweekcore (index ) { for (let item of gitcalendar.data[index]) { gitcalendar.thisweekdatacore += item.count } }; function addlastweek ( ) { for (let item of gitcalendar.lastweek) { gitcalendar.weekdatacore += item.count } }; function addbeforeweek ( ) { for (let i = gitcalendar.thisdayindex; i < gitcalendar.beforeweek.length; i++) { gitcalendar.weekdatacore += gitcalendar.beforeweek[i].count } }; function addweek (data ) { if (gitcalendar.thisdayindex === 6 ) { gitcalendar.aweekago = gitcalendar.lastweek[0 ].date; addlastweek() } else { lastweek = data.contributions[51 ]; gitcalendar.aweekago = lastweek[gitcalendar.thisdayindex + 1 ].date; addlastweek(); addbeforeweek() } } fetch(githubapiurl) .then(data => data.json()) .then(data => { gitcalendar.data = data.contributions; gitcalendar.total = data.total; gitcalendar.first2date = gitcalendar.data[48 ]; gitcalendar.firstdate = gitcalendar.data[47 ]; gitcalendar.firstweek = data.contributions[0 ]; gitcalendar.lastweek = data.contributions[52 ]; gitcalendar.beforeweek = data.contributions[51 ]; gitcalendar.thisdayindex = gitcalendar.lastweek.length - 1 ; gitcalendar.thisday = gitcalendar.lastweek[gitcalendar.thisdayindex].date; gitcalendar.oneyearbeforeday = gitcalendar.firstweek[0 ].date; gitcalendar.monthindex = gitcalendar.thisday.substring(5 , 7 ) * 1 ; gitcalendar.montharrbefore = gitcalendar.month.splice(gitcalendar.monthindex, 12 - gitcalendar.monthindex); gitcalendar.monthchange = gitcalendar.montharrbefore.concat(gitcalendar.month); addweek(data); addlastmonth(); responsiveChart(); }) .catch(function (error ) { console .log(error); }); if (document .getElementById("gitcalendarcanvasbox" ).offsetWidth < 500 ) { gitcalendar.simplemode = false } window .onresize = function ( ) { if (gitcalendar.simplemode) responsiveChart() } window .onscroll = function ( ) { if (document .querySelector('.angle-wrapper' )) { document .querySelector('.angle-wrapper' ).style.display = 'none' } };
然后你要去创建 Stylus 样式辣
3.进入%brt%\themes\butterfly\source\css\_layout\
新建一个名为gitcalendar.styl
的文件 用 编 辑 器 打开 在文件内部 植 入 以下代码:
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 172 173 174 175 176 177 178 if hexo-config('gitcalendar.enable') .gitcalendar font-family SourceHanSans-Medium border 1px solid #DDDDDD border-radius 3px min-height 120px text-align center margin 0 auto border-width 0px width 100% display flex display -webkit-flex justify-content center align-items center flex-wrap wrap img &.spinner width 70px margin-top 50px min-height 70px .gitcalendar-graph text .wday , .gitcalendar-graph text .month font-size 10px fill #aaa .contrib-legend text-align right padding 0 14px 10px 0 display inline-block float right .legend display inline-block list-style none margin 0 5px position relative bottom -1px padding 0 li display inline-block width 10px height 10px .text-small font-size 12px color #767676 .gitcalendar-graph padding 15px 0 0 text-align center .contrib-column text-align center border-left 1px solid #ddd border-top 1px solid #ddd font-size 11px .contrib-column-first border-left 0 .table-column padding 10px display table-cell width 33% vertical-align top .contrib-number font-weight 300 line-height 1.3em font-size 24px display block .monospace text-align center color #000 font-family monospace a color #1D75AB text-decoration none .contrib-footer font-size 11px padding 0 10px 12px text-align left width 100% box-sizing border-box height 26px .left &.text-muted float left margin-left 9px color #767676 a color #4078c0 text-decoration none .left .text-muted a :hover , .monospace a :hover text-decoration underline h2 &.f4 &.text-normal &.mb-3 display none .float-left &.text-gray float left #user-activity-overview display none .day-tooltip white-space nowrap position absolute z-index 99999 padding 10px font-size 12px color #959da5 text-align center background rgba (0,0,0,.85) border-radius 3px display none pointer-events none strong color #dfe2e5 &.is-visible display block &:after position absolute bottom -10px left 50% width 5px height 5px box-sizing border-box margin 0 0 0 -5px content " " border 5px solid transparent border-top-color rgba (0,0,0,.85) .position-relative width 100% padding-left 20px padding-right 20px @media screen and (max-width: 650px ) .contrib-column display none .angle-wrapper z-index 9999 display inline display none width 200px height 40px position relative padding 5px 0 background rgba(0 , 0 , 0 , 0.8 ) border-radius 8px text-align center color white span padding-bottom 1em &:before content '' width 0 height 0 border 10px solid transparent border-top-color rgba(0 , 0 , 0 , 0.8 ) position absolute left 47.5% top 100% .angle-box position fixed padding 10px
4.快马加鞭的前往%brt%\themes\butterfly\layout\
找到我们的 食 物 index.pug
为了方便我们食用,找到#recent-posts.recent-posts 在下面插入一段代码
1 2 3 4 5 6 if theme.gitcalendar.enable .recent-post-item(style='width:100%' ) !=partial('includes/gitcalendar' , {}, {cache :theme.fragment_cache}) if theme.categoryBar.enable .recent-post-item(style='height:auto;width:100%;padding:0px;' ) #categoryBar!= list_categories(site.categories,{class : 'categoryBar' ,depth : 1 })
记得一定要放在+postUI 的前一行哦 - 5.进入%brt%\themes\butterfly\layout\includes\
的additional-js.pug
文件 在 script(src=url_for(theme.CDN.utils))的上面加入以下内容
1 script((src = url_for(theme.CDN.vue)));
然后再找到 script(defer src=url_for(theme.CDN.busuanzi))配置项 在这下面放入以下代码
1 2 3 if theme.gitcalendar.enable !=partial('includes/gitcalendar-js' , {}, {cache :theme.fragment_cache}) !=partial('includes/third-party/prismjs' , {}, {cache :theme.fragment_cache})
好的,修改完了,接下来我们就可以去添加 CDN 配置项和 gitcalendar 配置项了 进入%brt%\_config.butterfly.yml
找到 CDN 配置项 在 utils: /js/utils.js 配置项的下面插入以下代码
然后随便找一个屑位置,插入以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 gitcalendar: enable: true simplemode: true user: slblog-github apiurl: color: "['#e4dfd7', '#f9f4dc', '#f7e8aa', '#f7e8aa', '#f8df72', '#fcd217', '#fcc515', '#f28e16', '#fb8b05', '#d85916', '#f43e06']"
然后参照上面的配置就行辣~ 关于配置 apiurl 可以参照Akilar 大佬的文章 自建 API 哦 各位有什么想魔改的可以评论以一下(只要不太难,毕竟我还是个 初 中 生)
在你的网站添加一个 ♂ 美妙 ♂ 的 PACE 加载进度条 这个很简单,只需要一个 JS 和一个 CSS 就可以了 现在我们开始吧 首先进入%brt%\_config.butterfly.yml
找到 inject 大项 在 bottom 配置项下面添加如下配置:
1 2 - <script async data-pjax src="https://cdn.jsdelivr.net/gh/HCLonely/hclonely.github.io@1.4.7/js/custom/pace.min.js"></script> - <link rel=stylesheet href="https://cdn.jsdelivr.net/gh/HCLonely/hclonely.github.io@1.4.7/css/custom/pace-theme-flash.min.css">
然后就行了,哈哈其实是用来水一下字数的
备用引入 备用 1
1 2 - <script async data-pjax src="https://static.slqwq.cn/script/pace-main.min.js"></script> - <link rel=stylesheet href="https://static.slqwq.cn/styles/pace-theme-flash.min.css">
备用 2
1 2 - <script async data-pjax src="https://static-2.slqwq.cn/script/pace-main.min.js"></script> - <link rel=stylesheet href="https://static-2.slqwq.cn/styles/pace-theme-flash.min.css">
备用 3
1 2 - <script async data-pjax src="https://static-3.slqwq.cn/script/pace-main.min.js"></script> - <link rel=stylesheet href="https://static-3.slqwq.cn/styles/pace-theme-flash.min.css">
备用 4
1 2 - <script async data-pjax src="https://cdn.jsdelivr.net/gh/slblog-github/Static@main/script/pace-main.min.js"></script> - <link rel=stylesheet href="https://cdn.jsdelivr.net/gh/slblog-github/Static@main/styles/pace-theme-flash.min.css">