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