作為第一個介紹的實作,實作對象是這個 Gif:
出處是 FB 上的某處,這張圖的微妙在數學
簡諧運動的球,在複製並平均分配到不同角度後,組成的大球也像在規律滾動
實作時一步步的想法:
Step1. 畫出線段與球:
**Step2. 讓球動:**由於不需要複雜的運動,直接寫在 app.ticker 的呼叫裡就好
**Step3. 複製線段與球:**依據設定,將線段與球等分複製到不同角度
**Step4. 調整運動的參數:**不同的線段裡的球,簡諧運動的參數不太相同
Step5. 加入調整介面: Gif 裡的球會自動增加.我的實作則是使用 dat.GUI 來手動調整球與線段的數量
Step1. 畫出線段與球:
// 初始化一個 800 x 600 大小的 PIXI.Application
var app = new PIXI.Application(800, 600, {backgroundColor : 0xEEEEEE});
document.body.appendChild(app.view);
// 本例子適合把 stage 放在畫面正中間
app.stage.x = app.renderer.width * 0.5;
app.stage.y = app.renderer.height * 0.5;
// 建立容器
var objContainer = new PIXI.Container();
app.stage.addChild(objContainer);
// 畫球
var ball = new PIXI.Graphics();
ball.beginFill(0x000000, .3);
ball.drawCircle(0, 0, 10);
ball.endFill();
// 畫線
var objLine = new PIXI.Graphics();
objLine.lineStyle ( 1, 0x000000 , 0.3);
objLine.moveTo(-400, 0);
objLine.lineTo(400, 0);
objContainer.addChild(ball);
objContainer.addChild(objLine);
Step2. 讓球動:
var tk = 0;
app.ticker.add(function(delta) {
tk ++;
if(tk == 360) { tk = 0; };
//讓球做簡諧運動
ball.x = Math.sin(tk / (180 / Math.PI)) * (800 * 0.5);
});
由於 Math.sin 會回傳 -1~1,很適合用做簡諧運動的公式
800 是 PIXI.Application
的寬
800 * 0.5 是球會運動到左右邊界,也就是 -400 ~ 400
之間
Step3. 複製線段與球:
將線段與球平均複製與旋轉到各個角度 (此時球還是同進同出)
var objCount = 9; // 會複製九段線與球
for(var i=1; i<objCount +1; i++){
this["objContainer"+i] = new PIXI.Container();
// … 畫出球與線段的部分與前面相同
this["objContainer"+i].rotation = (360 / objCount) * (i-1) * (Math.PI / 180);
stage.addChild(this["objContainer"+i]);
}
角度轉弧度 的方法可能會比較不習慣
假設要轉90度,寫法是:
90 * (Math.PI / 180);
Step4. 調整運動的參數
不同線段裡的球,簡諧運動的參數不太相同
var tk = 0;
app.ticker.add(function(delta) {
tk ++;
if(tk == 360) { tk = 0; };
for(var i=1; i < objCount + 1; i++){
app.stage.children[i].children[1].x= 800 * Math.sin(( tk + (360 / objCount) * i ) / (180 / Math.PI)) * 0.5;
}
});
這段是數學,由於這個例子的簡諧運動公式是 Math.sin(tk / (180 / Math.PI)) * (800 * 0.5);
而 tk 會隨著時間遞增並取 / 360 後的餘數;
以三組線段與球
的例子來說,結果會是:
Math.sin(tk + 0
/ (180 / Math.PI)) * (800 * 0.5);
Math.sin(tk + 120
/ (180 / Math.PI)) * (800 * 0.5);
Math.sin(tk + 240
/ (180 / Math.PI)) * (800 * 0.5);
歸納起來就是 Math.sin(( tk + (360 / objCount) * i
) / (180 / Math.PI)) 了
Step5. 加入調整介面:
Step5-1. 頁面上匯入 dat.gui.js:<script src='js/libs/dat.gui.min.js'></script>
Step5-2. 頁面裡的程式碼:
var gui = new dat.GUI();
var effectController = {
objCount: objCount
};
// 滑動的 controller,拖動範圍為 3~15,間隔為1
gui.add( effectController, "objCount", 3, 15, 1 ).onChange( countChange );
function countChange(){ // 拖動時會執行的程式
rebuildObjs();
};
function rebuildObjs(){
... //把頁面上的元件都清掉,並重新複製線段與線
}
gui.add( effectController, "objCount", 3
, 15
, 1
).onChange( countChange
);
controller 對應到 effectController 裡的 objCount 物件,最小值 3
,最大值 15
,每次拖動的間隔為 1
;拖動結果為 3, 4, 5, 6… 15
當 controller 有變動時呼叫 countChange
方法
將 dat.GUI 實體 New 出來後,加入 controller 並設定事件即可
不用調整 HTML,也不用寫CSS
因為是實做的第一篇,不太容易拿捏要講的內容,
示範的程式碼並不是最終的程式碼.程式碼都放上來會很長並且混亂
最後結果:
http://eia.github.io/pixijs/170317/
省略部分:
resize:
頁面上放上 resize 的事件監聽即可,resize 後需再設定 app.stage 的位置,將畫面置中
app.stage.x = app.renderer.width * 0.5;
app.stage.y = app.renderer.height * 0.5;
手機處理:
2
倍顏色調整:
讓結果與原 Gif 更相近
本文用到的一些方法,如有不太清楚的話可以參考先前的文章: