国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

借助CSS實現(xiàn)點贊粒子動效

開發(fā) 前端
先從單個粒子看,其實就是一個拋物線運動,我們先從平拋運動開始。眾所周知,拋物線運動是一個水平方向上勻速、垂直方向上勻加速的合成運動。

大部分點擊效果都平平無奇,如果你碰到一個這樣的點擊效果,會不會忍不住多點幾次呢?

Kapture 2025-08-09 at 13.19.13Kapture 2025-08-09 at 13.19.13

看似有些復雜,其實分解開來,其實就兩個動畫。

  1. 粒子的拋物線動畫
  2. 數(shù)字的縮放動畫

下面來一步步實現(xiàn)它,花兩分鐘一起看看吧!

一、CSS 拋物線運動

先從單個粒子看,其實就是一個拋物線運動,我們先從平拋運動開始。

眾所周知,拋物線運動是一個水平方向上勻速、垂直方向上勻加速的合成運動。

image-20250809133654026image-20250809133654026

這個其實用 CSS 動畫也很好實現(xiàn),水平和垂直兩個方向的位移動畫分別用不同的動畫緩存函數(shù)。

這里簡單介紹一下:

實現(xiàn)這樣的效果需要一個嵌套結(jié)構(gòu)。

<div class="ball-x">
  <div class="ball-y"></div>
</div>

然后里外設(shè)置不同的動畫緩沖函數(shù)。

.ball-x { 
  animation-timing-function: linear; /*勻速直線運動*/
}
.ball-y { 
  animation-timing-function: cubic-bezier(.55, 0, .85, .36);  /*大致勻加速運動*/
}

運動分解效果如下:

Kapture 2023-04-21 at 17.26.05Kapture 2023-04-21 at 17.26.05

當然,這里為了兼容性考慮,使用了兩層標簽,其實還可以使用單層標簽實現(xiàn),需要用到動畫合成屬性。

回到我們的例子,假設(shè)單個粒子的HTML是這樣的。

<div class="custom-tips" style="left: 50%; top: 50%;">
    <div class="custom-tips-dot" emoji="??"></div>
 </div>

關(guān)鍵樣式如下:

.custom-tips {
position: absolute;
width: 1em;
height: 1em;
margin-left: -.5em;
margin-top: -.5em;
left: 0;
top: 0;
transform: translate(var(--left, 50%), var(--top, 50%));
}
.custom-tips-dot {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
animation: custom-x 1s linear forwards;
}
.custom-tips-dot::before {
content: attr(emoji, '??');
animation: custom-y 1scubic-bezier(0.55, 0, 0.85, 0.36);
}

/* x方向 */
@keyframes custom-x {
  100% {
    transform: translateX(300%);
  }
}
/* y方向 */
@keyframes custom-y {
  100% {
    transform: translateY(300%);
  }
}

效果如下(綠色線框是水平運動):

Kapture 2025-08-09 at 14.03.54Kapture 2025-08-09 at 14.03.54

這樣就簡單實現(xiàn)了一個平拋運動。

二、CSS 斜拋運動

平拋運動可能沒有那種禮花綻放的感覺,有點平淡,我們還需要有一定角度朝上做斜拋運動。

看著好像有點復雜?其實就是多了一個向上的初始速度,示意如下:

image-20250809141915739image-20250809141915739

這個在 JS中很好實現(xiàn),給一個初始值就行,垂直方向上先往上減速,一直到 0,然后開始加速,這樣整體就是一個斜拋運動了。

那么,CSS 如何處理呢?好像并沒有這種概念。

其實呢,可以從緩沖函數(shù)入手,比如上面用到的緩沖函數(shù)是cubic-bezier(0.55, 0, 0.85, 0.36),是一種逐漸變快的運動。

image-20250809142326339image-20250809142326339

這時,我們可以改變第一個錨點,往下拉,直到第二個值出現(xiàn)負數(shù),如下:

image-20250809142536888image-20250809142536888

這樣會出現(xiàn)一個輕微的回彈效果,效果如下:

Kapture 2025-08-09 at 14.26.33Kapture 2025-08-09 at 14.26.33

是不是有點像斜拋運動了?

我們可以繼續(xù)調(diào)整幅度,讓回彈效果更強烈一些,比如:

image-20250809143033923image-20250809143033923

這樣就更接近真實的斜拋運動了。

