2009年08月6日
【練習】3D標籤雲實作
看到有些部落格裡開始出現3D造型的標籤雲(3D tag cloud), 感覺滿有趣的, 於是模仿動態做一個, 當作PV3D的練習, 原始檔附於文末。
延伸閱讀:
‧3D標籤雲不再是WordPress獨有 » 樂多也可以
結果:
為了方便下載和使用, 直接寫在fla檔裡
import org.papervision3d.view.BasicView;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.special.BitmapParticleMaterial;
import org.papervision3d.core.geom.Particles;
import org.papervision3d.core.geom.renderables.Particle;
import org.papervision3d.events.InteractiveScene3DEvent;
var scale:Number = 5; // 字的縮放
var radius:Number = 300; // 圓半徑
var smoothing:Boolean = true; // 材質平滑化
var minAlpha:Number = 0.3; // 最遠處alpha
var glow:GlowFilter = new GlowFilter (0x003366, 1, 8, 8, 2, BitmapFilterQuality.LOW, true, false); // 移上換色
var i:uint; // 迴圈變數
// tag設定及圓的參數
var tags:Array = ["免費","新聞","Cookie","Toshiba","練習","JavaScript","玩具","人生","作品","TAMAMA","LocalConnection","備忘","MSN大頭","星爺","Loader","XML","創作","轉載","事件","加菲貓","Silverlight","3D","全螢幕"];
var tag_num:uint = tags.length;
var tag_num_sqrt:Number = Math.sqrt (tag_num);
var segW:uint = Math.ceil (tag_num_sqrt) + 1;
var segH:uint = Math.ceil (tag_num_sqrt);
// 3D變數
var bv:BasicView = new BasicView (stage.stageWidth, stage.stageHeight, true, true);
var tagArray:Array = [];
var tagContainer:DisplayObject3D = new DisplayObject3D ("tag_container");
tagContainer.x = -radius * 0.25;
tagContainer.y = radius * 0.25;
var sphere:Sphere = new Sphere (new ColorMaterial(), radius, segW, segH);
// 由sphere取得節點資訊
var vertices_choose:Array = [];
var vertices_num:uint = sphere.geometry.vertices.length;
// 裁員(避免tag量超過點的量)
if (tag_num > vertices_num)
tag_num = tags.length = vertices_num;
// 取一次亂數
for (i = 0; i < tag_num; i++) {
var chooseId:int = sphere.geometry.vertices.length * Math.random();
vertices_choose.push (sphere.geometry.vertices [chooseId]);
sphere.geometry.vertices.splice (chooseId, 1);
}
// 生成3D tag
for (i = 0; i < tag_num; i++) {
// 2D
var txt:TextField = new TextField ();
txt.text = tags[i];
txt.filters = [new BlurFilter(1.1, 1.1)];
var txtW:Number = txt.textWidth + 4;
var txtH:Number = txt.textHeight + 4;
var bitmap:BitmapData = new BitmapData (txtW, txtH, true, 0x01FFFFFF);
bitmap.draw (txt);
// 3D
var material:BitmapParticleMaterial = new BitmapParticleMaterial (bitmap);
material.interactive = true;
material.smooth = smoothing;
var v = vertices_choose[i];
var tag:Particle = new Particle (material, scale, 0, 0, 0); // 使用粒子以使面永遠朝向鏡頭
var tagHolder:Particles = new Particles ("tag_");
tagHolder.addParticle (tag);
tagHolder.x = v.x; // 放到圓的點上
tagHolder.y = v.y;
tagHolder.z = v.z;
tagHolder.extra = {key:tags[i]};
tagHolder.useOwnContainer = true; // 個別化layer以套用效果
tagHolder.autoCalcScreenCoords = true; // 啟動screen計算(求深度)
tagHolder.addEventListener (InteractiveScene3DEvent.OBJECT_OVER, objectOverHandler);
tagHolder.addEventListener (InteractiveScene3DEvent.OBJECT_OUT, objectOutHandler);
tagHolder.addEventListener (InteractiveScene3DEvent.OBJECT_PRESS, objectPressHandler);
tagContainer.addChild (tagHolder);
tagArray.push (tagHolder);
}
function objectOverHandler (e):void {
bv.viewport.buttonMode = true;
e.target.filters = [glow];
}
function objectOutHandler (e):void {
bv.viewport.buttonMode = false;
//e.target.filters = [];
for (var j:uint = 0; j < tag_num; j++) {
tagArray [j].filters = [];
}
}
function objectPressHandler (e):void {
trace (e.target.extra.key);
}
bv.viewport.interactive = true;
bv.scene.addChild (tagContainer);
bv.camera.z = -2 * radius;
bv.camera.zoom = 20;
// 開始render
bv.startRendering ();
addChild (bv);
addEventListener (Event.ENTER_FRAME, enterFrameHandler);
function enterFrameHandler (e):void {
// 隨滑鼠移動
tagContainer.rotationX += (mouseY - stage.stageHeight * 0.5) * 0.02;
tagContainer.rotationY += (mouseX - stage.stageWidth * 0.5) * 0.02;
for (var j:uint = 0; j < tag_num; j++) {
// 依深度設定alpha
tagArray[j].alpha = minAlpha + (1 - minAlpha) * (1 - (tagArray[j].screen.z - radius) / (2 * radius));
}
}
原始檔下載:(需搭配PaperVision3D服用)
引用URL
http://cgi.blog.roodo.com/trackback/9692349
