跳到主要內容

新案上線, Absolut 校園創作競賽

創意絕對.絕對搖滾. 校園創作競賽



在這次的專案,有三個技術點想跟大家分享(如果有更好的方法,歡迎指教討論喔),
1. 自製網頁的ScrollBar
要寫一個ScrollBar不會很難, 但要配合隨視窗縮放的ScrollBar就不是那麼簡單。
在這兒我使用的是bit-101大叔的 minimalcomps 組件裡的VSlider。
該組件的特色,就是有個setSize的函式, 能讓你動態更改組件大小且不會變型。
基本用法如下:
new VSlider(要加入到那個容器裡, x座標, y座標, change偵聽函式);
決解ScrollBar的程式,再補上偵聽stage的Resize事件, 和偵聽stage的MouseWheel事件
完成(誤)
設計師當然不會用這樣的樣計樣式, 好在該特組件在建立元件時, 會執行addChildren函式
我們只要去override後,加入自己的元件,然後把對映的變數重新指過去就可以了
先在flash做好ScrollBar元件,並取好名稱
在這我不使用flash直接compile,因為太慢, 而是使用Embed把該swf裡的元件重新加進來。
再使用FlexSDK來做compile的動作。
自製ScrollBar的程式碼
/**
* @author milkmidi
* @see http://milkmidi.blogspot
* @version 1.0.1
* @date created 2010/03/24/
*/
package milkmidi.tutorials.absolut.cast {  
import com.bit101.components.VSlider; 
import flash.display.*; 
import flash.events.*;  
[Embed(source='../../../../../assets/Assets.swf',symbol="Scroll_mc")]
public class SliderMC extends VSlider{  
public var thumb_mc     :MovieClip;
public var track_mc     :MovieClip;
private var _addWheelListener:Boolean = false;
public function SliderMC(pParent:DisplayObjectContainer = null, pX:int = 0 , pY:int = 0, pChangeHandler:Function = null)  {      
super(pParent, pX, pY, pChangeHandler);     
}     
override protected function addChildren():void {      
_handle = thumb_mc;
_handle.buttonMode = true;
_handle.addEventListener(MouseEvent.MOUSE_DOWN, onDrag);    
}  
private function _mouseWheelHandler(e:MouseEvent):void {   
if(e.delta>0)
value += 15;
else
value -= 15;     
onSlide(e);   
}
override public function get value():Number { return super.value; }  
override public function set value(value:Number):void {   
super.value = value;
onSlide(null);
}  
public function get addWheelListener():Boolean { return _addWheelListener; }  
public function set addWheelListener(value:Boolean):void {
_addWheelListener = value;
if (_addWheelListener)
stage.addEventListener(MouseEvent.MOUSE_WHEEL , _mouseWheelHandler);   
else
stage.removeEventListener(MouseEvent.MOUSE_WHEEL , _mouseWheelHandler);      
}
override protected function drawBack():void {
track_mc.height = height;
}
override protected function drawHandle():void {   
positionHandle();
}  
} 
}
主程式測試碼
/**
* @author milkmidi
* @see http://milkmidi.blogspot
* @version 1.0.1
* @date created 2010/04/07/
*/
package  {  
import com.bit101.components.HBox;
import com.bit101.components.HSlider;
import com.bit101.components.VSlider;
import flash.display.*;  
import flash.events.Event;
import milkmidi.tutorials.absolut.cast.SliderMC;
public class A01SliderMCDemo extends Sprite {    

private var _scroll:SliderMC;
public function A01SliderMCDemo()  {   
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE , init);
}  

private function init(e:Event=null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);   
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE , _resizeHandler);
_scroll = new SliderMC(this, 0, 0, _slidrChangeHandler);
_scroll.addWheelListener = true;
_scroll.setSliderParams(0, 100, 50); 
_resizeHandler(null);   
//以下是測試用的
new VSlider(this, 0, 0, _slidrChangeHandler);
}

private function _resizeHandler(e:Event):void {
_scroll.x = stage.stageWidth - 40;
_scroll.setSize(200, stage.stageHeight);
}