Kapture 2025-08-09 at 14.29.11Kapture 2025-08-09 at 14.29.11

關(guān)鍵 CSS 如下:

.custom-tips-dot::before {
    content: attr(emoji, '??');
    animation: custom-y 1s cubic-bezier(0.56, -1.35, 0.85, 0.36) forwards;
  }

是不是也比較容易?

三、借助JS批量生產(chǎn)

單個粒子可能比較死板,也不夠隨機。

要實現(xiàn)隨機也比較容易,每次生成例子的水平位移不同就行了,然后多個粒子的動畫有一定的延時就可以了。

image-20250809235534054image-20250809235534054

為了方便JS透傳過去,可以借助CSS變量來生成。

這里用--x表示水平位移,--d表示延遲。

.custom-tips-dot {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
outline: 1px solid yellowgreen;
animation: custom-x 1svar(--d, 0s) linear forwards; 
}
.custom-tips-dot::before {
content: attr(emoji, '??');
animation: custom-y 1svar(--d, 0s) cubic-bezier(0.56, -1.35, 0.85, 0.36) forwards;
}
/* x方向 */
@keyframes custom-x {
  0% {
    opacity: 0;
    transform: translateX(0%)
  }
  10%, 90% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translateX(var(--x, 300%)); /*隨機的水平位移*/
  }
}

然后用 JS動態(tài)生成這些 dom。

function createDots(emojis) {
const temp = document.createDocumentFragment();
const random_emojis = emojis.slice(0, Math.ceil(Math.random() * emojis.length)).sort(() =>Math.random() - .5)
  random_emojis.forEach(emoji => {
    const dot = document.createElement('div');
    dot.className = 'custom-tips-dot';
    dot.setAttribute('emoji', emoji);
    dot.style.setProperty('--d', `${Math.random() * 0.2}s`);
    dot.style.setProperty('--x', `${(Math.random() - 0.5) * 1000}%`);
    temp.appendChild(dot);
    /*動畫結(jié)束后自動移除dom*/
    dot.addEventListener('animationend', () => {
      console.log('dot.parentNode', dot.parentNode, dot.parentNode?.childElementCount)
      if (dot?.parentNode?.childElementCount <= 1) {
        dot.parentNode.remove();
      } else {
        dot.remove();
      }
    });
  })
return temp;
}

document.addEventListener('click',(ev) => {
const { clientX, clientY } = ev;
console.log(clientX, clientY);
document.body.style.setProperty('--left', `${clientX}px`);
document.body.style.setProperty('--top', `${clientY}px`);
const tips = document.createElement('div');
  tips.style.setProperty('--left', `${clientX}px`);
  tips.style.setProperty('--top', `${clientY}px`);
  tips.className = 'custom-tips';
const dots = createDots(['??', '??', '??', '??', '??', '??', '??']);
  tips.appendChild(dots);
document.body.appendChild(tips);
})

這樣就能每次隨機生成一定數(shù)量的emoji了,效果如下:

Kapture 2025-08-09 at 14.39.25Kapture 2025-08-09 at 14.39.25

四、+1 動畫

數(shù)字變化動畫是最簡單的,就是一個縮放+透明度變化的動畫。

image-20250810000526217image-20250810000526217

假設(shè)HTML是這樣的:

<div class="custom-num" num="1"></div>

我們用偽元素來生成+1的字符,動畫很簡單,就兩個關(guān)鍵幀,實現(xiàn)如下:

.custom-num {
position: absolute;
left: 0;
top: 0;
display: flex;
width: 2em;
height: 2em;
font-size: 2em;
color: #fff;
justify-content: center;
align-items: center;
margin-left: -1em;
margin-top: -2em;
font-weight: bold;
text-shadow: 4px4px0rgba(255,0,0);
transform: translate(var(--left), var(--top));
}
.custom-num::before {
content: '+'attr(num);
opacity: 0;
animation: count-shark 1svar(--d, 0s);
}
@keyframes count-shark {
  0%,100%{
    opacity: 0;
    transform: scale(.4);
  }

  30%,70%{
    opacity: 1;
    transform: scale(1);
  }
}

效果如下:

Kapture 2025-08-09 at 14.46.13Kapture 2025-08-09 at 14.46.13

然后我們借助JS來實現(xiàn)數(shù)字增加的邏輯,其實就是移除上一個,新增一個dom,新增的會自動執(zhí)行動畫,實現(xiàn)如下:

