Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
何用原生JavaScript寫一個(gè)氣泡的效果。話不多說(shuō),直接上代碼。
script腳本如下:
html代碼如下:
是不是很簡(jiǎn)單呢。然后我們用手機(jī)看看效果
手指點(diǎn)擊屏幕,或者在電腦上打開(kāi),鼠標(biāo)移動(dòng)時(shí),氣泡也會(huì)跟隨移動(dòng)
效果不錯(cuò),建議收藏哦
通訊應(yīng)用和聊天界面中,當(dāng)你正在與對(duì)方交談時(shí)對(duì)方正在輸入一條信息,會(huì)有一個(gè)小的氣泡動(dòng)畫或者文案提示。本文將探討使用現(xiàn)代 CSS 來(lái)實(shí)現(xiàn)這一動(dòng)畫效果,首先會(huì)實(shí)現(xiàn)一個(gè) Blink 效果的動(dòng)畫,然后實(shí)現(xiàn)一個(gè)波浪效果動(dòng)畫,最后實(shí)現(xiàn)一個(gè)語(yǔ)音氣泡效果。
1)Blink 效果:
2)Wave 效果:
3)語(yǔ)音氣泡效果:
通過(guò) html:5 和 div.container>(div.dot)*3 快速創(chuàng)建頁(yè)面及容器。
<div class="container">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
1)容器居中:
body {
display: grid;
place-content: center;
min-height: 100vh;
margin: 0;
}
2)容器樣式:
注意:此處使用了現(xiàn)代CSS 原生嵌套(參考鏈接:)
.container {
display: flex;
justify-content: center;
align-items: center;
gap: 0.25rem;
background: #e2e8f0;
border-radius: 9999px;
padding: 1rem;
.dot {
border-radius: 9999px;
height: 0.5rem;
width: 0.5rem;
background: #93a2b7;
}
}
1)Blink 效果:
核心思想是通過(guò)給dot 元素設(shè)置 opacity 設(shè)置屬性來(lái)改變其透明度,同時(shí)對(duì) 3 個(gè) dot 的透明度變化設(shè)置不同的動(dòng)畫延遲 animation-delay 屬性來(lái)實(shí)現(xiàn)閃爍的效果。
.container {
.dot {
opacity: 0;
animation: blink 1s infinite;
&:nth-child(1) {
animation-delay: 0.3333s;
}
&:nth-child(2) {
animation-delay: 0.6666s;
}
&:nth-child(3) {
animation-delay: 0.9999s;
}
}
}
@keyframes blink {
50% {
opacity: 1;
}
}
2)Wave 效果:
核心思想:給 dot 元素增加 transform 屬性,設(shè)置 translateY 的值將目標(biāo)元素從下至上垂直重新定位,同時(shí)在動(dòng)畫關(guān)鍵幀 keyframes 中對(duì)顏色進(jìn)行調(diào)整。
.container {
.dot {
animation: wave 1s infinite;
}
}
@keyframes wave {
0% {
transform: translateY(0px);
background: rgba(148 163 184 / 0);
}
25% {
transform: translateY(-0.25rem);
background: rgba(148 163 184 / 0.8);
}
50% {
transform: translateY(0px);
background: rgba(148 163 184 / 0);
}
75% {
transform: translateY(0.25rem);
background: rgba(148 163 184 / 0.8);
}
100% {
transform: translateY(0);
background: rgba(148 163 184 / 0);
}
}
2)語(yǔ)音氣泡效果:
語(yǔ)音氣泡是以可視化方式顯示對(duì)話或思想的一種流行而有效的方法。你可能在漫畫、卡通、廣告和社交媒體文章中見(jiàn)過(guò)它們。它們?yōu)樵O(shè)計(jì)增添了幽默、情感和個(gè)性,同時(shí)也為觀眾提供了語(yǔ)境。此外,語(yǔ)音氣泡布局還可以將文字較多的設(shè)計(jì)分割開(kāi)來(lái),使其更加吸引人。
核心思想:在 wave 效果的基礎(chǔ)上,對(duì) .contianer 容器增加 ::before 和 ::after 兩個(gè)偽元素來(lái)實(shí)現(xiàn)左下角的圓圈,同時(shí)動(dòng)畫中增加對(duì)整個(gè)容器的放大和縮小 scale 動(dòng)畫,并采用 ease-out 函數(shù)。
.container {
animation: 2s zoom infinite ease-out;
position: relative;
&::before,
&::after {
content: '';
position: absolute;
border-radius: 9999px;
background: rgb(226 232 240);
bottom: 0;
left: 0;
}
&::before {
height: 1rem;
width: 1rem;
transform: translate(-0.125rem, 0.125rem);
}
&::after {
height: 0.5rem;
width: 0.5rem;
transform: translate(-0.5rem, 0.5rem);
}
.dot {
border-radius: 9999px;
height: 0.5rem;
width: 0.5rem;
background: rgba(148 163 184 / 1);
animation: wave 1.2s infinite;
&:nth-child(1) {
animation-delay: 0.4s;
}
&:nth-child(2) {
animation-delay: 0.8s;
}
&:nth-child(3) {
animation-delay: 1.2s;
}
}
}
@keyframes zoom {
50% {
transform: scale(1.1);
}
}
如果本文對(duì)您有幫助,歡迎關(guān)注、點(diǎn)贊和轉(zhuǎn)發(fā),感謝您的支持!
家好! 歡迎來(lái)到本教程,我們將深入了解使用 HTML 畫布和 JavaScript 在代碼中創(chuàng)建有趣的氣泡的世界。 最好的部分? 我們將只使用一點(diǎn) HTML 和所有 JavaScript,而不是 CSS 來(lái)實(shí)現(xiàn)所有這一切。
今天,我們要掌握以下幾個(gè)概念:
使用畫布上下文的 arc 方法創(chuàng)建圓。
利用 requestAnimationFrame 函數(shù)實(shí)現(xiàn)平滑的圓形動(dòng)畫。
利用 JavaScript 類的強(qiáng)大功能來(lái)創(chuàng)建多個(gè)圓圈,而無(wú)需重復(fù)代碼。
向我們的圓圈添加描邊樣式和填充樣式以獲得 3D 氣泡效果。
你可以跟著我一起看,或者如果你想看源代碼,可以使用最終的codepen
首先,我們需要一個(gè) HTML5 Canvas 元素。 Canvas 是創(chuàng)建形狀、圖像和圖形的強(qiáng)大元素。 這就是氣泡將產(chǎn)生的地方。 讓我們來(lái)設(shè)置一下 -
<canvas id="canvas"></canvas>
為了使用畫布做任何有意義的事情,我們需要訪問(wèn)它的上下文。 Context 提供了在畫布上渲染對(duì)象和繪制形狀的接口。
讓我們?cè)L問(wèn)畫布及其上下文。
const canvas=document.getElementById('canvas');
const context=canvas.getContext('2d');
我們將設(shè)置畫布以使用整個(gè)窗口的高度和寬度 -
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
讓我們通過(guò)添加一些 css 為畫布提供一個(gè)漂亮的舒緩淺藍(lán)色背景。 這是我們要使用的唯一 CSS。 如果您愿意,也可以使用 JavaScript 來(lái)完成此操作。
#canvas {
background: #00b4ff;
}
讓我們進(jìn)入有趣的部分。 我們將通過(guò)單擊畫布來(lái)創(chuàng)建氣泡。 為了實(shí)現(xiàn)這一點(diǎn),我們首先創(chuàng)建一個(gè)點(diǎn)擊事件處理程序:
canvas.addEventListener('click', handleDrawCircle);
由于我們需要知道在畫布上單擊的位置,因此我們將在句柄 DrawCircle 函數(shù)中跟蹤它并使用事件的坐標(biāo) -
//We are adding x and y here because we will need it later.
let x, y
const handleDrawCircle=(event)=> {
x=event.pageX;
y=event.pageY;
// Draw a bubble!
drawCircle(x, y);
};
為了創(chuàng)建圓圈,我們將利用畫布上下文中可用的 arc 方法。 Arc 方法接受 x 和 y - 圓心、半徑、起始角和結(jié)束角,對(duì)于我們來(lái)說(shuō),這將是 0 和 2* Math.PI,因?yàn)槲覀冋趧?chuàng)建一個(gè)完整的圓。
const drawCircle=(x, y)=> {
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.strokeStyle='white';
context.stroke();
};
現(xiàn)在我們有了圓圈,讓我們讓它們移動(dòng),因?yàn)椤?/p>
GIF
請(qǐng)記住,當(dāng)我們創(chuàng)建圓時(shí),我們使用了 arc 方法,它接受 x 和 y 坐標(biāo) - 圓的中心。 如果我們快速移動(dòng)圓的 x 和 y 坐標(biāo),就會(huì)給人一種圓在移動(dòng)的印象。 讓我們?cè)囋嚢桑?/span>
//Define a speed by which to increment to the x and y coordinates
const dx=Math.random() * 3;
const dy=Math.random() * 7;//Increment the center of the circle with this speed
x=x + dx;
y=y - dy;
我們可以將其移至函數(shù)內(nèi) -
let x, y;
const move=()=> {
const dx=Math.random() * 3;
const dy=Math.random() * 7; x=x + dx;
y=y - dy;
};
為了讓我們的圓圈無(wú)縫移動(dòng),我們將創(chuàng)建一個(gè)動(dòng)畫函數(shù)并使用瀏覽器的 requestAnimationFrame 方法來(lái)創(chuàng)建一個(gè)移動(dòng)的圓圈。
const animate=()=> {
context.clearRect(0, 0, canvas.width, canvas.height);
move();
drawCircle(x,y); requestAnimationFrame(animate);
};//Don't forget to call animate at the bottom
animate();
現(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè)圓圈,是時(shí)候創(chuàng)建多個(gè)圓圈了!
但在我們創(chuàng)建多個(gè)圓圈之前,讓我們準(zhǔn)備一下我們的代碼。為了避免重復(fù)我們的代碼,我們將使用類并引入 Particle 類。 粒子是我們動(dòng)態(tài)藝術(shù)作品和動(dòng)畫的構(gòu)建塊。 每個(gè)氣泡都是一個(gè)粒子,具有自己的位置、大小、運(yùn)動(dòng)和顏色屬性。 讓我們定義一個(gè) Particle 類來(lái)封裝這些屬性:
class Particle {
constructor(x=0, y=0) {}
draw() {
// Drawing the particle as a colored circle
// ...
} move() {
// Implementing particle movement
// ...
}
}
讓我們將一些已設(shè)置的常量移至 Particle 類 -
class Particle {
constructor(x=0, y=0) {
this.x=x;
this.y=y;
this.radius=Math.random() * 50;
this.dx=Math.random() * 3;
this.dy=Math.random() * 7;
}
draw() {
// Drawing the particle as a colored circle
// ...
} move() {
// Implementing particle movement
// ...
}
}
draw 方法將負(fù)責(zé)在畫布上渲染粒子。 我們已經(jīng)在drawCircle中實(shí)現(xiàn)了這個(gè)功能,所以讓我們將它移動(dòng)到我們的類中并將變量更新為類變量
class Particle {
constructor(x=0, y=0) {
this.x=x;
this.y=y;
this.radius=Math.random() * 50;
this.dx=Math.random() * 3;
this.dy=Math.random() * 7;
this.color='white';
}
draw() {
context.beginPath();
context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
context.strokeStyle=this.color;
context.stroke(); context.fillStyle=this.color;
context.fill();
} move() {}
}
同樣,讓我們?cè)陬愔幸苿?dòng) move 函數(shù) -
move() {
this.x=this.x + this.dx;
this.y=this.y - this.dy;
}
現(xiàn)在,我們需要確保在事件處理程序中調(diào)用 Particle 類。
const handleDrawCircle=(event)=> {
const x=event.pageX;
const y=event.pageY;
const particle=new Particle(x, y);
};canvas.addEventListener('click', handleDrawCircle);
由于我們需要在 animate 函數(shù)中訪問(wèn)該粒子,以便調(diào)用其 move 方法,因此我們將該粒子存儲(chǔ)在一個(gè)名為 molecularArray 的數(shù)組中。 當(dāng)創(chuàng)建大量粒子時(shí),這個(gè)數(shù)組也會(huì)很有幫助。 這是反映這一點(diǎn)的更新代碼 -
const particleArray=[];
const handleDrawCircle=(event)=> {
const x=event.pageX;
const y=event.pageY; const particle=new Particle(x, y);
particleArray.push(particle);
};canvas.addEventListener('click', handleDrawCircle);
記得也要更新動(dòng)畫功能 -
此時(shí),您將在屏幕上看到這個(gè)粒子 -
驚人的! 現(xiàn)在,到了有趣的部分! 讓我們創(chuàng)建很多圓圈并設(shè)計(jì)它們的樣式,使它們看起來(lái)像氣泡。
為了創(chuàng)建大量氣泡,我們將使用 for 循環(huán)創(chuàng)建粒子并將它們添加到我們?cè)诖颂巹?chuàng)建的粒子數(shù)組中。
const handleDrawCircle=(event)=> {
const x=event.pageX;
const y=event.pageY;
for (let i=0; i < 50; i++) {
const particle=new Particle(x, y);
particleArray.push(particle);
}
};canvas.addEventListener('click', handleDrawCircle);
在動(dòng)畫函數(shù)中,我們將通過(guò)清除畫布并在新位置重新繪制粒子來(lái)不斷更新畫布。 這會(huì)給人一種圓圈在移動(dòng)的錯(cuò)覺(jué)。
const animate=()=> {
context.clearRect(0, 0, canvas.width, canvas.height);
particleArray.forEach((particle)=> {
particle?.move();
particle?.draw();
}); requestAnimationFrame(animate);
};animate();
現(xiàn)在我們有了移動(dòng)的氣泡,是時(shí)候給它們添加顏色,使它們看起來(lái)像氣泡了!
我們將通過(guò)向氣泡添加漸變填充來(lái)實(shí)現(xiàn)此目的。 這可以使用 context.createRadialGradient 方法來(lái)完成。
const gradient=context.createRadialGradient(
this.x,
this.y,
1,
this.x + 0.5,
this.y + 0.5,
this.radius
);
gradient.addColorStop(0.3, 'rgba(255, 255, 255, 0.3)');
gradient.addColorStop(0.95, '#e7feff');context.fillStyle=gradient;
恭喜! 您剛剛僅使用 HTML Canvas 和 JavaScript 創(chuàng)建了一些超級(jí)有趣的東西。 您已經(jīng)學(xué)習(xí)了如何使用 arc 方法、利用 requestAnimationFrame、利用 JavaScript 類的強(qiáng)大功能以及使用漸變?cè)O(shè)計(jì)氣泡以實(shí)現(xiàn) 3D 氣泡效果。
請(qǐng)隨意嘗試顏色、速度和大小,使您的動(dòng)畫真正獨(dú)一無(wú)二。
請(qǐng)隨意嘗試顏色、速度和大小,使您的動(dòng)畫真正獨(dú)一無(wú)二。
我希望您在學(xué)習(xí)本教程時(shí)能像我在創(chuàng)建它時(shí)一樣獲得樂(lè)趣。 現(xiàn)在,輪到你進(jìn)行實(shí)驗(yàn)了。 我很想看看你是否嘗試過(guò)這個(gè)以及你創(chuàng)造了什么。 與我分享您的代碼鏈接,我很樂(lè)意查看。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。