Трехмерное вдохновение PaperVision3D.
Я не профессиональный флешер - я пока еще только учусь. Кое что на флеше на данный момент у меня уже получается (на мой взгляд) вполне прилично - например 3D на моей титульной страничке. Довольно успешно у меня получаются плоские анимационные вещи во флеш. Я пишу и целые сайты, в основе которых флеш с обвязкой jQuery - например http://rzd.vb-net.com/. Кое-что у меня уже вполне неплохо получается и на Flex - http://rzd.vb-net.com/. Но какие-то вещи у меня пока еще не получаются.
Ниже пример ролика который НЕ ПОЛУЧИЛСЯ. Провозившись целый день и исчерпав все свои идеи - я так и не сумел развернуть текст вверх ногами на двух гранях куба. Все остальное в этом ролике получилось. Тут можно добавить и другую реакцию на клик мышки, и другие кубики с фото и развивать эту прогу в любом направлении - но, увы, текст на двух гранях у меня не разворачивается вверх ногами (без поломки куба).
Похоже никакой стандартный rotate или матричное преобразование тут не проходит. Надо писать свое преобразование copyPixels? Или как сделать разворот текста правильно? Внизу странички есть возможность писать комментарии.
To view this page ensure that Adobe Flash Player version 10.0.0 or greater is installed.
Массив знакомых мне слов я взял из проекта, который лежит у меня на титульной страничке - в реальном проекте он конечно должен вычитываться в онлайне любым из способов, которые я показывал на страничке - Как сделать SOAP/WSDL-вебсервис на ASP.NET/MONO для вызова его из FLEX или на страничке Как сделать простейший Web-handler - формирующий XML или JSON.
Итак, вот код основного рабочего класса :
1: package
2: {
3: import flash.display.Scene;
4: import flash.display.Sprite;
5: import flash.display.Stage;
6: import flash.events.MouseEvent;
7: import flash.events.TimerEvent;
8: import flash.text.Font;
9: import flash.text.TextField;
10: import flash.text.TextFormat;
11: import flash.utils.Timer;
12: import flash.display.DisplayObject;
13: import flash.geom.Matrix;
14: import flash.display.Bitmap;
15: import flash.display.BitmapData;
16:
17: import org.papervision3d.objects.primitives.Plane;
18: import org.papervision3d.materials.BitmapFileMaterial;
19: import org.papervision3d.core.proto.MaterialObject3D;
20: import org.papervision3d.materials.ColorMaterial;
21: import org.papervision3d.materials.MovieMaterial;
22: import org.papervision3d.materials.utils.MaterialsList;
23: import org.papervision3d.objects.primitives.Cube;
24: import org.papervision3d.view.BasicView;
25:
26: import gs.TweenMax;
27: import gs.easing.Quad;
28:
29: public class BannerCube extends BasicView
30: {
31: [Embed(source="C:/WINDOWS/Fonts/Verdana.TTF", fontName="Verdana", fontFamily="Verdana", embedAsCFF="false", mimeType ="application/x-font-truetype")]
32: private var Verdana:Class;
33:
34: static private var Title:Array =[
35: "Visual Studio",
36: "MS SQL",
37: "PosrgreSQL",
38: "MySQL",
39: "SqlServer",
40: "Visual basic",
41: "JavaScript",
42: "ActionScript",
43: "SQL CLR",
44: "VBA",
45: "VB6",
46: "MONO",
47: "ASP NET",
48: "ASP NET MVC",
49: ".NET",
50: "jQuery",
51: "Markup",
52: "WSDL",
53: "WebSite",
54: "WebServer",
55: "Hosting",
56: "Routing",
57: "ZyWall",
58: "Trendnet",
59: "Cisco",
60: "WebServer",
61: "VmWare",
62: "Linux",
63: "VoIP",
64: "Network",
65: "Flex",
66: "Air",
67: "Android",
68: "OpenSuse",
69: "Kiosk",
70: "Terminal",
71: "Freeware",
72: "OpenSource"
73: ]
74:
75: public var _CAMERA_FOCUS:int = 100;
76: public var _CAMERA_ZOOM:int = 10;
77: public var _HEIGTH:int = 480;
78: public var _WIDTH:int = 900;
79: public var _LEFT:int = -60;
80: public var _LEFT_WIDTH:int =850;
81: public var _RIGHT_WIDTH:int = 150;
82: public var _CUBE_SIDE:int = 200;
83: public var _CUBE_Z:int = 200;
84: public var _CUBE_Y:int = 100;
85: public var _BACKGROUND:uint=0x000015;
86: public var _CUBE_SIDE_COLOR:uint=0xffffff;
87: public var _TEXT_SIZE:int=50;
88: public var _TEXT_PADDING:int=20;
89: public var _ROTATE_SPEED:int=3000;
90: public var _STAR_PLANE_WIDTH:int=1720;
91: public var _STAR_PLANE_HEIGTH:int=700;
92: public var _STAR_PLANE_Z:int=700;
93:
94: private var cubes:Array = [];
95: private var targetRotation:Number = 0;
96:
97: static private var colorsArray:Array = [0x76b6f8, 0x4291e1, 0x1f73c8, 0xe77111, 0xe8914c, 0xfad2b2];
98: static private var place:Array = ["front", "back", "bottom", "top", "right","left" ];
99:
100: public function BannerCube(
101: CAMERA_FOCUS:int = 100,
102: CAMERA_ZOOM:int = 11,
103: HEIGTH:int = 480,
104: WIDTH:int = 1200,
105: LEFT:int = -100,
106: LEFT_WIDTH:int =950,
107: RIGHT_WIDTH:int = 200,
108: CUBE_SIDE:int = 180,
109: CUBE_Z:int = 250,
110: CUBE_Y:int = 100,
111: BACKGROUND:uint=0x000015,
112: CUBE_SIDE_COLOR:uint=0xffffff,
113: TEXT_SIZE:int=50,
114: TEXT_PADDING:int=20,
115: ROTATE_SPEED:int=3000,
116: STAR_PLANE_WIDTH:int=1700,
117: STAR_PLANE_HEIGTH:int=1000,
118: STAR_PLANE_Z:int=560,
119: viewportWidth:Number=900,
120: viewportHeight:Number=200,
121: scaleToStage:Boolean=false,
122: interactive:Boolean=true,
123: cameraType:String="Target")
124: {
125: _CAMERA_FOCUS = CAMERA_FOCUS;
126: _CAMERA_ZOOM = CAMERA_ZOOM;
127: _HEIGTH = HEIGTH;
128: _WIDTH = WIDTH;
129: _LEFT = LEFT;
130: _LEFT_WIDTH = LEFT_WIDTH;
131: _RIGHT_WIDTH = RIGHT_WIDTH;
132: _CUBE_SIDE = CUBE_SIDE;
133: _CUBE_Z = CUBE_Z;
134: _CUBE_Y = CUBE_Y;
135: _BACKGROUND = BACKGROUND;
136: _CUBE_SIDE_COLOR = CUBE_SIDE_COLOR;
137: _TEXT_SIZE = TEXT_SIZE;
138: _TEXT_PADDING = TEXT_PADDING;
139: _ROTATE_SPEED = ROTATE_SPEED;
140: _STAR_PLANE_WIDTH = STAR_PLANE_WIDTH;
141: _STAR_PLANE_HEIGTH = STAR_PLANE_HEIGTH;
142: _STAR_PLANE_Z = STAR_PLANE_Z;
143:
144: Font.registerFont(Verdana);
145: super(_WIDTH, _HEIGTH, scaleToStage, interactive, cameraType);
146:
147: var plane:Plane=CreatePlane("stars.jpg");
148: plane.x = 0;
149: plane.y = 0;
150: plane.z = _STAR_PLANE_Z;
151: scene.addChild(plane);
152:
153: opaqueBackground = _BACKGROUND ;
154: camera.focus = _CAMERA_FOCUS;
155: camera.zoom = _CAMERA_ZOOM;
156: camera.ortho = false;
157:
158: var myTimer:Timer = new Timer(_ROTATE_SPEED);
159: myTimer.addEventListener("timer", timerHandler);
160: myTimer.start();
161:
162: var movieMaterial:Array=[];
163:
164: var LeftCube:Cube = CreateCube(_LEFT_WIDTH);
165: LeftCube.x = _LEFT;
166: LeftCube.y = _CUBE_Y;
167: LeftCube.z = _CUBE_Z;
168: LeftCube.replaceMaterialByName(CreateTextSprite(colorsArray[0], colorsArray[1], "0_back_", _LEFT_WIDTH , _CUBE_SIDE, false) , "back" );
169: LeftCube.replaceMaterialByName(CreateTextSprite(colorsArray[2], colorsArray[3], "1_top_", _LEFT_WIDTH , _CUBE_SIDE, false) , "top" );
170:
171: scene.addChild(LeftCube);
172: cubes.push(LeftCube);
173:
174: var RightCube:Cube = CreateCube(_RIGHT_WIDTH);
175: RightCube.x = _LEFT + _LEFT_WIDTH/2 + 3 +_RIGHT_WIDTH/2;
176: RightCube.y = _CUBE_Y;
177: RightCube.z = _CUBE_Z;
178: RightCube.replaceMaterialByName(CreateTextSprite(colorsArray[4], colorsArray[5], "0_back_", _RIGHT_WIDTH , _CUBE_SIDE, false ) , "back" );
179: RightCube.replaceMaterialByName(CreateTextSprite(colorsArray[0], colorsArray[1], "1_top_", _RIGHT_WIDTH , _CUBE_SIDE, false) , "top" );
180:
181: scene.addChild(RightCube);
182: cubes.push(RightCube);
183:
184: startRendering();
185:
186: addEventListener(MouseEvent.CLICK, mouseDownHandler);
187: }
188:
189: public function timerHandler(event:TimerEvent):void {
190: mouseDownHandler(null);
191: }
192:
193: private function mouseDownHandler(event:MouseEvent):void
194: {
195: targetRotation -= 90 % 360;
196: cubes.forEach(cubes_forEachCallback);
197: }
198:
199: private var RotateCount:int=0;
200: private var RotateNumber:int=0;
201: private var DataIndex:int=1;
202:
203: private function cubes_forEachCallback(cube:Cube, index:int, array:Array):void
204: {
205: index++;
206: var time:Number = .3 * index;
207: TweenMax.to(cube, time, {rotationX:targetRotation, ease:Quad.easeInOut});
208:
209: RotateCount++;
210: if (RotateCount>1) {
211: //первые две грани заполены при создании - пропускаем
212: if (RotateCount%2==0){
213: //повернулся второй куб - сдвигаем индекс отображаемых данных
214: if (DataIndex<Title.length-1){
215: DataIndex++;
216: }
217: else{
218: DataIndex=0;
219: }
220: }
221:
222: RotateNumber=RotateCount/2;
223: var width:int = (RotateCount%2==0) ? _RIGHT_WIDTH : _LEFT_WIDTH;
224: var fillColor:int = (RotateCount%2==0) ? colorsArray[RotateNumber%4+1] : colorsArray[RotateNumber%4+2];
225: var textColor:int = (RotateCount%2==0) ? colorsArray[RotateNumber%4+3] : colorsArray[RotateNumber%4+4];
226: switch (RotateNumber%4)
227: {
228: case 0 :
229: cube.replaceMaterialByName(CreateTextSprite(fillColor, textColor, DataIndex.toString()+"_top_"+Title[DataIndex], width , _CUBE_SIDE, false) , "top" );
230: break;
231: case 1 :
232: cube.replaceMaterialByName(CreateTextSprite(fillColor, textColor,DataIndex.toString()+"_front_"+Title[DataIndex], width , _CUBE_SIDE, true) , "front" );
233:
234: //
235: // ??? разворачивать можно здесь - уже после добавления текстуры ???
236: //
237: //var material1:MaterialObject3D = cube.getMaterialByName("front");
238: //var material2:MovieMaterial = cube.getMaterialByName("front") as MovieMaterial;
239: //var sprite1:Sprite = material2.movie as Sprite;
240: //sprite1.rotation=180;
241: //sprite1.rotationX=180;
242: //sprite1.rotationY=180;
243: //sprite1.rotationZ=180;
244:
245: break;
246: case 2 :
247: cube.replaceMaterialByName(CreateTextSprite(fillColor, textColor, DataIndex.toString()+"_bottom_"+Title[DataIndex], width , _CUBE_SIDE, true), "bottom" );
248: break;
249: case 3 :
250: cube.replaceMaterialByName(CreateTextSprite(fillColor, textColor, DataIndex.toString()+"_back_"+Title[DataIndex], width , _CUBE_SIDE, false ), "back" );
251: break;
252: }
253: }
254: }
255:
256: private function CreateCube(width:int):Cube {
257: var materialsList:MaterialsList = new MaterialsList();
258: materialsList.addMaterial(new ColorMaterial(colorsArray[1]), "front");
259: materialsList.addMaterial(new ColorMaterial(colorsArray[2]), "back");
260: materialsList.addMaterial(new ColorMaterial(colorsArray[3]), "bottom");
261: materialsList.addMaterial(new ColorMaterial(colorsArray[4]), "top");
262: materialsList.addMaterial(new ColorMaterial(_CUBE_SIDE_COLOR), "right");
263: materialsList.addMaterial(new ColorMaterial(_CUBE_SIDE_COLOR), "left");
264: return (new Cube(materialsList, width, _CUBE_SIDE, _CUBE_SIDE));
265: }
266:
267: private function CreatePlane(FileName:String):Plane {
268: var material:BitmapFileMaterial = new BitmapFileMaterial(FileName);
269: var plane:Plane = new Plane(material, _STAR_PLANE_WIDTH, _STAR_PLANE_HEIGTH,1,1);
270: return plane;
271: }
272:
273: private function CreateTextSprite(FillColor:uint, TextColor:uint , text:String, x:int, y:int, RotateText:Boolean):MovieMaterial {
274:
275: var sprite1:Sprite = new Sprite();
276: sprite1.graphics.beginFill(FillColor);
277: sprite1.graphics.drawRect(0, 0, x, y);
278: sprite1.graphics.endFill();
279: sprite1.useHandCursor=true;
280:
281: var textField1:TextField = new TextField()
282: textField1.text = text;
283: textField1.y = _CUBE_SIDE/2 - _TEXT_SIZE/2;
284: textField1.x = _TEXT_PADDING;
285: textField1.width = x - _TEXT_PADDING*1.5;
286: textField1.antiAliasType="ADVANCED";
287: //textField1.wordWrap="true";
288:
289: var textFormat1:TextFormat = new TextFormat();
290: textFormat1.color = TextColor;
291: textFormat1.size = _TEXT_SIZE;
292: textFormat1.font = "Verdana";
293: textField1.setTextFormat(textFormat1)
294: textField1.embedFonts="true";
295:
296: if (RotateText){
297:
298: //
299: // ??? разворачивать можно здесь - до превращения спрайта в текстуру ????
300: //
301: //textField1.rotationX=180;
302: //trace(sprite1.transform.matrix);
303: //sprite1.transform.matrix.rotate(10);
304: }
305:
306: sprite1.addChild(textField1)
307:
308: sprite1.mouseChildren = false;
309: //colorBox.addEventListener(MouseEvent.CLICK, onMovieMatClicked);
310:
311: var movieMaterial1:MovieMaterial = new MovieMaterial(sprite1, true, true);
312: movieMaterial1.interactive = true;
313: movieMaterial1.smooth = true;
314:
315: return movieMaterial1;
316: }
317: }
318: }
Для запуска этого класса из флекса нужен еще вот такой враппер:
1: private var bannerCube1:BannerCube;
2:
3: protected function application_start(event:FlexEvent):void
4: {
5: //GetSiteTopic.send();
6: bannerCube1 = CreateBannerCube();
7: stage.addChild(bannerCube1);
8:
9: }
10:
11: protected function Static_clickHandler(event:MouseEvent):void
12: {
13: stage.removeChild(bannerCube1)
14: bannerCube1 = CreateBannerCube();
15: stage.addChild(bannerCube1);
16: }
17:
18: protected function CreateBannerCube():BannerCube
19: {
20: var X:BannerCube = new BannerCube(
21: CAMERA_FOCUS.value,
22: CAMERA_ZOOM.value,
23: HEIGTH.value,
24: WIDTH.value,
25: LEFT.value,
26: LEFT_WIDTH.value,
27: RIGHT_WIDTH.value,
28: CUBE_SIDE.value,
29: CUBE_Z.value,
30: CUBE_Y.value,
31: 0x000015,
32: 0xffffff,
33: TEXT_SIZE.value,
34: TEXT_PADDING.value,
35: 3000,
36: STAR_PLANE_WIDTH.value,
37: STAR_PLANE_HEIGTH.value,
38: STAR_PLANE_Z.value,
39: VIEWPORT_WIDTH.value,
40: VIEWPORT_HEIGTH.value
41: );
42: return X;
43: }
Кроме того, для запуска проекта требуется рисунок и две библиотеки - PaperVision3D и TweenMax.
Для тех кто в танке (и попал на эту страничку случайно) - могу порекомендовать неплохой путеводитель по функционалу PaperVision3D - http://osbo.com/papervision3d/ и посмотреть вообще примеры флеш-приложений вначале странички Анимация и программирование в Flash Professional.
|