live2d
对于live2d,ai告诉我一个比原版更聪明的看板娘,安装方法是:
方案二:利用 Butterfly 的 inject 功能(最优雅)
Butterfly 专门提供了一个 inject 配置项,允许你把代码插入到页面的特定位置,而不用去翻找复杂的 HTML 文件。
- 打开
_config.butterfly.yml。
- 找到
inject: 部分,在 bottom: 下面添加那行脚本:
1 2 3 4 5
| inject: head: bottom: - <script src="https://fastly.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/autoload.js"></script>
|
看板娘
看板娘的这个我应该怎么变成右下角固定
如果你使用的是这个 autoload.js 脚本,它默认通常会出现在左下角。要将其固定到右下角,最直接的方法是通过 CSS 覆盖。
由于这个脚本在运行时会自动往页面注入一个 ID 为 waifu(或者类似的容器)的 HTML 元素,我们可以直接在 Hexo 中添加样式来强制改变它的位置。
方案一:通过 Butterfly 的 Inject 功能(最推荐)
不需要改动 JS 脚本,直接在 _config.butterfly.yml 中添加一行 CSS 注入即可:
- 打开
_config.butterfly.yml。
- 找到
inject -> head 部分。
- 添加以下代码:
YAML
1 2 3 4 5
| inject: head: - <style>#waifu { left: auto !important; right: 0 !important; }</style> bottom: - <script src="https://fastly.jsdelivr.net/npm/live2d-widgets@1.0.0/dist/autoload.js"></script>
|
代码解释:
left: auto !important;:取消默认的左侧定位。
right: 0 !important;:将其固定到右侧。你可以把 0 改成 20px 让它离边缘有一点距离。
方案二:如果你使用的是本地文件
如果你已经把 waifu.css 下载到了本地(例如放在 source/live2d-widget/waifu.css):
打开该 waifu.css 文件。
搜索 #waifu。
将其中的 left: 0; 修改为:
CSS
1 2 3 4 5
| #waifu { right: 20px; /* 距离右边 20 像素 */ bottom: 0; /* 确保没有 left 属性,如果有,请删掉或改为 left: auto; */ }
|
方案三:针对不同插件容器名的通用补救
如果你发现上面的 #waifu 没起作用,说明你这个版本的插件可能用了不同的 ID。你可以按以下步骤查找:
- 在浏览器打开你的博客,按 F12 打开开发者工具。
- 点击左上角的“小箭头”图标,去页面上点击那个看板娘。
- 查看右侧面板中该元素的
id 是什么(可能是 landlord 或 live2d-widget)。
- 将方案一代码中的
#waifu 替换为那个 ID 即可。
⚠️ 可能存在的冲突
由于你在右下角可能还有:
- Butterfly 的“回到顶部”按钮。
- APlayer 播放器(如果你也把它设在了右边)。
建议: 如果右下角太挤了,你可以微调位置,比如: right: 50px !important; bottom: 20px !important; 这样看板娘会往左边和上方挪一点,避免挡住功能按钮。
改完后记得执行 hexo clean 和 hexo g。看板娘现在成功“瞬移”到右边了吗?
pwa
安装完后右上角会有个安装按钮,可以离线看博客,然后有缓存可以加快访问速度,右上角会有个通知博客更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| npm install --global gulp-cli #全局安装gulp命令集 npm install workbox-build gulp --save#安装workbox和gulp扬件
#压缩html插件 npm install gulp-htmlclean --save-dev npm install --save gulp-htmlmin #压缩css播件 npm install gulp-clean-css --save-dev #压缩js播件 #使用babel压缩js,与terser二选一 npm install --save-dev gulpuglify npm install --save-dev gulp-babel @babel/core @babel/preset-env #使用terser压缩js,与babel二选一(推荐) npm install gulp-terser --save-dev npm install --save-dev gulp-babel @babel/core @babel/preset-env # 压缩图片播件(没啥用) npm install --save-dev gulp-imagcmin #压缩字体播件(font-min仅支持压缩ttf格式的字体包) npm install gulp-fontmin --save-dev
|
关于font-min的补充说明,在本文中,是通过读取所有编译好的html文件(./public/“.html)中的字符,然后匹配原有字体包内./public/fonts/.ttf字体样式,输出压缩后的字体包到 /public/fontsdest/目录。所以最终引用字体的相对路径应读是/fontsdes/.ttf。而本地测试时,如果没有运行gulp,自然也就不会输出压缩字体包到public目录,也就看不到字体样式。
julp-terser只会直接压缩js代码,所以不存在因为语法变动导致的错误。事实上,当我们使用jsdelivr的CDN服务时,只需要在css或者js的后级前添加加.min,例如example.js->example.min.js,JsDelivr就会自动使用terser帮我们压缩好代码,
在package.json添加
创建gulpfile.js,在hexo的根目录创建这个文件
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
| import gulp from 'gulp'; import cleanCSS from 'gulp-clean-css'; import htmlmin from 'gulp-htmlmin'; import htmlclean from 'gulp-htmlclean'; import imagemin from 'gulp-imagemin'; import workbox from 'workbox-build'; import fontmin from 'gulp-fontmin';
import terser from 'gulp-terser';
gulp.task('generate-service-worker', ()=> { return workbox.injectManifest({ swSrc: './sw-template.js', swDest: './public/sw.js', globDirectory: './public', globPatterns: [ '404.html', 'index.html', 'js/main.js', 'css/index.css', ], modifyURLPrefix: { '': './', }, }); });
gulp.task('compress', ()=> gulp .src([ './public/**/*.js', '!./public/**/*.min.js', '!./public/js/custom/galmenu.js', '!./public/js/custom/gitcalendar.js', ]) .pipe(terser()) .pipe(gulp.dest('./public')) );
gulp.task('minify-css', () => { return gulp .src('./public/**/*.css') .pipe( cleanCSS({ compatibility: 'ie11', }) ) .pipe(gulp.dest('./public')); });
gulp.task('minify-html', () => { return gulp .src('./public/**/*.html') .pipe(htmlclean()) .pipe( htmlmin({ removeComments:true, collapseWhitespace:true, collapseBooleanAttributes: true, removeEmptyAttributes:true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, minifyJS: true, minifyCss: true, minifyURLs: true, }) ) .pipe(gulp.dest('./public')); });
gulp.task( 'default', gulp.series( 'generate-service-worker', gulp.parallel('compress', 'minify-html', 'minify-css', 'minify-font')) );
|
创建sw-template.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
| const workboxVersion = '5.1.3';
importScripts(`https://storage.googleapis.com/workbox-cdn/releases/${workboxVersion}/workbox-sw.js`);
workbox.core.setCacheNameDetails({ prefix:'shelter', });
workbox.core.skipWaiting(); workbox.core.clientsClaim();
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST,{ directoryIndex: null, });
workbox.precaching.cleanupOutdatedCaches();
workbox.routing.registerRoute( /\.(?:eot|ttf|woff|woff2)$/, new workbox.strategies.CacheFirst({ cacheName: 'fonts', plugins: [ new workbox.expiration.ExpirationPlugin({ maxEntries: 1000, maxAgeSeconds: 60 * 60 * 24 * 30, }), new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200], }), ], }) );
workbox.routing.registerRoute( /\.(?:png|jpg|jpeg|svg|gif|webp)$/, new workbox.strategies.StaleWhileRevalidate({ cacheName: 'images', plugins: [ new workbox.expiration.ExpirationPlugin({ maxEntries: 500, maxAgeSeconds: 60 * 60 * 24 * 30, }), ], }) );
workbox.routing.registerRoute( /^https:\/\/fonts\.googleapis\.com/, new workbox.strategies.StaleWhileRevalidate({ cacheName: 'google-fonts-stylesheets', }) );
workbox.googleAnalytics.initialize();
|
在[Blogroot]\themes\butterfly\layout\includes\third-party\目录下新建pwanotice.pug文件,打开 [Blogroot]\themes\butterfly\layout\includes\third-party\pwanotice.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
| #app-refresh(style='position: fixed; top: -2.2rem; left: 0; right: 0; z-index: 99999; padding: 0 1rem; font-size: 15px; height: 2.2rem; transition: all 0.3s ease;') .app-refresh-wrap(style='display: flex; color: #fff; height: 100%; align-items: center; justify-content: center;') label 🚀 有新内容发布啦! a(href='javascript:void(0)' onclick='location.reload()') span(style='color: #fff; text-decoration: underline; cursor: pointer; margin-left: 8px;') 点击刷新 script. if ('serviceWorker' in navigator) { // 如果当前页面受 Service Worker 控制,监听控制权变化 if (navigator.serviceWorker.controller) { navigator.serviceWorker.addEventListener('controllerchange', function() { showNotification(); }); }
// 页面加载完成后注册 sw.js window.addEventListener('load', function() { navigator.serviceWorker.register('/sw.js').catch(err => { console.error('PWA 注册失败:', err); }); }); }
function showNotification() { // 优先使用主题自带的 Snackbar 弹窗 if (window.GLOBAL_CONFIG && GLOBAL_CONFIG.Snackbar) { var snackbarBg = document.documentElement.getAttribute('data-theme') === 'light' ? GLOBAL_CONFIG.Snackbar.bgLight : GLOBAL_CONFIG.Snackbar.bgDark; var snackbarPos = GLOBAL_CONFIG.Snackbar.position;
Snackbar.show({ text: '🚀 有新文章发布啦!', backgroundColor: snackbarBg, duration: 10000, // 持续 10 秒 pos: snackbarPos, actionText: '点击刷新', actionTextColor: '#fff', onActionClick: function(e) { location.reload(); }, }); } else { // 如果没有 Snackbar,则显示顶部的 app-refresh 栏 var showBg = document.documentElement.getAttribute('data-theme') === 'light' ? '#49b1f5' : '#1f1f1f'; var appRefresh = document.getElementById('app-refresh'); if (appRefresh) { appRefresh.style.cssText = 'top: 0; background: ' + showBg + ';'; } } }
|
修改[Blogroot]\themes\butterfly\layout\includes\additional-js.pug
,在文件底部添加以下内容,注意缩进。 butterfly_v3.6.0取消了缓存配置,转为完全默认,需要将{cache:theme.fragment_cache} 改为{cache: true},现在使用的是高版本,使用最后两行就行,注意pug是严格缩进模式,第一行一定是一个空格,第二行两个
1 2 3 4 5
| if theme.pjax.enable !=partial('includes/third-party/pjax',{},{cache:theme.fragment_cache}) !=partial('includes/third-party/baidu_push', {},{cache:theme.fragment_cache}) if theme.pwa.enable != partial('includes/third-party/pwanotice', {} , {cache: true})
|
将你的图标包移入相应的目录,例如我是(img/siteicon/,所以放到[Blogroot]/source/img/siteicon/目录下。没有的话新建,site icon就是站点图标,可以去阿里的iconfont网站找资源
新建文件名为 manifest.json 并将其放到 [Blogroot]/source 目录下,此时还不能直接用,需要添加一些内容,以下是我的 manifest.json 配置内容,权且作为参考,其中的 theme_color 建议用取色器取设计的图标的主色调,同时务必配置 start_url和 name的配置项,这关系到你之后能否看到浏览器的应用安装按钮。
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
| { "name":"Shelter的博客", "short_name": "Shelter", "theme_color": "#49b1f5", "background _color": "#49b1f5", "display": "standalone", "scope": "/", "start_url": "/", "icons": [{ "src":"/img/siteicon/16.png", "sizes": "16x16", "type": "image/png" }, { "src": "/img/siteicon/32.png", "sizes": "32x32", "type": "image/png" }, { "src": "/img/siteicon/64.png", "sizes": "64x64", "type": "image/png" }, { "src":"/img/siteicon/128.png", "sizes":"128x128", "type": "image/png" }, { "src":"/img/siteicon/144.png", "sizes":"144x144", "type":"image/png" }, { "src":"/img/siteicon/512.png", "sizes":"512x512", "type": "image/png" } ], "splash_pages": null }
|
打开主题配置文件 [Blogroot]/_config.butterfly.yml,找到 PWA 配置项。添加图标路径。这里的 theme_color,建议改成你图标的主色调,包括 manifest.json 中的 theme_color 也是如此。
1 2 3 4 5 6 7 8
| pwa: enable: true manifest: /manifest.json theme_color: "#49b1f5", apple_touch_icon: /img/siteicon/128.png favicon_32_32: /img/siteicon/32/png favicon_16_16: /img/siteicon/16.png mask_icon: /img/siteicon/128.png
|
一图流
新建文件[Blogroot]/source/css/custom.css在custom.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 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 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
|
@font-face { font-family: ZhuZiAYuanJWD; src:url(https://cdn.cbd,int/anzhiyu-blog@latest/fonts/ZhuZiAWan.woff2); font-display: swap; font-weight: lighter; } @import url(https://fonts.googleapis.com/css2?family=ZC00L+KuaiLe&display=swap);
div#menus { font-family:'ZhuZiAYuanJWD'; } h1#site-title { font-family: ZhuZiAYuanJWD; font-size: 3em !important; } a.article-title, a.blog-slider__title, a.categoryBar-list-link, h1.post-title { font-family: ZhuZiAYuanJwD; }
.iconfont { font-family:'iconfont' !important; font-size: 3em; font-style: normal; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; } svg.icon { width: 1em; height: 1em; vertical-align:-0.15em; fill: currentColor; overflow: hidden; } .icon-zhongbiao::before { color: #f7c768; }
.bangumi-active { background:#dbecfe !important; border-radius: 10px !important; } a.bangumi-tab:hover { text-decoration: none !important; } .bangumi-button:hover { background:#dbecfe !important; border-radius: 10px !important; } a.bangumi-button.bangumi-nextpage:hover { text-decoration: none !important; } .bangumi-button { padding: 5px 10px !important; } a.bangumi-tab { padding: 5px 10px !important; } svg.icon.faa-tada { font-size: 1.1em; }
#uploadSource > svg { width: 1.19em; height: 1.5em; }
#page-header:not(.not-top-img):before { background-color: transparent !important; }
#recent-posts > .recent-post-item { background:rgba(255,255,255,0.9); }
#aside-content .card-widget { background:rgba(255,255,255,0.9); }
div#post { background:rgba(255,255,255,0.9); }
div#page { background:rgba(255,255,255,0.9); }
div#archive { background:■rgba(255,255,255,0.9); }
div#tag { background:rgba(255,255,255,0.9); }
div#category { background:rgba(255,255,255,0.9); }
[data-theme='dark']#recent-posts > .recent-post-item { background: #121212; }
[data-theme='dark'] .card-widget { background: #121212 !important; }
[data-theme='dark'] div#post { background: #121212 !important; }
[data-theme='dark'] div#tag { background: #121212 !important; }
[data-theme='dark'] div#archive { background: #121212 !important; }
[data-theme='dark'] div#page { background: #121212 !important; }
[data-theme='dark'] div#category { background: #121212 !important; }
[data-theme='dark'] div#category { background: transparent !important; }
#footer { background: transparent !important; }
#page-header { background: transparent !important; }
#rightside > div > button { border-radius: 5px; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background-color: #49b1f5; border-radius: 2em; }
::-webkit-scrollbar-corner { background-color: transparent; }
::-moz-selection { color: ■#fff; background-color: #49b1f5; }
.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body { left: -66px !important; transition: all 0.3s; }
.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover { left: 0 !important; transition: all 0.3s; }
.aplayer.aplayer-fixed { z-index: 999999 !important; }
.vcard { box-shadow: 2px 2px 5px #bbb; background: rgba(255,255,255,0.3); border-radius: 8px; padding: 30px; margin: 30px 0px 0px 0px; }
body { cursor: url('/img/x1.cur'), auto; } a, [type='button']:not(:disabled), [type='reset']:not(:disabled), [type='submit']:not(:disabled), button:not(:disabled) { cursor: url('/img/x2.cur'), auto !important; } #article-container a:hover { text-decoration: none !important; }
#article-container #hpp_talk p img { display: inline; }
#error-wrap { position: absolute; top: 40%; right: 0; left: 0; margin: 0 auto; padding:0 1rem; max-width: 1000px; transform: translate(0, -50%); }
#error-wrap .error-content { display: flex; flex-direction: row; justify-content: center; align-items: center; margin:0 1rem; height: 18rem; border-radius:8px; background: var(--card-bg); box-shadow: var(--card-box-shadow); transition: all 0.3s; } #error-wrap .error-content .error-img { box-flex: 1; flex: 1; height: 100%; border-top-left-radius: 8px; border-bottom-left-radius:8px; background-color: 口#49b1f5; background-position:center; background-size: cover; }
#error-wrap .error-content .error-info { box-flex: 1; flex: 1; padding: 0.5rem; text-align: center; font-size: 14px; font-family: Titillium Web, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft JhengHei', 'Microsoft YaHei', sans-serif; } #error-wrap .error-contenr .error-info .error_title { margin-top:-4rem; font-size: 9em; } #error-wrap .error-content .error-info .error_subtitle { margin-top:-3.5rem; word-break: break-word; font-size: 1.6em; } #error-wrap .error-content .error-info a { display: inline-block; margin-top: 0.5rem; padding: 0.3rem 1.5rem; background: var(--btn-bg); color: var(--btn-color); }
#body-wrap.error .aside-list { display: flex; flex-direction: row; flex-wrap: nowrap; bottom: 0px; position: absolute; padding: 1rem; width: 100%; overflow: scroll; } #body-wrap.error .aside-list .aside-list-group { display: flex; flex-direction: row; flex-wrap: nowrap; max-width:1200px; margin: 0 auto; } #body-wrap.error .aside-list .aside-list-item { padding: 0.5rem; } #body-wrap.error .aside-list .aside-list-item img { width: 100%; object-fit: cover; border-radius:12px; }
#body-wrap.error .aside-list .aside-list-item .thumbnail { overflow: hidden; width: 230px; height: 143px; background: var(--heo-card-bg); display: flex; } #body-wrap.error .aside-list .aside-list-item .content .title { -webkit-line-clamp:2; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; line-height: 1.5; justify-content: center; align-items: flex-end; align-content:center; padding-top: 0.5rem; color: white; } #body-wrap.error .aside-list .aside-list-item .content time { display: none; } #article-container figure.highlight { border-radius:10px; }
|
不需要一图流就删除下面代码
1 2 3 4 5 6 7 8 9
| #footer { background: transparent !important; }
#page-header { background: transparent !important; }
|
然后在butterfly配置文件里找到inject添加下面代码
1 2 3 4 5
| inject: head: - <link rel="stylesheet" href="/css/custom.css" media="defer" onload="this.media='all'">
|
然后在这个配置文件里找background添加路径
1
| background: /img/background.png
|
如果本地部署没问题但是服务器有问题,就在config里设置url,设置成自己的github.io

字数统计
安装插件:在你的博客根目录,打开cmd命令窗口执行npm install hexo-wordcount --save
开启配置:修改主题配置文件_config.butterfly.yml中的wordcount
1 2 3 4 5
| wordcount: enable: true post_wordcount: true min2read: true total_wordcount: true
|