function createNum() {
const current = document.querySelector('.custom-num');
let num = 1
if (current) {
    num = parseInt(current.getAttribute('num')) + 1;
    current.remove();
  }
const numDiv = document.createElement('div');
  numDiv.className = 'custom-num';
if (num > 1) {
    // numDiv.style.setProperty('--d','-.3s' )
  }
  numDiv.setAttribute('num', num);
  numDiv.addEventListener('animationend', () => {
    numDiv.remove();
  });
return numDiv;
}

最后兩者結(jié)合起來,就實現(xiàn)了文章開頭所示效果:

Kapture 2025-08-09 at 13.19.13Kapture 2025-08-09 at 13.19.13

你也可以訪問在線demo真實體驗:https://codepen.io/xboxyan/pen/wBKqpXb

五、其實canvas可能更適合

一般來說,粒子動畫可能canvas來實現(xiàn)更合適一點,性能也更好,不過可能對新手不太友好。這里推薦一個開箱即用的庫:叫做 Canvas Confetti,專門用來做這種禮花綻放特效的,如果自己手搓不來,可以試試這個。

不過我們這里案例的粒子也不是很多,所以使用CSS也無所謂了。

責任編輯:武曉燕 來源: 前端偵探
相關(guān)推薦

2020-01-10 15:15:53

Redis點贊數(shù)據(jù)庫

2022-09-01 06:54:28

CSS前端

2022-03-31 07:46:17

CSS動畫技巧

2012-05-09 12:25:55

2013-06-07 15:43:34

移動移動應用豐富動效

2025-09-12 13:24:36

2021-08-10 15:37:34

鴻蒙HarmonyOS應用

2020-12-03 11:00:29

Spring ClouRedis數(shù)據(jù)庫

2023-06-05 15:00:13

書籍翻頁動效鴻蒙

2015-07-31 11:40:36

動效Swift

2017-03-23 10:21:57

CSS3動效庫前端

2021-04-15 07:50:45

Veu 動效Vue應用程序

2021-06-21 15:49:39

React動效組件

2015-08-03 10:40:45

動效設(shè)計優(yōu)勢

2014-09-28 10:39:24

AppleWatchUI

2025-08-18 09:18:46

2022-08-22 20:10:59

自定義計數(shù)器CSS

2019-07-24 09:00:19

谷歌Android開發(fā)者

2021-03-04 06:14:03

CSS webkit-box-動效

2015-07-17 10:41:59

點贊按鈕
點贊
收藏

51CTO技術(shù)棧公眾號

