摘要:嘗試實(shí)現(xiàn)畫出一個(gè)彈射的小球很簡(jiǎn)單,那怎么用多個(gè)小球?qū)崿F(xiàn)這樣的效果呢。
本文首發(fā)于我的博客,這是我的github,歡迎star。
??這篇博客是模仿nest.js實(shí)現(xiàn)一個(gè)demo,由簡(jiǎn)單到復(fù)雜,來一步步的實(shí)現(xiàn)它。這里是效果預(yù)覽。我的github里邊還有很多別的前端的demo,喜歡的話可以點(diǎn)個(gè)star,你的支持就是我的動(dòng)力。
從一道面試題開始實(shí)現(xiàn)一個(gè)半徑10px的小球在500px*500px的方塊中做直線運(yùn)動(dòng),初始方向隨機(jī),速度保持不變,碰撞到墻壁后反彈。
??看下效果,思路很簡(jiǎn)單,將小球定位在方塊中,設(shè)置xy方向上的速度,每幀動(dòng)畫給小球定位的值加上對(duì)應(yīng)方向的速度值,在檢測(cè)到小球碰撞墻壁的時(shí)候,將對(duì)應(yīng)方向的速度置為反方向就可以了。這里是實(shí)現(xiàn)的代碼,沒有用到canvas,但是思路一致。
嘗試實(shí)現(xiàn)??畫出一個(gè)彈射的小球很簡(jiǎn)單,那怎么用多個(gè)小球?qū)崿F(xiàn)nest.js這樣的效果呢。這樣的特效肯定不能用Dom直接做,太耗費(fèi)性能,也做不出來,這時(shí)就顯露出canvas的強(qiáng)大之處了。
??同樣的,用canvas生成多個(gè)彈來彈去的小球。首先不要管鼠標(biāo)如何吸附這些小圓點(diǎn),只做小球之間的連線。在每次繪制小球之前,判斷一下它和之前的小球的距離是不是小于極限距離,小于就以它倆為端點(diǎn)繪制一條線。代碼如下,思路都寫在注釋里:
const theCanvas = document.getElementById("theCanvas"), ctx = theCanvas.getContext("2d"), mix = 6000; //會(huì)產(chǎn)生連線的極限距離的平方 //將canvas鋪滿瀏覽器 let canvas_width = theCanvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, canvas_height = theCanvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight, points = []; theCanvas.style = "position: fixed; top: 0px; left: 0px;"; //繪制函數(shù),用requestAnimationFrame調(diào)用實(shí)現(xiàn)動(dòng)畫 function draw() { //清屏 ctx.clearRect(0, 0, canvas_width, canvas_height); let i,pi,x_dist,y_dist; //遍歷點(diǎn)集合繪制線條 points.forEach((p, index) => { p.x += p.xa, //按指定速度移動(dòng) p.y += p.ya, p.xa *= p.x > canvas_width || p.x < 0 ? -1 : 1, p.ya *= p.y > canvas_height || p.y < 0 ? -1 : 1, ctx.fillRect(p.x - 0.5, p.y - 0.5, 1, 1); //繪制點(diǎn),其實(shí)是小方塊 //類似于握手問題,兩個(gè)點(diǎn)之間只繪制一次線 for(i = index + 1; i < points.length; i++) { pi = points[i]; x_dist = p.x - pi.x; y_dist = p.y - pi.y; dist = x_dist * x_dist + y_dist * y_dist; //判斷點(diǎn)之間的距離是否小于極限距離 if(dist < mix) { ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(pi.x, pi.y); ctx.stroke(); } } }),requestAnimationFrame(draw); } //隨機(jī)生成100個(gè)點(diǎn) for(let i = 0; i < 100; i++ ) { let x = Math.random() * canvas_width, //初始坐標(biāo) y = Math.random() * canvas_height, xa = 2 * Math.random() - 1, //x速度 ya = 2 * Math.random() - 1; //y速度 points[i] = {x, y, xa, ya}; } draw();
??看下效果,丑陋,和人家的不一樣,很生硬。因?yàn)檫B線不是突然出現(xiàn)突然消失的,點(diǎn)和點(diǎn)之間的連線是漸漸的出現(xiàn),然后漸漸消失的。給連線添加動(dòng)態(tài)的屬性,用點(diǎn)和點(diǎn)的之間的距離來計(jì)算連線的粗細(xì)、透明度,在兩點(diǎn)距離比較遠(yuǎn)的時(shí)候線會(huì)變淡,這樣看起來就舒服多了。
for(i = index + 1; i < points.length; i++) { pi = points[i]; x_dist = p.x - pi.x; y_dist = p.y - pi.y; dist = x_dist * x_dist + y_dist * y_dist; //根據(jù)兩點(diǎn)距離得到一個(gè)參數(shù)w w = (mix - dist) / mix; //判斷點(diǎn)之間的距離是否小于極限距離 if(dist < mix) { ctx.beginPath(); //根據(jù)參數(shù)w設(shè)置連線寬度和透明度 ctx.lineWidth = w / 2; ctx.strokeStyle = `rgba(110,110,110,${w + 0.2})`; ctx.moveTo(p.x, p.y); ctx.lineTo(pi.x, pi.y); ctx.stroke(); } }添加鼠標(biāo)事件
??先是加入對(duì)鼠標(biāo)的響應(yīng)。在鼠標(biāo)進(jìn)入瀏覽器時(shí)添加鼠標(biāo)這個(gè)點(diǎn),否則移除。
window.onmousemove = e => { e = e || window.event; current_point.x = e.clientX; current_point.y = e.clientY; }; window.onmouseout = () => { current_point.x = null; current_point.y = null; }; //將鼠標(biāo)的點(diǎn)添加至點(diǎn)集合中 all_points = [...random_points,current_point];
??要實(shí)現(xiàn)一個(gè)鼠標(biāo)吸附粒子的效果,思路就是粒子和鼠標(biāo)的距離在一定范圍內(nèi)時(shí),給粒子添加一個(gè)向著鼠標(biāo)的速度,結(jié)果就好像是粒子受到鼠標(biāo)的吸附一樣。這是一段鼠標(biāo)吸附效果的核心代碼:
//當(dāng)兩點(diǎn)距離小于極限距離時(shí)產(chǎn)生連線,當(dāng)?shù)诙€(gè)點(diǎn)是鼠標(biāo)所產(chǎn)生點(diǎn)時(shí),粒子如果在范圍內(nèi)就會(huì)產(chǎn)生向鼠標(biāo)點(diǎn)的速度,實(shí)現(xiàn)吸附效果 dist < pi.max && (pi === current_point && dist >= pi.max / 2 && (p.x -= 0.03 * x_dist, p.y -= 0.03 * y_dist));
??加入鼠標(biāo)的點(diǎn)之后再做一些調(diào)整,得到最終的代碼。
其他的粒子特效??還可以利用canvas的getImageData屬性,將圖片粒子化,做成輪播圖,點(diǎn)擊這里預(yù)覽,主要思路是用getImageData取到圖片像素點(diǎn)的信息,每隔一段取一個(gè)樣本,以這個(gè)樣本繪制粒子,繪制出類似于馬賽克一樣的圖片,然后給粒子加上運(yùn)動(dòng)的效果就可以了,這里是具體的代碼實(shí)現(xiàn)。
這篇博客到這就結(jié)束了,這是我的github,歡迎來訪,歡迎star。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/92227.html
摘要:模擬飛機(jī)航班線路動(dòng)畫一款基于的飛機(jī)航班線路模擬動(dòng)畫,它模擬了許多航班在不同目的地的起飛降落數(shù)量。跳動(dòng)加載動(dòng)畫可調(diào)節(jié)參數(shù)這是一款基于的跳動(dòng)加載動(dòng)畫,它的另一個(gè)特點(diǎn)是可以動(dòng)態(tài)調(diào)節(jié)動(dòng)畫參數(shù)。 showImg(https://segmentfault.com/img/bVblze6?w=900&h=383); HTML5 動(dòng)畫在Canvas 上得到了充分的發(fā)揮,我們 VIP 視頻也分享過很多相...
摘要:一開篇哈哈哈,感謝標(biāo)題黨的蒞臨雖然標(biāo)題有點(diǎn)夸張的感覺,但實(shí)際上,插件庫(kù)確實(shí)是簡(jiǎn)潔,高效,輕量級(jí),酷炫酷炫的咯。當(dāng)然,配置不同的參數(shù)值,或許可以得到挺多不同的特效呢上面已經(jīng)演示過標(biāo)配的粒子無序運(yùn)動(dòng)啦,下面演示后面兩種。 一:開篇 哈哈哈,感謝標(biāo)題黨的蒞臨~ 雖然標(biāo)題有點(diǎn)夸張的感覺,但實(shí)際上,插件庫(kù)確實(shí)是簡(jiǎn)潔,高效,輕量級(jí),酷炫酷炫的咯。廢話不多說,先來看個(gè)標(biāo)配例子吧: http://co...
摘要:我們一貫的理念我們我笑哭一貫的理念是信仰和。第一點(diǎn)視差粒子幾行代碼為了看起來更簡(jiǎn)潔,定義視差粒子層數(shù)的屬性就省略了,因?yàn)楸旧硭褪菍樱餐玫?。演示四層,為了讓大家能更了解屬性的使用方法。又高大上,又可以緩解加載的等待心情。 JParticles 2.0 發(fā)布,打造炫酷的粒子特效。不好意思哈,在這么繁花似錦的世界里,標(biāo)題不得不取得吸引眼球一點(diǎn)哈,不然...還是不啰嗦了,我們進(jìn)入正題吧s...
閱讀 783·2021-11-16 11:44
閱讀 3635·2019-08-26 12:13
閱讀 3289·2019-08-26 10:46
閱讀 2415·2019-08-23 12:37
閱讀 1258·2019-08-22 18:30
閱讀 2596·2019-08-22 17:30
閱讀 1902·2019-08-22 17:26
閱讀 2351·2019-08-22 16:20