Butterfly 主题魔改 - 打赏按钮

博文迁移计划:本文由博客旧站迁移而来,仅对图片和错误显示的文字进行勘误翻新,对博文本身所述内容不做更改,望周知
魔改系列提示:本教程适用于原版 Butterfly 主题,对其衍生再发行版本的可用性不做保证

前言

一直觉得主题的打赏按钮不够美观
看到店长的魔改方向不错,决定借鉴一下

参考教程
查看效果

修改zh-CN.yml

修改 [Blogroot]\themes\butterfly\languages\zh-CN.yml

1
2
3
4
5
6
7
8
9
10
date_suffix:
just: 刚刚
min: 分钟前
hour: 小时前
day: 天前
month: 个月前

- donate: 打赏
+ donate: 不给糖果就捣蛋
share: 分享

替换reward.pug

整体替换 [Blogroot]\themes\butterfly\layout\includes\post\reward.pugm 为以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
link(rel='stylesheet' href=url_for(theme.CDN.option.coin_css) media="defer" onload="this.media='all'")
.post-reward
button.tip-button.reward-button
span.tip-button__text= _p('donate')
.coin-wrapper
.coin
.coin__middle
.coin__back
.coin__front
.reward-main
ul.reward-all
each item in theme.reward.QR_code
- var clickTo = (item.itemlist||item).link ? (item.itemlist||item).link : (item.itemlist||item).img
li.reward-item
a(href=clickTo target='_blank')
img.post-qr-code-img(src=url_for((item.itemlist||item).img) alt=(item.itemlist||item).text)
.post-qr-code-desc=(item.itemlist||item).text
if theme.reward.coinAudio
- var coinAudio = theme.reward.coinAudio ? url_for(theme.reward.coinAudio) : 'https://cdn.cbd.int/akilar-candyassets@1.0.36/audio/coin.mp3'
audio#coinAudio(src=coinAudio)
script(defer src=url_for(theme.CDN.option.coin_js))

此处的 https://cdn.cbd.int/akilar-candyassets@1.0.36/audio/coin.mp3 可以自行下载并替换为本地链接

新建coin.css

新建 [Blogroot]\source\css\coin.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
.tip-button {
border: 0;
border-radius: 0.25rem;
cursor: pointer;
font-size: 20px;
font-weight: 600;
height: 2.6rem;
margin-bottom: -4rem;
outline: 0;
position: relative;
top: 0;
transform-origin: 0% 100%;
transition: transform 50ms ease-in-out;
width: auto;
-webkit-tap-highlight-color: transparent;
}
.tip-button:active {
transform: rotate(4deg);
}
.tip-button.clicked {
animation: 150ms ease-in-out 1 shake;
pointer-events: none;
}
.tip-button.clicked .tip-button__text {
opacity: 0;
transition: opacity 100ms linear 200ms;
}
.tip-button.clicked::before {
height: 0.5rem;
width: 60%;
background: $button-hover-color;
}
.tip-button.clicked .coin {
transition: margin-bottom 1s linear 200ms;
margin-bottom: 0;
}
.tip-button.shrink-landing::before {
transition: width 200ms ease-in;
width: 0;
}
.tip-button.coin-landed::after {
opacity: 1;
transform: scale(1);
transform-origin: 50% 100%;
}
.tip-button.coin-landed .coin-wrapper {
background: radial-gradient(circle at 35% 97%, rgba(3, 16, 50, 0.4) 0.04rem, transparent 0.04rem), radial-gradient(
circle at 45% 92%,
rgba(3, 16, 50, 0.4) 0.04rem,
transparent 0.02rem
), radial-gradient(circle at 55% 98%, rgba(3, 16, 50, 0.4) 0.04rem, transparent 0.04rem), radial-gradient(circle at
65% 96%, rgba(3, 16, 50, 0.4) 0.06rem, transparent 0.06rem);
background-position: center bottom;
background-size: 100%;
bottom: -1rem;
opacity: 0;
transform: scale(2) translateY(-10px);
}
.tip-button__text {
color: #fff;
margin-right: 1.8rem;
opacity: 1;
position: relative;
transition: opacity 100ms linear 500ms;
z-index: 3;
}
.tip-button::before {
border-radius: 0.25rem;
bottom: 0;
content: "";
display: block;
height: 100%;
left: 50%;
position: absolute;
transform: translateX(-50%);
transition: height 250ms ease-in-out 400ms, width 250ms ease-in-out 300ms;
width: 100%;
z-index: 2;
}
.tip-button::after {
bottom: -1rem;
color: white;
content: "ヾ(≧O≦)〃嗷~"; /*点击后显示的内容*/
height: 110%;
left: 0;
opacity: 0;
position: absolute;
pointer-events: none;
text-align: center;
transform: scale(0);
transform-origin: 50% 20%;
transition: transform 200ms cubic-bezier(0, 0, 0.35, 1.43);
width: 100%;
z-index: 1;
}

.coin-wrapper {
background: none;
bottom: 0;
height: 18rem;
left: 0;
opacity: 1;
overflow: hidden;
pointer-events: none;
position: absolute;
transform: none;
transform-origin: 50% 100%;
transition: opacity 200ms linear 100ms, transform 300ms ease-out;
width: 100%;
}

.coin {
--front-y-multiplier: 0;
--back-y-multiplier: 0;
--coin-y-multiplier: 0;
--coin-x-multiplier: 0;
--coin-scale-multiplier: 0;
--coin-rotation-multiplier: 0;
--shine-opacity-multiplier: 0.4;
--shine-bg-multiplier: 50%;
bottom: calc(var(--coin-y-multiplier) * 1rem - 3.5rem);
height: 3.5rem;
margin-bottom: 3.05rem;
position: absolute;
right: calc(var(--coin-x-multiplier) * 34% + 16%);
transform: translateX(50%) scale(calc(0.4 + var(--coin-scale-multiplier))) rotate(calc(var(
--coin-rotation-multiplier
) * -1deg));
transition: opacity 100ms linear 200ms;
width: 3.5rem;
z-index: 3;
}
.coin__front,
.coin__middle,
.coin__back,
.coin::before,
.coin__front::after,
.coin__back::after {
border-radius: 50%;
box-sizing: border-box;
height: 100%;
left: 0;
position: absolute;
width: 100%;
z-index: 3;
}
.coin__front {
background: radial-gradient(circle at 50% 50%, transparent 50%, rgba(115, 124, 153, 0.4) 54%, #c2cadf 54%),
linear-gradient(210deg, #8590b3 32%, transparent 32%), linear-gradient(150deg, #8590b3 32%, transparent 32%),
linear-gradient(to right, #8590b3 22%, transparent 22%, transparent 78%, #8590b3 78%), linear-gradient(
to bottom,
#fcfaf9 44%,
transparent 44%,
transparent 65%,
#fcfaf9 65%,
#fcfaf9 71%,
#8590b3 71%
), linear-gradient(to right, transparent 28%, #fcfaf9 28%, #fcfaf9 34%, #8590b3 34%, #8590b3 40%, #fcfaf9 40%, #fcfaf9
47%, #8590b3 47%, #8590b3 53%, #fcfaf9 53%, #fcfaf9 60%, #8590b3 60%, #8590b3 66%, #fcfaf9 66%, #fcfaf9 72%, transparent
72%);
background-color: #8590b3;
background-size: 100% 100%;
transform: translateY(calc(var(--front-y-multiplier) * 0.3181818182rem / 2)) scaleY(var(--front-scale-multiplier));
}
.coin__front::after {
background: rgba(0, 0, 0, 0.2);
content: "";
opacity: var(--front-y-multiplier);
}
.coin__middle {
background: #737c99;
transform: translateY(calc(var(--middle-y-multiplier) * 0.3181818182rem / 2)) scaleY(var(--middle-scale-multiplier));
}
.coin__back {
background: radial-gradient(circle at 50% 50%, transparent 50%, rgba(115, 124, 153, 0.4) 54%, #c2cadf 54%),
radial-gradient(circle at 50% 40%, #fcfaf9 23%, transparent 23%), radial-gradient(circle at 50% 100%, #fcfaf9 35%, transparent
35%);
background-color: #8590b3;
background-size: 100% 100%;
transform: translateY(calc(var(--back-y-multiplier) * 0.3181818182rem / 2)) scaleY(var(--back-scale-multiplier));
}
.coin__back::after {
background: rgba(0, 0, 0, 0.2);
content: "";
opacity: var(--back-y-multiplier);
}
.coin::before {
background: radial-gradient(circle at 25% 65%, transparent 50%, rgba(255, 255, 255, 0.9) 90%), linear-gradient(55deg, transparent
calc(var(--shine-bg-multiplier) + 0%), #e9f4ff calc(var(--shine-bg-multiplier) + 0%), transparent calc(var(
--shine-bg-multiplier
) + 50%));
content: "";
opacity: var(--shine-opacity-multiplier);
transform: translateY(calc(var(--middle-y-multiplier) * 0.3181818182rem / -2)) scaleY(var(--middle-scale-multiplier))
rotate(calc(var(--coin-rotation-multiplier) * 1deg));
z-index: 10;
}
.coin::after {
background: #737c99;
content: "";
height: 0.3181818182rem;
left: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 100%;
z-index: 2;
}

@keyframes shake {
0% {
transform: rotate(4deg);
}
66% {
transform: rotate(-4deg);
}
100% {
transform: rotate();
}
}

新建coin.js

新建 [Blogroot]\source\js\coin\coin.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
var tipButtons = document.querySelectorAll(".tip-button");

function coinAudio() {
var coinAudio = document.getElementById("coinAudio");
if (coinAudio) {
coinAudio.play(); //有音频时播放
}
}
// Loop through all buttons (allows for multiple buttons on page)
tipButtons.forEach(button => {
var coin = button.querySelector(".coin");

// The larger the number, the slower the animation
coin.maxMoveLoopCount = 90;

button.addEventListener("click", () => {
if (/Android|webOS|BlackBerry/i.test(navigator.userAgent)) return true; //媒体选择
if (button.clicked) return;
button.classList.add("clicked");

// Wait to start flipping th coin because of the button tilt animation
setTimeout(() => {
// Randomize the flipping speeds just for fun
coin.sideRotationCount = Math.floor(Math.random() * 5) * 90;
coin.maxFlipAngle = (Math.floor(Math.random() * 4) + 3) * Math.PI;
button.clicked = true;
flipCoin();
coinAudio();
}, 50);
});

var flipCoin = () => {
coin.moveLoopCount = 0;
flipCoinLoop();
};

var resetCoin = () => {
coin.style.setProperty("--coin-x-multiplier", 0);
coin.style.setProperty("--coin-scale-multiplier", 0);
coin.style.setProperty("--coin-rotation-multiplier", 0);
coin.style.setProperty("--shine-opacity-multiplier", 0.4);
coin.style.setProperty("--shine-bg-multiplier", "50%");
coin.style.setProperty("opacity", 1);
// Delay to give the reset animation some time before you can click again
setTimeout(() => {
button.clicked = false;
}, 300);
};

var flipCoinLoop = () => {
coin.moveLoopCount++;
var percentageCompleted = coin.moveLoopCount / coin.maxMoveLoopCount;
coin.angle = -coin.maxFlipAngle * Math.pow(percentageCompleted - 1, 2) + coin.maxFlipAngle;

// Calculate the scale and position of the coin moving through the air
coin.style.setProperty("--coin-y-multiplier", -11 * Math.pow(percentageCompleted * 2 - 1, 4) + 11);
coin.style.setProperty("--coin-x-multiplier", percentageCompleted);
coin.style.setProperty("--coin-scale-multiplier", percentageCompleted * 0.6);
coin.style.setProperty("--coin-rotation-multiplier", percentageCompleted * coin.sideRotationCount);

// Calculate the scale and position values for the different coin faces
// The math uses sin/cos wave functions to similate the circular motion of 3D spin
coin.style.setProperty("--front-scale-multiplier", Math.max(Math.cos(coin.angle), 0));
coin.style.setProperty("--front-y-multiplier", Math.sin(coin.angle));

coin.style.setProperty("--middle-scale-multiplier", Math.abs(Math.cos(coin.angle), 0));
coin.style.setProperty("--middle-y-multiplier", Math.cos((coin.angle + Math.PI / 2) % Math.PI));

coin.style.setProperty("--back-scale-multiplier", Math.max(Math.cos(coin.angle - Math.PI), 0));
coin.style.setProperty("--back-y-multiplier", Math.sin(coin.angle - Math.PI));

coin.style.setProperty("--shine-opacity-multiplier", 4 * Math.sin((coin.angle + Math.PI / 2) % Math.PI) - 3.2);
coin.style.setProperty("--shine-bg-multiplier", -40 * (Math.cos((coin.angle + Math.PI / 2) % Math.PI) - 0.5) + "%");

// Repeat animation loop
if (coin.moveLoopCount < coin.maxMoveLoopCount) {
if (coin.moveLoopCount === coin.maxMoveLoopCount - 6) button.classList.add("shrink-landing");
window.requestAnimationFrame(flipCoinLoop);
} else {
button.classList.add("coin-landed");
coin.style.setProperty("opacity", 0);
setTimeout(() => {
button.classList.remove("clicked", "shrink-landing", "coin-landed");
setTimeout(() => {
resetCoin();
}, 300);
}, 1500);
}
};
});

修改主题配置文件

修改 _config.butterfly.yml

1
2
3
4
5
6
# Sponsor/reward
reward:
enable: true
+ coinAudio: https://cdn.cbd.int/akilar-candyassets@1.0.36/audio/aowu.m4a
QR_code:
...
1
2
3
4
5
6
# CDN
CDN:
option:
...
+ coin_js: /js/coin/coin.js
+ coin_css: /css/coin/coin.css

此处的 https://cdn.cbd.int/akilar-candyassets@1.0.36/audio/aowu.m4a 可以自行下载并替换为本地链接

替换reward.styl

整体替换 [Blogroot]\themes\butterfly\source\css\_layout\reward.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
.post-reward
position: relative
margin-top: 4rem
width: 100%
text-align: center

.reward-button
display: inline-block
padding: .2rem 1.2rem
background: var(--btn-bg)
color: var(--btn-color)
cursor: pointer
transition: all .4s

&:hover
box-shadow: inset 15em 0 0 0 var(--btn-hover-color)

.reward-main
display: block

.reward-main
position: absolute
bottom: 40px
left: -25%
z-index: 100
display: none
padding: 0 0 15px
width: 150%

.reward-all
display: inline-block
margin: 0
padding: 1rem .5rem
border-radius: 4px
background: var(--reward-pop)

&:before
position: absolute
bottom: -10px
left: 0
width: 100%
height: 20px
content: ''

&:after
position: absolute
right: 0
bottom: 2px
left: 0
margin: 0 auto
width: 0
height: 0
border-top: 13px solid var(--reward-pop)
border-right: 13px solid transparent
border-left: 13px solid transparent
content: ''

.reward-item
display: inline-block
padding: 0 8px
list-style-type: none
vertical-align: top

img
width: 130px
height: 130px

.post-qr-code-desc
padding-top: .4rem
width: 130px
color: $reward-pop-up-color

完成

各配置项完成后,就可以见证奇迹
请使用 Hexo三连 秘法
然后进入任意文章,下滑找到 不给糖果就捣蛋 按钮
悬停时就是明示 V我50
点击一下会有惊喜哦