国产免费黄视频在线观看| 北条麻妃一区二区三区在线| 日韩一区在线免费观看| 西游记1978| 欧美一级精品| 68精品国产免费久久久久久婷婷| 成人勉费视频| 亚洲国产精品99| 影音先锋男人在线资源| 成人片在线看| 福利精品视频在线| 国产成人午夜| 国产美女一区二区| 欧美中文字幕一区| 超级碰碰不卡在线视频| 国产91精品久久久久| 你懂的视频在线| 97精品视频在线| 精品一区二区在线免费观看| 人妻久久久一区二区三区| 国产欧美精品一区二区色综合 | 日韩美女视频在线观看| 在线免费三级电影网站| 久久久久亚洲精品国产| 91精品国产乱码久久久久久| 国产精品高潮视频| 国产videos久久| 国产精品永久免费视频| 国产精品伦理久久久久久| 68精品久久久久久欧美| 国产精品秘入口| 中文字幕一区二| 一区二区三区国产免费| 99久久精品一区二区| 91动漫在线看| 欧美日韩国产丝袜另类| 日本精品在线一区| 一本一本久久a久久精品综合妖精| 97精品视频在线观看自产线路二| 在线观看免费网站黄| 亚洲国产三级在线| 麻豆传媒视频在线观看| 久久久久久伊人| 国产美女在线观看一区| 精品视频一区二区三区四区五区| 亚洲日本无吗高清不卡| 国产精品久久毛片a| 水蜜桃亚洲精品| 欧美99久久| 高清不卡日本v二区在线| 日韩成人av影视| 欧美xxxbbb| 97久久精品人搡人人玩| 99视频一区| 在线观看免费观看在线91| 亚洲免费高清视频| 欧美xxxx中国| 成人黄动漫网站免费| 精品夜夜嗨av一区二区三区| 日本一道本久久| 日韩欧美一区视频| 欧美日韩美女| 产国精品偷在线| 日韩午夜中文字幕| 日本免费在线一区| 黑人与亚洲人色ⅹvideos| 久久精品五月婷婷| 成人免费电影视频| 91香蕉视频导航| 怡红院精品视频| 欧美人与拘性视交免费看| 97久久视频| 翔田千里亚洲一二三区| 日本一区二区三级电影在线观看 | 日韩电影大全在线观看| 日韩精品成人一区二区三区 | 亚洲成av人**亚洲成av**| 久cao在线| 欧美有码在线视频| 看片网站欧美日韩| 一个人看的www一区| 在线观看欧美www| 国产综合久久| 五月天av在线播放| 亚洲欧美在线看| 亚洲黑丝一区二区| 高清日韩av| 色狠狠av一区二区三区香蕉蜜桃| 亚洲欧洲日本mm| 大地资源高清播放在线观看| xvideos亚洲| 国内精品写真在线观看| 大地资源中文在线观看免费版| 欧美黑人视频一区| 国产成人在线看| 美足av综合网| 国产精品免费观看高清| 亚洲精品日韩一| 午夜久久av| 日本日本19xxxⅹhd乱影响| 欧美成人高清电影在线| 欧美涩涩视频| 在线三级av| 97成人超碰免| 久久久久久影视| 日产精品一区| 日本视频精品一区| 欧美日韩一区二区欧美激情| 成人a'v在线播放| 国产羞羞视频| 色在人av网站天堂精品| 久久综合久久鬼色| 黄色成人在线观看网站| 国产夫妻自拍一区| 亚洲毛片在线观看| 国产真实乱偷精品视频免| 污污视频在线| 欧美一级日本a级v片| 欧美高清视频一二三区| 亚洲欧美清纯在线制服| 97超碰国产一区二区三区| 国产精品xxx在线观看www| 欧美日韩在线第一页| 香蕉av一区二区| 91大神在线网站| 免费观看国产成人| 精品国产一区二区国模嫣然| 日本午夜精品视频在线观看 | 青草久久视频| 四虎免费av| 欧洲美女免费图片一区| 日韩久久一区二区| 岳的好大精品一区二区三区| 国产一级大片| 国产免费一区视频观看免费| 午夜精品一区二区三区三上悠亚| 色综合色综合| 国产永久免费高清在线观看| 激情视频一区二区| 日韩欧美国产一区二区三区| 蜜桃视频在线一区| 日韩福利一区| 波多野结衣天堂| 欧美在线视频观看| 狠狠躁夜夜躁人人躁婷婷91| 在线成人h网| 蜜臀av在线播放| 野外做受又硬又粗又大视频√| 久久夜色精品国产亚洲aⅴ| 国产精品久久久久久久久久免费看| 日韩手机在线| 久久精品蜜桃| 亚洲一区二区三区免费观看| 中文字幕v亚洲ⅴv天堂| 国产精品乱码一区二区三区软件 | 免费黄色片在线观看| 国产精品乱码视频| 日韩高清人体午夜| 久久久亚洲午夜电影| 国内精品久久久久久99蜜桃| 国产女人在线观看| 亚洲精美视频| 欧美高清电影在线看| 色综合久久88色综合天天| 久久99精品久久只有精品| 国产精品久久久久久久久久辛辛| 黄色成人av| 日本欧洲国产一区二区| 精品国产欧美一区二区五十路| 亚洲精品视频自拍| 日韩国产高清在线| 福利在线一区| 阿v免费在线观看| 国产精品国产对白熟妇| 国产91网红主播在线观看| 欧美精品乱码久久久久久按摩| 成人免费毛片aaaaa**| 国产一区二区观看| wwww在线观看免费视频| 成人漫画网站免费| 欧美不卡1区2区3区| 久久在线精品视频| 欧美午夜电影网| 国产午夜亚洲精品羞羞网站| 9国产精品视频| 国产一级成人av| 牛牛电影国产一区二区| 久久.com| 女人被男人躁得好爽免费视频| 国产日韩视频在线观看| 中文字幕国产精品| 欧美日韩国产色站一区二区三区| 国产偷国产偷精品高清尤物| 久久久人人人| 成久久久网站| 亚洲人成777| 四季久久免费一区二区三区四区| 国产.com| 欧美一级在线看| 日韩国产伦理|