前言

之前去看富婆妹(ハミダシクリエイティブ)的 HP 的动效,感觉特别好看,就特别想整一个同款,于是在一月初花了点时间研究了一下,给博客换了个新主题,顺带做了个 Dark Mode 适配,这样晚上就看的舒服多了,不过做完之后基本上都在忙论文了,这两天论文答辩完等结果哩(应该比较乐观),所以来补档一下之前要写没写的内容(话说现在写这个标题真的好嘛,已经咕了快四个月才写)

ハミダシクリエイティブ 的 HP 动效长这个样子

主题

以下大量前端代码预警,不过没有前端知识也不要紧,我对前端也就只懂一点点,写 js 的时候还是靠着以前写爬虫的知识写的,不是很难,懂了核心思想就可以给自己的博客适配同款

效果可参照本博客,右下角两个按钮能切换主题

先来说主题怎么做,观察ハミダシクリエイティブ的前端代码,不难发现动效部分是用 css 实现的,代码位于 index.css?version=20191212 中,核心代码长下面这个样子

核心思想:在 index 里面给定一个 id 为 mv 的 section ,用 css 调整这个 section 的内容即可完成动效的制作

#mv .bg {
position: absolute;
top: -4000px;
left: -4000px;
width: 8000px;
height: 8000px;
background: url(/hamidashi/wp/wp-content/themes/hamidashi/img/common/bg.png) left top repeat;
z-index: 1;
-webkit-animation: infinitescroll 10s linear infinite;
-moz-animation: infinitescroll 10s linear infinite;
-ms-animation: infinitescroll 10s linear infinite;
-o-animation: infinitescroll 10s linear infinite;
animation: infinitescroll 10s linear infinite; }
@keyframes infinitescroll {
0% {
transform: translate3d(0, 0, 0); }
100% {
transform: translate3d(376px, 376px, 0); } }
#mv .bg {
-webkit-animation: infinitescroll 20s linear infinite;
-moz-animation: infinitescroll 20s linear infinite;
-ms-animation: infinitescroll 20s linear infinite;
-o-animation: infinitescroll 20s linear infinite;
animation: infinitescroll 20s linear infinite;
background-size: 1.5%; }

知道了原理,要仿照起来就很容易了,我们也在 index 给一个带 id 的 section ,用 css 调它就行了嘛,好说,来看实现

index.html

<!-- 背景滚动效果 -->
<section id="bgScroll">
<!-- 为实现多个主题,添加此 div -->
<div id="changeAbleBackground" class="bg1"></div>
</section>

bg.css

实现了两套主题,用 .bg1 和 .bg2 表示,要实现多个主题,只需要修改 background: url 的内容即可,另外注意在 plumemo 的情况下需要调整 z-index: -1 来保证背景图片置于最下方

@charset "UTF-8";
/* ************************************************ */
/* LuckyBlogV2 滚动背景 */
/* ************************************************ */
#bgScroll {
position: fixed;
top: 0;
left: 0;
width: 100%;
min-height: 100vh;
overflow: hidden;
text-align: right;
z-index: -99999; }
#bgScroll .bg1 {
position: absolute;
top: -4000px;
left: -4000px;
width: 8000px;
height: 8000px;
background: url(https://wdv2.luckykeeper.site:44443/api/v3/file/get/19729/hamidashi_bg.png?sign=JGTXN2brek0S9_vGAhCO4_6e2a09RMNTLA8y1p7bhkg%3D%3A0) left top repeat;
z-index: -1;
-webkit-animation: infinitescroll 10s linear infinite;
-moz-animation: infinitescroll 10s linear infinite;
-ms-animation: infinitescroll 10s linear infinite;
-o-animation: infinitescroll 10s linear infinite;
animation: infinitescroll 10s linear infinite; }
#bgScroll .bg2 {
position: absolute;
top: -4000px;
left: -4000px;
width: 8000px;
height: 8000px;
background: url(https://wdv2.luckykeeper.site:44443/api/v3/file/get/15117/sakura.png?sign=L4UAr7oDiOlMqkYxSAgoxtCojgBUOY5jzlcbngpepoQ%3D%3A0) left top repeat;
z-index: -1;
-webkit-animation: infinitescroll 10s linear infinite;
-moz-animation: infinitescroll 10s linear infinite;
-ms-animation: infinitescroll 10s linear infinite;
-o-animation: infinitescroll 10s linear infinite;
animation: infinitescroll 10s linear infinite; }
@keyframes infinitescroll {
0% {
transform: translate3d(0, 0, 0); }
100% {
transform: translate3d(376px, 376px, 0); } }
@media (max-width: 1200px) {
@media (max-width: 750px) {
#bgScroll .bg1 {
-webkit-animation: infinitescroll 20s linear infinite;
-moz-animation: infinitescroll 20s linear infinite;
-ms-animation: infinitescroll 20s linear infinite;
-o-animation: infinitescroll 20s linear infinite;
animation: infinitescroll 20s linear infinite;
background-size: 1.5%; }}
#bgScroll .bg2 {
-webkit-animation: infinitescroll 20s linear infinite;
-moz-animation: infinitescroll 20s linear infinite;
-ms-animation: infinitescroll 20s linear infinite;
-o-animation: infinitescroll 20s linear infinite;
animation: infinitescroll 20s linear infinite;
background-size: 5%; }}