private function _slidrChangeHandler(e:Event):void{
trace(e.currentTarget.value)
}
} 
}
2. 主視覺要隨視窗大小作定位
在這個案子裡,主視覺有二種模式, 一般模式(要完全罝中)
資訊打開模式(配合第一點的ScrollBar數值來作定位)
我想第一般模式很簡單, 直接對stage做Resize偵聽, 然後就完全置中
而第打開模式,其實也不難,反正ScrollBar裡的value預設就是0到100。
當ScollBar value 在0時, 主視覺物件的y軸也在0,
當ScrollBar value 在100時,主視覺物件的y軸就等於 (主視覺物件的高度-場景高*負1)
(keyVisual.height-stage.stageHeight*-1)
好了,公式出來了,剩下的應該不難。
package  {  

public class A02KeyVisualDemo extends A01SliderMCDemo{  

private var _keyVisual:KeyVisual_mc = new KeyVisual_mc();
public function A02KeyVisualDemo()  {   
addChild(_keyVisual);
}  
override protected function _onScrollChange(pValue:int):void {
pValue = 100 - pValue;
//因為VSlider拉到底是0, 跟我們需要的值是相反的, 所以要倒過來
var _rang:int = (_keyVisual.height - stage.stageHeight) * -1;   
_keyVisual.y = _rang * pValue / 100;         
}
} 
}
3. 效能問題
先直接看效能未優化版(僅供demo用, 活動資訊請以正式網址為主)
你可以看到整個網站在進場播放動畫時,是非常lag, 且整個網站的fps非常的低。
二者有非常明顯的差別(如果你的電腦配備超好的話,應該看不出來)
二個版本用的fla檔都是同一個。
先了解一下flash吃效能的幾個點。
flv:影片播放是很吃效能的,不管是外載還是匯入到flash裡,都非常吃效能,特別在大畫面時更明顯。
決解方法:用檔案k數來換, 把影片轉成序列圖檔
序列圖檔:能用jpg當然是最好的,但要有透明度的話,就一定要用PNG
在使用PNG時要特別注意, 假設你的圖片是600x400, 但真正有圖型的大小可能只有300x200, 其他的部份都是透明色塊, 請記得。打散他, 然後把用不到的透明色塊給delete掉, 這樣可以省下很多不必要的運算(經人體實驗是有效的)。
大畫面物件+多物件移動+序列圖檔:
就像這次的案子遇到的問題一樣,設計師做好美美的動畫,做完發現跑起來很lag,本來是想減少動畫量,但就少了一種感覺, 而我使用的方法就是 BitmapData
嘿嘿,想到了嗎
使用 BitmapData 類別,把該動畫所有的影格,事前畫成BitmapData, 在存在Array裡
當要播放動畫時,就去指定的Array裡把BitmapData拿出來。
這樣不管畫面上有多少物件,都視同只有一個BitmapData, 等到動畫播完時,在把Array裡的BitmapData Dispose掉,這樣動畫也順了,效能也有了。
但使用時還是需要注意幾個點:
一開始要把一個MovieClip裡的全部影格畫成BitmapData, 表示一瞬間會消耗大量的CPU,此時使用者的電腦可能會停頓一下,那可不可以改成邊播MovieClip邊畫呢,答案是這樣做的效能沒什麼差
所以我的作法是把整段動畫分階段去畫,一開始可能先畫20個影格,當動畫播到20個影格時,再去畫另外的20個影格
等到動畫全部播完後,再整個Dispose掉。

