跳到主要內容

新案上線, 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 服務並不支援。
祝大家學習愉快

轉載請註明出處

奶綠的 github.io Source Code

Android完全入門篇-01 安裝SDK與裝置USBDriver

大家好,我是奶綠茶
筆者以 Windows 系統來介紹安裝
1. 下載 Android SDK
http://developer.android.com/sdk/index.html
有分 32 位元和 64 位元的版本
為了教學方便,筆者將檔案放置在 D:\ 下
壓開後會有
eclipse資料夾:Eclipse程式碼編譯器
sdk:Android 開發用的 SDK
SDK Manager.exe:sdk管理用的軟體


2. 開啟手機的"開發人員選項"
部份手機該選項被隱藏起來了
要開啟的話,點選"關於手機"
接著連點"版本號碼"七次,就會重新開啟該功能
接著再開啟"USB偵錯"功能
接上你的 USB 線後
這樣你的電腦才能透過 USB 線來偵錯手機的資訊
3. 為裝置安裝 adb usb driver
因為各家廠牌的 Driver 都不同也不通用,所以需要自行 Google 找 Driver
可以用"XXX廠牌 型號 adb usb driver"關鍵字來找
例:HTC Newone adb usb driver
接著找到 我的電腦 / 內容


裝置管理員

會看到一個金嘆號未知的裝置, 按右鍵更新驅動程式軟體

選擇"瀏覽電腦上的驅動程式軟體"

完成後就會看到裝置啟動,並出現 XXX Android ADB Interface

4.測試是否連接成功
進入到第一步下載的 sdk 資料夾裡
D:\adt-bundle-windows-x86_64-20131030\sdk
然後在 platform-tools 資料夾上按住 Shift 鍵,然後再按滑鼠右鍵
選擇"在此處開啟命令視窗"
(此功能只有 Win7 之後的版本才支援, XP使用者就要自行輸入 dos 指令進入到資料夾)
輸入 adb devices
如果看到一串數字,並顯示 device 就表示連線成功
5.新增環境變數(選擇性設定)
為了方便的使用 adb 指令
可以為 windows 設定變數
開啟我的電腦 / 內容 / 左邊的"進階系統設定"
點選下方 環境變數

下方系統變數,找到 Path的選項,按下編輯

在變數值欄位的最後方加入
;D:\adt-b…

前端攻城屍自動化教學 1 (入門軟體篇, 使用 prepros)

大家好,我是奶綠茶
寫程式的最高原則,就是要"懶"
"懶"指的是 "雜事交由電腦幫你完成"
你就可以專心在程式面上
比如說:
uglifyjs JS 自動幫你把 JS 壓成一行
自動幫你轉 sass/ scss
程式碼一存檔,html 就自動 reload
如果這些事還要手動處理就真的麻煩了

新手可以直接使用現成的軟體
https://prepros.io/
這是一套永久免費的軟體(如果覺的好用也支持一下作者)
免費版和正式版的功能都一樣,差在免費版三不五時會貼心的提醒你要不要付費

1. 下載軟體, 支援 PC(不支援 XP ) 和 Mac
2. 安裝, 一直下一步下一步下一步
3. 啟動軟體



4. 把你的專案資料夾拉進 prepros

5. 點選你的 js 檔
可以看到有五個選項
Auto Compile:當你存檔時是否要自動編譯,當然是要打勾呀。
SourceMaps:產生 sourcemap 檔,通常會搭配下方的 UglifyJS。
Uglify JS:幫你把 js 壓縮成一行。
Convert ES6 to ES5:將 ES6 的語法自動轉成 ES6。
Mangle Variables:將非全域變數的名字打亂。
筆者通常都是全勾。



6. 點選你的 css 檔
AutoCompile:是否存檔自動編譯
AutoPrefixCSS:自動加入 css3的 -web-kit 等前綴字。
SourceMaps:產生 sourceMap檔。
CompressCSS:將 css 壓縮成一行
Enable Cssnext:這個我還沒認真研究


7. 點選你的 html,接下右鍵
可以看到一個 Live Preview This File
按下後會啟動一個 localhost 的網頁,之後只要有修改 js, css ,都會自動 reload

8. 加掛 Proxy
live reload 預設只能跑 html, 如果想要執行 php 或是 asp.net 的話
可以在設定裡面開啟 Live Preview Custom Server

9. 其他
Prepros 也整合了 FTP ,可以讓你方便的直接上傳檔案

轉載請註明出處
SourceCodeDownload