做了多个主题,肯定需要做主题的切换,这个问题咱们等到下面 Dark Mode 部分讲完之后一起来讲

Dark Mode!

为了解决晚上看白色画面刺眼的问题,很早就想做 Dark Mode 了,既然主题做了,何不顺带把 Dark Mode 一起做了呢,仍然用 css 来做,非常简单,直接来看实现

index.html

最顶上加个 theme ,我们用这个来判断展示什么模式的主题,顾名思义,白天就是 day-mode ,晚上就是 dark-mode

<html lang="zh-CN" theme="day-mode">

changeTheme.css

根据给定的 theme 切换模式

changeTheme.css 这里主要是在 theme="dark-mode" 的时候反转颜色,记得图片要在反色一次,live2d 也是,不然就显得很阴间了2333

/* DarkMode */
html[theme="dark-mode"] {
filter: invert(1) hue-rotate(180deg);
}

html[theme="dark-mode"] img{
filter: invert(1) hue-rotate(180deg);
}
html[theme="dark-mode"] .gWvPxa .blog-item .post-thumb a{
filter: invert(1) hue-rotate(180deg);
}

html[theme="dark-mode"] canvas#live2d{
filter: invert(1) hue-rotate(180deg) !important;
}

html[theme="dark-mode"] .gJkinm{
filter: invert(1) hue-rotate(180deg) !important;
}

html[theme="dark-mode"] .player .Video{
filter: invert(1) hue-rotate(180deg) !important;
}

html {
transition: color 300ms, background-color 300ms;
}

主题切换

那么我们现在实现了两套主题,白天模式和 Dark Mode,加起来就是四种组合,怎样才能做到主题切换并且记住用户的选择呢?也不难,我们用 JavaScript 实现即可,核心思想是用 js 修改 html 里面的内容(主题 -> class bg1/bg2;DarkMode -> html theme),并且借助用户浏览器的存储,把用户的选择存储到用户电脑的硬盘里面,加载页面的时候进行切换即可,还是来看实现

index.html

调用 changeThemeButton() 方法切换主题并存储,这里放上两张图片做按钮

调用 readUserThemeSettingAndApply() 方法应用用户设定

<!-- 放上一只阿露 -->
<div id="darkModeButton">
<div id="RikuhachimaAru" onclick="changeThemeButton()" style="position: fixed; opacity: 1; right: 100px; bottom: -7px;cursor:pointer; z-index: 99999">
<img style="width:160px; height:160px" src="https://wdv2.luckykeeper.site:44443/api/v3/file/get/19730/darkmode.png?sign=IOIpjI0O7No_FLwsWyFsWvERgoL6Eg7O00CRKICLpWw%3D%3A0">
</div></div>
<!-- 放上一只星野 -->
<div onclick="changeBackgroundButton()" style="position: fixed; opacity: 1; right: 0px; bottom: -7px;cursor:pointer; z-index: 99999">
<img style="width:150px; height:150px" src="https://wdv2.luckykeeper.site:44443/api/v3/file/get/19760/changeTheme.png?sign=mOvI4XF5_EmEXRKWAPW_o0FEblTktJndxQsK9NoLDTY%3D%3A0">
</div>
<!-- 应用用户设定 -->
<script type="text/javascript">readUserThemeSettingAndApply()</script>