package milkmidi.display { 
import flash.display.*; 
import flash.events.Event;
import flash.geom.Matrix;
import flash.net.URLRequest;
import flash.utils.clearInterval;
import flash.utils.clearTimeout;
import flash.utils.setTimeout; 
public class BitmapDataSequence extends Sprite {
public static const END_FRAME:String = "endFrame";
private var _target   :MovieClip;
private var _targetWidth :int;
private var _targetHeight :int;  
private var _fps   :uint;
private var _totalFrames :uint;  
private var _bitmap   :Bitmap = new Bitmap();
private var _bmdArray  :Array = [];    
private var _frame   :int = 1;  
private var _inter   :int;
private var _drawMatrix  :Matrix;
private var _sequenceTime :Number;
public function BitmapDataSequence(pTargetMC:MovieClip, pWidth:Number = 320, pHeight:Number = 240, pFps:Number = 30):void {   
_fps = pFps;      
_targetWidth = pWidth;
_targetHeight = pHeight;   
_target = pTargetMC;         
_totalFrames = _target.totalFrames;
addChild(_bitmap);   
}
public function startSequence(pTime:Number = 0 ):void {   
_sequenceTime = pTime;
convert();   
}  
public function prevFrame():void {
_frame--; 
_frame = _frame < 1 ? 1 :_frame;   
showFrameBitmapData(_frame);   
}
public function nextFrame():void {
_frame++; 
_frame = _frame > _totalFrames  ? _totalFrames : _frame;   
showFrameBitmapData(_frame);
}
public function play():void {
showFrameBitmapData(_frame);   
if (_frame == _totalFrames) {    
dispatchEvent(new Event(END_FRAME));
}
_frame %= _totalFrames;      
_frame++;   
_inter = setTimeout(play, 1000 / _fps);      
}
public function stop():void {
clearTimeout(_inter);
}
public function gotoAndStop(pFrame:uint):void {   
stop();
_frame = pFrame;
showFrameBitmapData(_frame);
}
public function gotoAndPlay(pFrame:uint):void { 
stop();
_frame = pFrame;   
play();
}
private function convert():void {    
_target.gotoAndStop(_frame);   
var _mtr:Matrix = new Matrix();       
var _bmp:BitmapData = new BitmapData(_targetWidth, _targetHeight, true, 0x00000000);
_bmp.draw(_target, _drawMatrix);      
_bmdArray.push(_bmp);
_frame++;  
//trace(_frame, _bmdArray.length);
if (_frame > _totalFrames) {
stop();    
_frame = 1;    
showFrameBitmapData(1);
dispatchEvent(new Event(Event.COMPLETE));
return;
}   
if (_sequenceTime == 0)   
convert();
else
setTimeout( convert, _sequenceTime * 1000);
}  

private function showFrameBitmapData(pFrame:uint):void {
_bitmap.bitmapData = _bmdArray[pFrame - 1];    
}
public function get totalFrames():uint { return _totalFrames; }   
public function get currentFrame():uint { return _frame; }

public function get drawMatrix():Matrix { return _drawMatrix; }  
public function set drawMatrix(value:Matrix):void {
_drawMatrix = value;
}
public function destroy():void {
clearInterval(_inter);
for each (var _bmp:BitmapData in _bmdArray) {
_bmp.dispose();
}        
}
}

}
SourceCodeDownload

留言

jerry寫道…
一個字~強~
匿名表示…
http://ecodazoo.com/
請問老師這個是怎麼做的阿?
匿名表示…
dispatchEvent(new Event('END_FRAME'));
?是這樣嗎?
匿名表示…
動畫全部畫完再dispose
這樣畫面就被清掉了
如果要不斷播放
就不dispose嗎
還是不斷play() > dispose();
那個效能較好
匿名表示…
奶綠老師,不好意思..A02KeyVisualDemo這個在我的認知是在寫-視覺顯示區那個元件,但是我不知道怎麼應用這個as..,主場景程式和SliderMC我已經懂了,但是A02KeyVisualDemo程式我懂,但是不知道怎麼應用且 是用在哪?!


不好意思,我很想學奶綠老師分享的這支程式,所以想問清楚~


