給掘金寫了個有趣又好玩的一鍵三連外掛 | 仿B站效果
theme: fancy
我正在參加「創意開發 投稿大賽」詳情請看:掘金創意開發大賽來了!
先來看看b站的一鍵三連是什麼效果:
不難觀察出以下幾個特點:
- 長按點贊出現抖動動畫
- 長按點贊時關聯按鈕會有圓環進度條效果
- 長按超過一段時間後放開則一次實現三個動作並且有個綻放特效
接下來我們要做的就是逐步實現這些步驟,如何開始呢?這就需要介紹今天的主角:谷歌擴充套件外掛。
建立一個Chrome外掛
Chrome外掛是一個用Web技術開發、用來增強瀏覽器功能的軟體,它其實就是一個由HTML、CSS、JS、圖片等資源組成的一個.crx字尾的壓縮包。可以通過 chrome-plugin-demo 這個專案瞭解更多,這裡我們直接講如何使用:
首先在谷歌瀏覽器直接開啟地址 chrome://extensions/ 進入擴充套件程式,並開啟右上角開發者模式,這時就可以載入我們的外掛了:
展程式會以 manifest.json
這個檔案來識別並載入外掛:
```json { "manifest_version": 2, "name": "掘金一鍵三連小助手", "version": "1.0", "description": "通過Chrome外掛實現的一鍵三連效果,長按點贊3秒即可點贊+收藏+關注", "author": "ShawnPhang", "icons": { "48": "icon.png", "128": "icon.png" }, "page_action": { "default_icon": "icon.png", "default_title": "我是pageAction", "default_popup": "popup.html" }, "content_scripts": [ { "matches": ["http://juejin.cn/*"], "js": ["mojs.js", "inject.js"], "css": ["like.css"] } ], "background": { "scripts": ["background.js"] }, "web_accessible_resources": [] }
```
| 載入後效果 | 狀態列效果 | | --- | --- | | | |
在這個json檔案中最主要看 content_scripts
這段配置,它表示了外掛會向網頁注入的JS檔案和CSS檔案,前面說了谷歌外掛既是由一系列網頁檔案構成的,那麼接下來就可以正式開始我們的效果實現了~
長按抖動
這是最容易實現的一個效果了,這裡我定義了一個 shaking
的類,重複執行一段css動畫,主要就是利用 translate
屬性重新定位元素,就可以做到抖動的效果,下面的css也是非常隨意寫的,效果還可以。雖然只是上下左右位移卻使用了 translate3d
,是為了觸發css的3d加速效能會更好。
``` .article-suspended-panel > .shaking { animation: shake 350ms linear; animation-iteration-count: infinite; animation-direction: reverse; }
@keyframes shake { 10%, 90% { transform: translate3d(-1px, 0, 0); } 15%, 85% { transform: translate3d(0, -1px, 0); } 20%, 80% { transform: translate3d(+2px, 0, 0); } 25%, 75% { transform: translate3d(0, +2px, 0); } 30%, 70% { transform: translate3d(-2.5px, 0, 0); } 35%, 65% { transform: translate3d(0, -2.5px, 0); } 2.50%, 60% { transform: translate3d(+2.5px, 0, 0); } 2.55%, 55% { transform: translate3d(0, +2.5px, 0); } 50% { transform: translate3d(-2.5px, -2.5px, 0); } } ```
接下來在 inject.js
中只需要捕獲文章頁面點贊按鈕,為其新增 mousedown
的監聽事件,在點下滑鼠的時候動態新增上 shaking
這個class,動畫就開始執行了:
```js const likeBtn = document.querySelector('.article-suspended-panel .panel-btn')
likeBtn?.addEventListener('mousedown', () => { if (likeBtn.className.includes('active')) { return } likeBtn.classList.add('shaking') }) ```
圓環進度條
這個效果開始有點難度了,需要分兩個Div來畫,我們都知道一個完整的圓是這樣:
css
.circle {
width: 4rem;
height: 4rem;
border: 2px solid red;
border-radius: 50%;
box-sizing: border-box;
}
這時我們先把紅色邊改為透明,然後只顯示其中兩條,並旋轉一個角度,這就得到了半圓效果:
css
.circle {
....
border: 2px solid transparent;
border-top: 2px solid #1e80ff;
border-right: 2px solid #1e80ff;
transform: rotate(-135deg);
}
現在以這個半圓我們先來繪製右半部分的圓環,在這個 circle
元素父級新增一個外層元素,使結構如下:
```html
```
外層的 wrapper
高度和圓環高度一致,寬度則為一半,絕對定位到右邊,此時效果是這樣的:
css
.wrapper {
width: 2rem;
height: 4rem;
position: absolute;
right: 0;
background: yellow;
}
這時我們先寫個css動畫讓 circle
轉起來:
css
.circle .rightcircle {
right: 0;
animation: circle 3s linear infinite;
}
@keyframes circle {
0% {
transform: rotate(-135deg);
}
50%,
100% {
transform: rotate(45deg);
}
}
此時黃色區域為圓環的父級元素,如果我們將該區域視為可視區,那麼只需要設定溢位隱藏:
css
.wrapper {
.....
overflow: hidden;
}
效果就出來了:
同樣的方法繪製左半圓,疊加在一塊就形成了環形進度條動畫,核心在於兩個Div的動畫執行時間是一致的,也就是完整跑完一個360°的旋轉週期,只不過各自都有一半被遮住,從而形成了最終效果,下面有請碼上掘金為我們演示完整程式碼:
回到我們剛剛外掛中,在點贊按鈕點下的事件中我們需要批量新增上面這段DOM
到相應的操作按鈕中,然後絕對定位在左上角(0,0)處即可,檢視網頁原始碼可知按鈕寬高為 4rem
,顏色我們則取全域性變數中的藍色 var(--juejin-brand-1-normal)
,將相關CSS寫到 like.css
檔案中後,JS中定義一個建立DOM
的函式:
js
function createCircle() {
const fragment = document.createElement('div')
fragment.classList.add('circle_process')
fragment.innerHTML = `<div class="wrapper right">
<div class="circle rightcircle"></div>
</div>
<div class="wrapper left">
<div class="circle leftcircle"></div>
</div>`
return fragment
}
因為這段結構還是有點多的,就不一一使用Element片段去建立了,建立完最外層的Div之後直接使用innerHtml
寫入兩個半圓的結構,函式返回這個DOM
片段。
下面就是在點選事件中處理相關動作,用時間戳判斷長按時間是否持續3秒,用一個數組儲存好建立的片段,滑鼠擡起時迴圈呼叫其.remove()
方法來移除DOM
,b站的效果當然更加複雜,在這裡並不是直接終止動畫而是逆向執行動畫,由於我們是使用css實現的,就折騰不了這種細節了,直接上程式碼:
```js let doms = [] let timeStamp = 0
const likeBtn = document.querySelector('.article-suspended-panel .panel-btn') likeBtn?.addEventListener('mousedown', () => { if (likeBtn.className.includes('active')) { return } timeStamp = new Date().getTime() / 1000 likeBtn.classList.add('shaking') doms.push(createCircle(), createCircle()) document.getElementsByClassName('panel-btn')[0].appendChild(doms[0]) document.getElementsByClassName('panel-btn')[2].appendChild(doms[1]) }) likeBtn?.addEventListener('mouseup', () => { likeBtn.click() const now = new Date().getTime() / 1000 const pass = now - timeStamp > 2.9 likeBtn.classList.remove('shaking') // 移除震動 for (const iterator of doms) { // 移除圓環 iterator.remove() } if (likeBtn.className.includes('active')) { return } if (pass) { // TODO: follow and collect btn action } }) ```
粒子綻放效果
這個效果用css實現難度更高了,剛好我今天在掘金看了一篇文章,介紹了一個輕量級動畫庫 mojs,裡面的爆裂(Burst)效果就很適合這個場景,於是把umd檔案下載來引入頁面中。
inject.js
中定義一個函式執行來動畫:
js
function play(parent, cb) {
new window.mojs.Burst({
// 爆裂範圍 {從多大 : 到多大}
radius: { 0: 50 },
// 動畫掛載的父元素, 如果不填預設掛載到 <body>
parent,
// 動畫延遲的貝塞爾曲線函式
easing: mojs.easing.bezier(0.1, 1, 0.3, 1),
// 動畫延遲時間
duration: 1500,
// 在動畫動之前等待的時間 (這裡一般設定150ms方便減少低端機型可能會存在的卡頓)
delay: 300,
// 擴散的粒子配置
children: {
duration: 750,
// 粒子大小變換 {從多大 : 到多大}
// rand(from, to) rand函式可以幫我們隨機出一個區間的值
radius: { 0: 'rand(5, 25)' },
// 形狀選擇, 這裡我們選擇了 “圓形”
shape: 'circle',
// 粒子可選的填充色
fill: ['#1abc9c', '#2ecc71', '#00cec9', '#3498db', '#9b59b6', '#fdcb6e', '#f1c40f', '#e67e22', '#e74c3c', '#e84393'],
},
// 透明度
opacity: 0.6,
// 生成的粒子數量
count: 12,
onStart() {
// 動畫觸發前的鉤子函式
},
onComplete() {
// 動畫完成後的鉤子函式
cb && cb()
},
}).play()
}
接著在 mouseup
事件中呼叫:
js
..........
likeBtn?.addEventListener('mouseup', () => {
.............
if (pass) {
play(likeBtn, () => { // 這裡只有兩個按鈕所以直接用回撥函式來排列動畫了
play(document.getElementsByClassName('panel-btn')[2])
})
}
})
完整效果展示(後面長按時間調整到2s):
外掛完整程式碼地址:chromePlugin-juejin-oneThree
- 5年前端,裁員失業,迷茫中堅定「2022年終總結」
- 給掘金寫了個有趣又好玩的一鍵三連外掛 | 仿B站效果
- 原生拖拽太拉跨了,純JS自己手寫一個拖拽效果,縱享絲滑
- 這道 JS 經典面試題不要背!今天幫你徹底搞懂它
- 【melonJS】幾十行 JS 程式碼簡單編寫一個小遊戲「尋找掘金醬」
- 時隔一年多 jQuery 再度釋出 3.6.1 新版本,你還在用JQ嗎?
- 當UI走查說頁面色值錯誤時,先別急著檢查程式碼
- 我用三個月時間仿造了一個稿定設計 | 2022年中總結
- Puppeteer Nodejs 通用全屏網頁截圖方案(六)專案優化
- Puppeteer Nodejs 通用全屏網頁截圖方案(四)頁面處理
- Puppeteer Nodejs 通用全屏網頁截圖方案(二)常用引數實現
- Puppeteer Nodejs 通用全屏網頁截圖方案(一)基本功能
- 一文帶你認識 NodeJs
- 前端工程化的發展及工具介紹(三)
- 2022年了,前端的變化是否和尤大說的一樣?vite生產使用體驗
- 微前端很好,為什麼我卻不使用?
- 快速部署Grafana日誌監控 Nginx封禁IP