changeTheme.js

切换主题,存储用户设定

// LuckyBlogV2 切换主题
// By Luckykeeper <https://luckykeeper.site | luckykeeper@luckykeeper.site>

var darkModeStatus = 0;
var blogTheme = 1

// 页面加载-读取,记录设置变量
function readUserThemeSettingAndApply(){
console.log('Reading User Settings……')
if (localStorage.getItem('darkModeStatus')) {
if (Number(darkModeStatus) != Number(localStorage.getItem('darkModeStatus'))){
darkModeStatus = Number(localStorage.getItem('darkModeStatus'))
console.log('ChangeThemeFromClientHistory:',darkModeStatus)
changeThemeFunc(darkModeStatus)
}
}

if (localStorage.getItem('blogTheme')) {
if (blogTheme != Number(localStorage.getItem('blogTheme'))){
blogTheme = Number(localStorage.getItem('blogTheme'))
console.log('ChangeBackgroundFromClientHistory:',blogTheme)
changeBackgroundFunc(blogTheme)
}
}
}

// 主题切换按钮
function changeThemeButton(){
if (darkModeStatus==1){
darkModeStatus = 0
localStorage.setItem('darkModeStatus', darkModeStatus)
}else{
darkModeStatus = 1
localStorage.setItem('darkModeStatus', darkModeStatus)
}
changeThemeFunc(darkModeStatus)
}

// 主题之间的切换动作
function changeThemeFunc(darkModeStatus) {
if (darkModeStatus==1){
$("html").attr("theme","dark-mode");
$("#RikuhachimaAru").remove()
$("#darkModeButton").append('<div id="AjitaniHifumi" onclick="changeThemeButton()" style="position: fixed; opacity: 1; right: 140px; bottom: -7px;cursor:pointer; z-index: 99999"><img style="width:160px; height:160px" src="https://wdv2.luckykeeper.site:44443/api/v3/file/get/19732/daymode.png?sign=MD-gBvM3uBwHELd3bi1bEeGdCl3R4bEd74fXe9kIktU%3D%3A0"> </div>');
// document.querySelector("#root > div.sc-jTzLTM.hZECho > div.sc-gZMcBi.eSOeDz > div.sc-gqjmRU.gJkinm").setAttribute("filter","invert(1) hue-rotate(180deg)")
console.log('黑暗模式:ON');
}else{
$("html").attr("theme","day-mode");
$("#AjitaniHifumi").remove()
$("#darkModeButton").append('<div id="RikuhachimaAru" onclick="changeThemeButton()" style="position: fixed; opacity: 1; right: 100px; bottom: -7px;cursor:pointer; z-index: 99999"><img style="width:160px; height:160px" src="https://wdv2.luckykeeper.site:44443/api/v3/file/get/19730/darkmode.png?sign=IOIpjI0O7No_FLwsWyFsWvERgoL6Eg7O00CRKICLpWw%3D%3A0"> </div>');
// document.querySelector("#root > div.sc-jTzLTM.hZECho > div.sc-gZMcBi.eSOeDz > div.sc-gqjmRU.gJkinm").removeAttribute("filter")
console.log('黑暗模式:OFF');
}
}

// 背景切换按钮
function changeBackgroundButton(){
switch(blogTheme){
case 2:
blogTheme = 1
localStorage.setItem('blogTheme', blogTheme)
break;
default:
blogTheme = blogTheme + 1
localStorage.setItem('blogTheme', blogTheme)
break;
}
changeBackgroundFunc(blogTheme)
}

// 背景之间的切换
function changeBackgroundFunc(blogTheme){
switch(blogTheme){
case 1:
$("#changeAbleBackground").remove()
$("#bgScroll").append('<div id="changeAbleBackground" class="bg1"></div>');
console.log('当前主题:theme-react-hamidashi')
break;
case 2:
$("#changeAbleBackground").remove()
$("#bgScroll").append('<div id="changeAbleBackground" class="bg2"></div>');
console.log('当前主题:theme-react-sakura')
break;
}
}

来整同款?

阅读以下文件,更换图片链接,即可快速给自己博客上同款~

index.html

bg.css

changeTheme.css

changeTheme.js