如果A02KeyVisualDemo是視覺顯示區那個元件的class,那不用embed該元件嗎?!
milkmidi寫道…
A02KeyVisualDemo extends A01SliderMCDemo了,所以SlidrMC的程式已經有就不用再重寫
而那個主要的視覺元件,我是使用swc
你可以看到Assets.swf是有被加入到FlashDevelop專案裡,且是藍色的
所以我在上方new的KeyVisual_mc就是swc裡的元件
milkmidi寫道…
http://ecodazoo.com/
是日本AS大師roxik自已原創的3D Engine
我只知道大概的方法,但沒辦法做到像他這麼順。

dispatchEvent(new Event('END_FRAME'));
這指的是什麼呢??

動畫全部播就就dispose, 是因為動畫就只播過一次就不要,所以最後才把他整個dispose掉
匿名表示…
奶綠老師 不好意思 我還是不太懂 為什麼 A02KeyVisualDemo extends A01SliderMCDemo 之後 A02KeyVisualDemo 的程式裡 就可以使用Asset.swf的元件?

那換句話說 我可以直接讓視覺元件直接去link A02KeyVisualDemo 嗎?!

不好意思..麻煩您了 我是不太懂swc和embed的方式。
milkmidi寫道…
我來說明一下swc和embed的關系好了
swc:是可以包含設覺元件和程式碼的元件
可以把一堆as檔,包裝成一個swc,
你可以想成是把他zip起來。
怎麼產生swc呢, 只要在發佈面版裡, 將swc選項打勾, 發佈後, 就會幫你產生swc檔, 要注意喔, 只有元件庫裡有勾選成類別的才會匯出在swc裡。
怎麼用呢:FlashCS4,Flex,FlashDevelop都可以直接使用swc元件,只有FlashCS3不能。
在我的A02KeyVisualDemo這隻,我有去new一個KeyVisual_mc類別, 這個類別就是憂在Assets.fla裡製作的。
而Embed是將外部的元素匯入到swf檔,有點像是將檔案匯到flash的元件庫裡。
Embed是由Flex來的, 因為Flex沒有元件庫的概念, 所以才有這個語法可以使用
但要注意一下,使用Embed swf檔時,該swf裡的程式碼都會消失喔。
希望這樣對你有幫助
匿名表示…
嗯! 清楚了~ 謝謝奶綠老師!!
我有寫出來了~ 大開心!
匿名表示…
老師 請問_sequenceTime 這變數的功能是?
milkmidi寫道…
設成0的話
會一開始就把全有的影格的BitmapData劃完
如果影格數很長, 此時會非常吃效能,然後整個停住
加這個變數是用來告訴flash幾毫秒要劃一張。
匿名表示…
感謝奶綠大的分享,但有一個小問題我想請教,以下是我的程式碼。
var seq_bg:BitmapDataSequence=new BitmapDataSequence(designers_bg)
seq_bg.startSequence()
然後我原本設定STOP,場景上的影片他自己會開始跑,但是還是會頓,打開工作管理員,效能也沒有差,請問是我使用方法錯誤嗎?

這個網誌中的熱門文章

超好用的無限免費網頁空間,無廣告,無流量限制

大家好,我是奶綠茶 今天來教大家如何申請一個無限免費速度又快的網頁空間 1 首先到  https://github.com/ 申請帳號(一直下一步,下一步,下一步) 2 到你的個人頁,切換上方的 tab 到 Repositories, 按下右鍵的 new 3 Repository name 一定要是這樣的格式 username.github.io 我的 github 網址是 github.com/milkmidi 那就要輸入 milkmidi.github.io 選擇 public, 這樣別人才看的到 private 有其他用途, 而且要付費才能使用 完成後按下 Create repository 5 安裝 SourceTree github 並不支援 FTP 或是網頁上傳,一定要透過指令碼 在這我們選用有圖型介面的軟體,方便大家學習 https://www.sourcetreeapp.com/ 下載並安裝 啟動後登入你的 github 帳號 6 clone 你的 github io 專案 右上角有個 Clone or download 點選後 複製 https 連結(不要選到 ssh ) 7 將 https 的連結貼到 SourceTree 8 上傳 html 到本機 github.io 資料夾,放一個 index.html 切換到 SourceTree, 這時會看到 Unstaged files 的欄位 選擇 Stage All 9 git 要求每次的 Commit, 都一定要打說明文字(好習慣) 輸入完成後,按下右邊的 Commit 10 發佈(Push),這樣就完成啦 可以到你的 http://milkmidi.github.io/ 去查看檔案有沒有出來 其他 Commit 可以想像是做一個記錄,你可以很多的 Commit 最後再一次 Push 上去 github 原本是給程式設計師用的版本控管服務 免費版提供無限空間讓你放檔案,但一定要是 public 想要有私有的 Project ,就只能付費 github.io 只能放靜態檔案,php, aspx 服務並不支援。 祝大家學習愉快 轉載請註明出處 奶綠的 gi...

奶綠茶新書上市_密技公怖_程式碼下載

奶綠茶第一本 Flash 書籍上市啦 博客來書籍館 Flash 3D 特效宅急便 - 商業範例隨學隨 把我對 Flash 的研究與熱愛, 全寫在其中 本書的前幾章, 特別安排 ActionScript3.0 的許多範例 好讓你一步步瞭解 as2 和 as3 的差別 再安排製作動畫不可缺少的 Tweener 類別和一些常用的數學動畫公式 最後當然就來到本書的重點 PV3D 啦 從 PV3D 的原理, 基本架構一點一點的介紹 再透過許多實用的範例, 從中瞭解 PV3D 製作的小技巧 有任何書籍相關的問題, 也請不吝指教 感謝一路走來, 幫助過我的前輩們, 邦邦、Ticore、神魂、Maso、Erin 旗標出版社 小編 Bready 米蘭數位所有夥伴 米蘭數位ActionScript Team:Jason,Ash,Mark 本書大鋼: 1.ActionScript3.0概論 分析AS3的概念與語法, 從基本的滑鼠事件、外部載入、氣泡事件介紹起 適合熟悉AS2, 想轉戰AS3的人員。 2.程式碼製作動畫 使用簡單的數學公式, 套用到程式裡, 脫離死版的影格動畫。 3.製作動畫的好夥伴:Tweener 除了套用數學公式外, Tweener類別也能加速我們開發出更多的動畫效果, 不需辛辛苦苦的找公式。 4.自定類別 AS3的精神, 是在於強大的物件導向, 當然也要熟悉類別的寫法與使用。 5.Flash3D - Papervison3D 如果在Flash玩轉3D效果, PV3D是最好學, 最快上手的3D Flash Engine, 從簡單的3D概念, PV3D類別, 事件等。 6 漫天飛舞的Paper3DWorld效果 7 迷你旋轉木馬式秀圖效果 8 最經典! CoverFlow 圖像展示效果 9 天旋地轉 TiltViewer效果 10 FlatWall3D電視牆效果 11 經典旋轉木馬 Carousel3D 秀圖效果 12 光源材質展示與簡易型的方塊彈跳效果 13 載入外部3D模型與動畫 14 超立體旋轉九宮格 Box3DWorld 15 空間感與透明感兼具的 SpaceGallery 16 螺旋式 SpiralCarouse 影像展示 17 Flash10 3D功能 18 Flash效...

奶綠茶photoGalleryV3.5

奶小茶的photoGalleryV3.5原始檔 2007/12/30 更新小Bug,請重新下載 線上Demo: http://milkmidi.com/photogallery/galleryv3.html 1.支援SWFAddress,讓FLASH可以有上一頁下一頁和每張獨立網址的功能 2.圖片路徑圖說經由XML來設定 3.背景依據顯示圖片,自動變化成最接近的顏色 4.非商業用途,歡迎使用並修改(如果覺得我製作的好,也煩請加入我的logo) 5.可結合後端伺服器 00.art 相本集資料夾 com 奶綠茶的Class檔 swfaddress SWFAddress資料夾 swfobject swfobject資料夾 XML galleryV3.fla 原始檔 index.html 主檔html SWFAddress.as SWFaddressEvent.as Source Code Download 解壓密碼:回覆文章,即可看見Password