|
|
|||||
Эффект пластики с отменой
Здравствуйте! Задача: создать эффект пластики с возможностью отмены последнего результата.
Сама реализация эффекта была позаимствована отсюда silin.su/AS3/bitmap/plasticDistort/ Изучив код, вроде понял что к чему, но вот вернуть корректно предыдущее состояние "пластики" не выходит. К примеру: 3 раза взяли и потянули мишкой, потом нажали "отмена" (все отлично происходит), и если опять начинаем "тянуть" картинку, то состояние сетки опять стает как до первого нажатия "отмена" + только что "потянули" (демо версия и исходник в CS5 приложена). Весь код собран в один класс, опишу кратко на что, по моему, стоит обратить внимание: 1. Сохранение текущего слепка в массив истории происходит в ф-ции savePlastic 2. Возврат - в undoPlastic package { import flash.display.*; import flash.events.*; import flash.geom.*; import flash.ui.*; import fl.controls.NumericStepper; import fl.controls.CheckBox; import fl.controls.Button; public class Main extends Sprite { // Компоненты private var _numStepper:NumericStepper; private var _gridCheckBox:CheckBox; private var _btnReset:Button; private var _btnUndo:Button; // private var divX:int = 30; private var divY:int = 40; // private var W:Number = 300; private var H:Number = 400; // private var _canvas:Sprite; private var indices:Vector.<int>; private var uvData:Vector.<Number>; private var verticies:Vector.<Number>; private var nodes:Vector.<Point>; private var _texture:BitmapData; private var anchor:Point = new Point(); private var marker:Point = new Point(); private var _plasticArrHistory:Array; public function Main():void { _plasticArrHistory = new Array(); // картинка _texture = new TestBD(); // Добавляем контейнер _canvas = new Sprite(); addChild(_canvas); // Инициализация компонентов initComponents(); initGrid(); // Отрисовка draw(); // Слушатели _canvas.addEventListener(MouseEvent.MOUSE_DOWN, canvasMouseDown); _canvas.addEventListener(MouseEvent.MOUSE_UP, stageMouseUp); _canvas.addEventListener(MouseEvent.ROLL_OVER, canvasRollOver); _canvas.addEventListener(MouseEvent.ROLL_OUT, canvasRollOut); } /** Инициализация компонентов */ private function initComponents():void { _numStepper = numStepper; _numStepper.addEventListener(Event.CHANGE, update); _gridCheckBox = gridCheckBox; _btnReset = btnReset; _btnReset.addEventListener(MouseEvent.CLICK, btnResetClick); _btnUndo = btnUndo; _btnUndo.addEventListener(MouseEvent.CLICK, btnUndoClick); } private function canvasRollOut(e:MouseEvent):void { Mouse.cursor = MouseCursor.AUTO; } private function canvasRollOver(e:MouseEvent):void { Mouse.cursor = MouseCursor.HAND; } /** Обработчик нажатия миши */ private function canvasMouseDown(e:MouseEvent):void { anchor.x = marker.x = mouseX; anchor.y = marker.y = mouseY; _canvas.addEventListener(MouseEvent.MOUSE_MOVE, canvasMouseMove); } /** Обработчик перемещения миши */ private function canvasMouseMove(e:MouseEvent):void { marker.x = mouseX; marker.y = mouseY; update(); anchor.x = marker.x; anchor.y = marker.y; } /** Обработчик отпускания миши */ private function stageMouseUp(e:MouseEvent):void { _canvas.removeEventListener(MouseEvent.MOUSE_MOVE, canvasMouseMove); // Сохраняем состояние savePlastic(); } /** Сохранение состояния */ public function savePlastic():void { var v:Vector.<Number> = verticies.concat(); var n:Vector.<Point> = nodes.concat(); // Сохраняем состояние в массив _plasticArrHistory.push( {v:v, n:n} ); } /** Шаг назад в пластике */ public function undoPlastic():void { var len:int = _plasticArrHistory.length; // Если нету сохраненных состояний, то ... if (len == 0) return; // Срезаем последнее состояние в истории _plasticArrHistory.length -= 1; // Если сохраненных состояний больше чем 1 if (len != 1) { // Получаем последнее состояние (перед срезом это было предпоследнее) len = _plasticArrHistory.length; var v:Vector.<Number> = _plasticArrHistory[len - 1].v; var n:Vector.<Point> = _plasticArrHistory[len - 1].n; // Пересохраняем значения verticies = v.concat(); nodes = n.concat(); // Отрисовка draw(); resampleGrid(); } else { // Если 1 значение, то просто сброс сетки resetGrid(); } } private function btnResetClick(e:MouseEvent):void { resetGrid(); } private function btnUndoClick(e:MouseEvent):void { undoPlastic(); } private function update(e:Event = null):void { resampleGrid(); draw(); } private function draw():void { _canvas.graphics.clear(); if (_gridCheckBox.selected) { _canvas.graphics.lineStyle(0, 0x80FF80, 0.35); } _canvas.graphics.beginBitmapFill(_texture, null, false, true); _canvas.graphics.drawTriangles(verticies, indices, uvData); _canvas.graphics.endFill(); } private function initGrid():void { uvData = new Vector.<Number>(); verticies = new Vector.<Number>(); indices = new Vector.<int>(); nodes = new Vector.<Point>(); var k:int = 0; for (var i:int = 0; i <= divY; i++) { for (var j:int = 0; j <= divX; j++) { verticies.push(W * j / divX, H * i / divY); uvData.push(j / divX, i / divY); if (i < divY && j < divX) { indices.push(k, k + 1, k + divX + 1, k + 1, k + divX + 2, k + divX + 1); } nodes.push(new Point(W * j / divX, H * i / divY)); k++; } } } private function resampleGrid():void { for (var i:int = 1; i < divY; i++) { for (var j:int = 1; j < divX; j++) { var k:int = i * (divX + 1) + j; var node:Point = nodes[k]; var fX:Number = (anchor.x - node.x < 0) ? ((W - node.x) / (W - anchor.x)) : (node.x / anchor.x); var fY:Number = (anchor.y - node.y < 0) ? ((H - node.y) / (H - anchor.y)) : (node.y / anchor.y); var f:Number = fX * fY; for (var m:int = 1; m < _numStepper.value; m++) { f *= f; } node.x += (marker.x - anchor.x) * f; node.y += (marker.y - anchor.y) * f; verticies[2 * k] = node.x; verticies[2 * k + 1] = node.y; } } } private function resetGrid():void { for (var i:int = 0; i <= divY; i++) { for (var j:int = 0; j <= divX; j++) { var k:int = i * (divX + 1) + j; nodes[k].x = W * j / divX; nodes[k].y = H * i / divY; } } update(); } } } Спасибо! Исходник: flasher.rar Демка: |
Часовой пояс GMT +4, время: 16:06. |
|
« Предыдущая тема | Следующая тема » |
|
|