PDA

Просмотр полной версии : Вращение объекта по центру


KiL33
14.01.2016, 10:41
В примере, если зажать мышь и потянуть, создается прямоугольная форма, при нажатии на кнопку, форма делает поворот. Вращается она из точки 0,0. Нужно, чтобы форма вращалась по центру. А в идеале пивот вращения может находиться в произвольном месте.

test.swf

import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.text.TextField;
import com.greensock.TweenMax;

stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
var obj:Sprite;

var btn:Sprite = simpleButton();
addChild(btn);
btn.addEventListener(MouseEvent.CLICK, initRotate);
btn.x = (stage.stageWidth/2) - (btn.width/2);
btn.y = 200;

function initRotate(e:MouseEvent):void {

if(obj != null) TweenMax.to(obj, 1, {rotation:90});
}

function onDown(e:MouseEvent):void {
if(e.target is Sprite) return;

obj = new Sprite();
addChild(obj)
obj.x = mouseX;
obj.y = mouseY;

stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);

}


function onMove(e:MouseEvent):void {

obj.graphics.clear();
obj.graphics.beginFill(0x0);
obj.graphics.drawRect(0, 0, obj.mouseX, obj.mouseY);

}

function onUp(e:MouseEvent):void {

stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);

}


function simpleButton():Sprite {

var sp:Sprite = new Sprite();
sp.buttonMode = true;
sp.graphics.beginFill(0xCCCCCC);
sp.graphics.drawRect(0,0,100,20);
sp.graphics.endFill();
var txt:TextField = new TextField();
sp.addChild(txt);
txt.mouseEnabled = false;
txt.text = "ROTATE";
txt.autoSize = "left"
txt.x = (sp.width/2) - (txt.width/2);
return sp;
}

illuzor
14.01.2016, 11:03
Нужно положить объект в контейнер и сдвинуть координаты на минус половину длины и ширины.
Вращать контейнер.

KiL33
14.01.2016, 13:38
Т.е. при отпускании мыши сдвигать созданный объект, который внутри контейнера?
Тогда приходится такой мазохизм делать

obj.x = -obj.width/2
obj.y = -obj.height/2

cont.x = cont.x+(obj.width/2);
cont.y = cont.y+(obj.height/2);

Чтобы при сдвиге объекта он не смещался, приходится в обратную сторону смещать сам контейнер. Как то не очень. Может я не так понял?

illuzor
14.01.2016, 13:52
Всё так.
Ещё вариант - задействовать матрицу (http://help.adobe.com/ru_RU/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html)

Wolsh
14.01.2016, 13:59
http://flasher.ru/forum/showpost.php?p=1063241&postcount=18

alatar
14.01.2016, 15:10
http://www.flasher.ru/forum/blog.php?b=704

KiL33
14.01.2016, 17:33
alatar, круто. Но у меня вся анимация c использованием твинов, как в таком случае использовать подход с матрицей, не знаю.

alatar
14.01.2016, 17:54
твинеру всё равно что анимировать вы можете передать ему любую функцию, которая будет принимать "анимируемое" значение.

KiL33
15.01.2016, 09:00
Так то оно так.
Не могу понять, как применить ваш метод.

Я делаю

var m:Matrix = mc.transform.matrix;
var mtx:Matrix = rotateAroundTo(m, new Point(координаты пивота), new Point(координаты объекта));

TweenMax.to(mc, 1, {x:mtx.tx, y:mtx.ty, rotation:90});

Не?)

Объект улетает в сторону.

alatar
17.01.2016, 13:39
Координаты, передаваемые в функцию должены быть в локальных координатах объекта, который необходимо повернуть. Углы, если используются, должны быть в радианах.
А дальше, например так.
TweenPlugin.activate([TransformMatrixPlugin]);
...
var targetMatrix:Matrix = rotateAroundTo(mc.transform.matrix, mc.globalToLocal(pivot), mc.globalToLocal(координаты куда необходимо повернуться))ж

TweenMax.to(mc, 1, {transformMatrix:targetMatrix})

KiL33
17.01.2016, 14:31
Во оно как, спасибо!

Добавлено через 27 часов 31 минуту
alatar, можно еще вопрос. Теперь по scale из вашего блога) Допустим есть форма квадрата, если я ее делаю шире, а потом поворачиваю на 90 гр. то ширина становится высотой. Как то это странно. Ведь я меняю не width а scale. Есть какие-нибудь варианты решения?

alatar
18.01.2016, 18:34
with и height вычмсляемые свойства. По-сути они показывают размеры квадрата описанного вокруг DisplayObject и эквивалентны значениям возвращаемым getBounds() в родительской системе координат.

"Реальные" значения ширины и высоты (как если бы объект не был повернут) можно вычислить, если взять getBounds() в локальных координатах объекта и умножить полученные width и height на scaleX и scaleY, соответственно.

А зачем вам это? Мне в голову приходит не так много случаев, когда это дейтсвительно требуется.

KiL33
20.01.2016, 10:01
По вопросу выше, я немного ошибся, с этим все отлично.

Но вот интересно, почему при повороте scaleAround объект начинает уменьшаться?
var targetMatrix:Matrix = rotateAround(symbol.transform.matrix, symbol.globalToLocal(new Point(pivot.x, pivot.y)), degToRad(180));
TweenMax.to(symbol , 1, { transformMatrix:targetMatrix } )
private function degToRad(deg:Number):Number{
return deg/180*Math.PI;
}
Transform.swf
И вот еще, мне нужно чтобы объект, по мимо изменении размеров, одновременно мог делать разворот. По одиночке я могу это использовать в твине, а совместно, это возможно?

alatar
20.01.2016, 17:37
Но вот интересно, почему при повороте scaleAround объект начинает уменьшаться?
Видимо особенности интерполяции матриц в TweenMax, для корректной работы не хватает промежуточных значений.
И вот еще, мне нужно чтобы объект, по мимо изменении размеров, одновременно мог делать разворот. По одиночке я могу это использовать в твине, а совместно, это возможно?
Возможно. Необходимо передать матрицу сначала в scaleAround, потом, полученную матрицу в rotateAroundTo

P.S. Но вообще-то в TweenMax есть готовый плагин TransformAroundPointPlugin (http://greensock.com/asdocs/com/greensock/plugins/TransformAroundPointPlugin.html) который делает то, что вы хотите.

KiL33
21.01.2016, 05:26
TransformAroundPointPlugin

Да, это то что надо, спасибо!