Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Flex (http://www.flasher.ru/forum/forumdisplay.php?f=84)
-   -   Вращение изображения вокруг центра ViewPort (http://www.flasher.ru/forum/showthread.php?t=206131)

Sonet 14.01.2014 15:44

Вращение изображения вокруг центра ViewPort
 
Ситуация такова: есть изображение, которое лежит внутри контейнера фиксированного размера, оно может быть как больше так и меньше контейнера; у контейнра установлено свойство clipAndEnableScrolling, поэтому все, что за пределами контейнера невидимо. Надо уметь вращать изображение вокруг точки, которая является центром видимой зоны.

Код AS3:

                public static function rotateImageAroundCenterOfViewPort(image:Image, value:Number):void
                {
                        var bounds:Rectangle = image.getBounds(image.parent);
                        // Calculate rotation and shifts
                        var angle:Number = value - image.rotation;
                        var radians:Number = angle * (Math.PI / 180.0);
                        var shiftByX:Number = image.parent.width / 2 - bounds.x;
                        var shiftByY:Number = image.parent.height / 2 - bounds.y;
                        // Perform rotation
                        var matrix:Matrix = new Matrix();
                        matrix.translate(-shiftByX, -shiftByY);
                        matrix.rotate(radians);
                        matrix.translate(+shiftByX, +shiftByY);
                        matrix.concat(image.transform.matrix);
                        image.transform.matrix = matrix;
                }

Данная функция работает правильно только 1 раз (шаг вращения 90 градусов в любую сторону) и почему-то частенько не работает, если изображение имеет сдвиг или скейл. Что надо поменять, чтобы она работала всегда?

Akopalipsis 14.01.2014 15:55

Попробуйте вот так, point это точка во круг которой крутится объект.
Если работать не будет, хотя вроде должно, то на форуме много тем, Вы напишите если что, я попробую найти..
Аааа, я Вас вспомнил:) я тоже сейчас делаю трансформацию и мне кажется, что подход предложенный мной, может не подойти.
Код AS3:

private static var DEG_TO_RAD:Number = 3.1415926535897932 / 180;
public static function rotationPointMatrix(target:DisplayObject, angle:Number, point:Point = null):void
{
        var matrix:Matrix = target.transform.matrix;
        matrix.translate( -point.x, -point.y);
        matrix.rotate( -target.rotation * DEG_TO_RAD);
        matrix.rotate(angle * DEG_TO_RAD);
        matrix.translate(point.x, point.y);
        target.transform.matrix = matrix;
}


Sonet 14.01.2014 16:21

Пока не пробовал, но очень походе на мой способ. Мне кажется, что всю дело в:
Код AS3:

matrix.translate(+shiftByX, +shiftByY);

Т.к. изображение к тому моменту уже как бы повернуто, то смешения должны задаваться относительно нового угла вращения, а не старого.

Isfet 14.01.2014 16:53

помещайте изображение в контейнер в координаты

Код AS3:

 img.x = -img.width*0.5;
 img.y = -img.height*0.5;

и вращайте сам контейнер

Sonet 14.01.2014 17:11

Во-первых, мне надо вращать изображение не вокруг его центра (как это сделать я знаю), а вокруг центра контейнера, в котором оно находится.
Во-вторых, я могу двигать изображение с помощью мыши, так что фиксировать его позицию никак нельзя.

Akopalipsis 14.01.2014 17:28

Способ с -х-у может подойти, но обяжет все расчёты делать с минусами и не позволит вращать во круг произвольно взятой точки, что обязательно должно присутствовать в трансформе. я как сделаю, то покужу в Вашей теме, что у меня получилось, но пока я застрял на неопределённое время с рамкой, как в FS.

Sonet 14.01.2014 18:04

Код AS3:

public static function rotateImageAroundCenterOfViewPort(image:Image, value:int):void
                {
                        trace("rotation Begin: x ", image.x, " y: ", image.y);
                        var bounds:Rectangle = image.getBounds(image.parent);
                        trace("rotation Begin: bounds.x ", bounds.x, " bounds.y: ", bounds.y);
                        // Calculate rotation and shifts
                        var angle:Number = value - Math.round(image.rotation);
                        var radians:Number = angle * (Math.PI / 180.0);
                        var shiftByX:Number;
                        var shiftByY:Number;
                        // Perform rotation
                        switch(Math.round(image.rotation) / 90 % 4)
                        {
                                case 0:
                                {
                                        shiftByX = image.parent.width / 2 - bounds.x;
                                        shiftByY = image.parent.height / 2 - bounds.y;
                                        break;
                                };
                                case 1:
                                {
                                        shiftByX = image.parent.height / 2 - bounds.y;
                                        shiftByY = bounds.width - (image.parent.width / 2 - bounds.x);
                                        break;
                                };
                                case -2:
                                case 2:
                                {
                                        shiftByX = bounds.width - (image.parent.width / 2 - bounds.x);
                                        shiftByY = bounds.height - (image.parent.height / 2 - bounds.y);
                                        break;
                                };
                                case -1:
                                {
                                        shiftByX = bounds.height - (image.parent.height / 2 - bounds.y);
                                        shiftByY = image.parent.width / 2 - bounds.x;
                                        break;
                                };
                                default:
                                {
                                        break;
                                }
                        }
                        var matrix:Matrix = new Matrix();
                        matrix.translate(-shiftByX, -shiftByY);
                        matrix.rotate(radians);
                        matrix.translate(+shiftByX, +shiftByY);
                        matrix.concat(image.transform.matrix);
                        image.transform.matrix = matrix;
                        trace("rotation End: x ", image.x, " y: ", image.y);
                        trace("rotation: xShift ", shiftByX, " yShift: ", shiftByY);
                }

Немного поизучал тему. Выяснил на практике, что смещение надо задавать от текущего положения top-left точки. А нахождение этой точки в свою очередь связано с углом поворота. Но вот незадача: в image.rotation накапливается погрешность, из-за чего через некоторое число поворотов метод начинает сбоить и появляется лишний угол поворота.

Akopalipsis 14.01.2014 18:19

Цитата:

в image.rotation накапливается погрешность, из-за чего через некоторое число поворотов метод начинает сбоить и появляется лишний угол поворота
Есть такое, но почему вы мой код не используете, там нет погрешностей.

Добавлено через 21 минуту
И погрешности не только в rotation накапливаются, это касается и x,y и может ещё чего.

Sonet 14.01.2014 20:38

Потому что, как и мой первый вариант, он вращает правильно всего 1 раз.
Код AS3:

                public static function rotateImageAroundCenterOfViewPort(image:Image, value:int):void
                {
                        var bounds:Rectangle = image.getBounds(image.parent);
                        trace("rotation Begin: bounds.x ", bounds.x, " bounds.y: ", bounds.y);
                        // Calculate rotation and shifts
                        var shiftByX:Number;
                        var shiftByY:Number;
                        // Perform rotation
                                        shiftByX = image.parent.width / 2 - bounds.x;
                                        shiftByY = image.parent.height / 2 - bounds.y;
                        var matrix:Matrix = image.transform.matrix;
                        matrix.translate( -shiftByX, -shiftByY);
                        matrix.rotate( -image.rotation * DEG_TO_RAD);
                        matrix.rotate(value * DEG_TO_RAD);
                        matrix.translate(shiftByX, shiftByY);
                        image.transform.matrix = matrix;
                }

Ыот во что он превратился у меня. Проблема в неверном вычислении точки поворота (т.е. с точки зрения смотрящего на экран - она верная, с точки зрения компонента - нет). Эту проблему я решил выше "свитчем", но возникла новая - с погрешностью.

Akopalipsis 14.01.2014 21:14

Sonet конечно я могу ошибаться, но я столько уже экспериментировал с трансформацией, что могу сказать - в коде нет ошибок. Вы можете просто включить его на EF и смотреть, как он крутится и крутится и не сбивается, даже если угол подавать вот 0,0000545454545 такими значениями.
Ошибка может крыться в том, что я пока тоже не делал, а именно, расчёт угла в зависимости от курсора.
Хотя сложного вроде не чего в этом нет.

Sonet 14.01.2014 22:14

Ну не знаю. Мне надо вращать относительно видимой области. Наверное я не понимаю, как правильно вычислить эту точку (хотя скейлинг, без помощи матрицы, сделал).

Если не трудно, можете сделать пример, где есть изображение 200*200 внутри контейнера 100*100 с clipAndEnableScrolling = true. И чтобы оно вот так по таймеру вращалось вокруг центра видимой области.

dimarik 14.01.2014 22:29

Цитата:

Сообщение от Sonet (Сообщение 1157215)
Во-первых, мне надо вращать изображение не вокруг его центра (как это сделать я знаю), а вокруг центра контейнера, в котором оно находится.
Во-вторых, я могу двигать изображение с помощью мыши, так что фиксировать его позицию никак нельзя.

Вращение контейнера, содержащего изображение, относительно произвольной точки по-прежнему не подходит?

И, судя по clipAndEnableScrolling тема переезжает во флекс.

Sonet 14.01.2014 22:46

Цитата:

Сообщение от dimarik (Сообщение 1157238)
Вращение контейнера, содержащего изображение, относительно произвольной точки по-прежнему не подходит?

И, судя по clipAndEnableScrolling тема переезжает во флекс.

Крайне не желательно, т.к. потому надо будет вычислять смещения и т.п. С точки хрения пользователя,а не приложения.

Это свойство я использую, и привел в пример только, чтобы пояснить, что контйенер скрывает части изображения, выступающие за его границы. Геометрия от этого не меняется, поэтому я создал тему в более популярном разделе AS 3.0.

Akopalipsis 14.01.2014 23:26

Вложений: 1
Цитата:

Геометрия от этого не меняется, поэтому я создал тему в более популярном разделе AS 3.0.
Тут я тоже согласен, так как ветку flex я вообще не посещаю.
Цитата:

где есть изображение 200*200 внутри контейнера 100*100 с clipAndEnableScrolling = true.
Что это такое я не знаю, но сделал аналог в as3 -( покликайте по сцене )
Код AS3:

package 
{
        import flash.display.Bitmap;
        import flash.display.DisplayObject;
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.geom.Matrix;
        import flash.geom.Point;
        import flash.geom.Rectangle;
 
        public class RotationTest extends Sprite
        {
                [Embed(source = "../../../bin/14-01-2014 21-30-06.jpg")]
                private var Picture:Class;
                private var _viewPort:Sprite;
 
                private var _isScrollRectVisible:Boolean;
                private var _transformContainer:Sprite;
                private var _rect:Rectangle;
                private var _centerTransformConteiner:Point;
 
                public function RotationTest()
                {
                        stage.addEventListener(MouseEvent.MOUSE_DOWN, stage_mouseDownHandler);
 
                        _viewPort = new Sprite();
                        _viewPort.graphics.beginFill(0x2E2E2E);
                        _viewPort.graphics.drawRect(0, 0, 500, 300);
                        _viewPort.x = 50;
                        _viewPort.y = 50;
                        super.addChild(_viewPort);
                        var img:Bitmap = new Picture();
 
                        _rect = new Rectangle(0, 0, 100, 100);
 
                        _transformContainer = new Sprite();
                        _transformContainer.scrollRect = _rect;
                        _transformContainer.x = 100;
                        _transformContainer.y = 100;
                        img.x -= 40;
                        img.y -= 30;
                        _transformContainer.addChild(img);
                        _viewPort.addChild(_transformContainer);
 
                        _isScrollRectVisible = true;
 
                        _centerTransformConteiner = new Point(_transformContainer.x + _rect.width * 0.5, _transformContainer.y + _rect.height * 0.5);
                        this.drawPoint(_centerTransformConteiner);
 
                        var frame:Shape = new Shape();
                        frame.graphics.lineStyle(1, 0xFFFFFF);
                        frame.graphics.drawRect(0, 0, _rect.width, _rect.height);
                        frame.graphics.endFill();
                        frame.x = _transformContainer.x;
                        frame.y = _transformContainer.y;
                        _viewPort.addChild(frame);
 
                        stage.addEventListener(Event.ENTER_FRAME, stage_enterFrameHandler);
                }
                private var _angle:Number = 0;
                private function stage_enterFrameHandler(event:Event):void
                {
                        this.rotationPointMatrix(_transformContainer, (_angle++), _centerTransformConteiner);
                }
                private var DEG_TO_RAD:Number = 3.1415926535897932 / 180;
                public function rotationPointMatrix(target:DisplayObject, angle:Number, point:Point = null):void
                {
                        var matrix:Matrix = target.transform.matrix;
                        matrix.translate( -point.x, -point.y);
                        matrix.rotate( -target.rotation * DEG_TO_RAD);
                        matrix.rotate(angle * DEG_TO_RAD);
                        matrix.translate(point.x, point.y);
                        target.transform.matrix = matrix;
                }
                private function stage_mouseDownHandler(event:MouseEvent):void
                {
                        if (_isScrollRectVisible)
                        {
                                _transformContainer.scrollRect = null;
                                _isScrollRectVisible = false;
                        }else
                        {
                                _transformContainer.scrollRect = _rect;
                                _isScrollRectVisible = true;
                        }
                }
                private function drawPoint(point:Point):void
                {
                        var circle:Shape = new Shape();
                        circle.graphics.beginFill(0xFF0006);
                        circle.graphics.drawCircle(0, 0, 2);
                        circle.graphics.endFill();
                        circle.x = point.x;
                        circle.y = point.y;
                        _viewPort.addChild(circle);
                }
 
        }
 
}

scrollRect.swf   (38.8 Кб)

Sonet 15.01.2014 13:09

Вложений: 1
А почему вы вращаете _transformContainer да еще и относительно такой точки ( не понимаю, почему учитываются его x и y координаты)? У меня максимально просто случай: изображение и контейнер с установленным scrollRect. Метод будет просто принимать на вход изображение и угол и поворачивать его относительно центра scrollrect (еще одно несоответствие, т.к. у вас scrollRect тоже поворачивается, а мне надо, чтобы я всегда видел прямоугольник, полностью заполненный изображением, которое в свою очередь может быть повернуто).

Я попытался перенести этот код к себе, но у меня не работает ну никак.

Код AS3:

                private static var DEG_TO_RAD:Number = 3.1415926535897932 / 180;
                public static function rotateImageAroundCenterOfViewPort(image:Image, value:int):void
                {
                        var xShift:Number = image.x + image.parent.width / 2;
                        var yShift:Number = image.y + image.parent.height / 2;
                        var matrix:Matrix = image.transform.matrix;
                        matrix.translate( -image.x, -image.y);
                        matrix.rotate( -image.rotation * DEG_TO_RAD);
                        matrix.rotate(value * DEG_TO_RAD);
                        matrix.translate(xShift, yShift);
                        image.transform.matrix = matrix;
                }

У меня компонент Image лежит внутри контейнера, scrollRect которого - он сам (т.е. прямоугольник (0, 0, w, h)). Вроде по сути все то же самое, но не работает.

Кстати, у вас похоже тоже погрешность накапливается (от этого никуда не деться?) - после нескольких минут вращения изображение прилично так сдвинулось.

Akopalipsis 15.01.2014 14:19

Цитата:

А почему вы вращаете _transformContainer да еще и относительно такой точки
Прочтя -
Цитата:

И чтобы оно вот так по таймеру вращалось вокруг центра видимой области.
мне показалось, что вращение нужно делать, от центра контейнера с картинкой.
Цитата:

еще одно несоответствие, т.к. у вас scrollRect тоже поворачивается, а мне надо, чтобы я всегда видел прямоугольник,
я тоже подумал что Вам именно так и надо, но тут уже сами, передавайте не контейнер, а картинку, не чего не изменится.
Цитата:

Кстати, у вас похоже тоже погрешность накапливается (от этого никуда не деться?)
Уже минут пять крутится и не смещается не на пиксель...

Sonet 15.01.2014 14:22

В случае передачи изображения, какую точку надо передать? Она у вас не в методе считается, и мне не понятно почему именно так (не ясно почему вообще в расчет берутся х и y координаты).

Akopalipsis 15.01.2014 14:46

Координаты у точки должны быть те, во круг которых вы хотите вращать.
Цитата:

Она у вас не в методе считается, и мне не понятно почему именно так
Считать координаты вращающегося объекта в методе вращения - это как пилить сук на котором сидишь, да и зачем их пересчитывать каждый раз, координаты точки ведь не меняются... Но можно и в методе, но тогда нужно усложнять в два раза. Первым делом, нужно вернуть объект в исходное положение и начальные координаты, то есть рассчитать угол в обратную.. и ещё нужно координаты округлять, так как они смещаются.
Вот как можно ещё сделать.

Добавлено через 5 минут
Вы в коде считаете так, что ширина контейнера равна видимой области, но это не так.

Sonet 15.01.2014 14:53

Цитата:

Сообщение от Akopalipsis (Сообщение 1157310)
Координаты у точки должны быть те, во круг которых вы хотите вращать.

Считать координаты вращающегося объекта в методе вращения - это как пилить сук на котором сидишь, да и зачем их пересчитывать каждый раз, координаты точки ведь не меняются... Но можно и в методе, но тогда нужно усложнять в два раза. Первым делом, нужно вернуть объект в исходное положение и начальные координаты, то есть рассчитать угол в обратную.. и ещё нужно координаты округлять, так как они смещаются.
Вот как можно ещё сделать.

Добавлено через 5 минут
Вы в коде считаете так, что ширина контейнера равна видимой области, но это не так.

У меня так.

+ я должен считать точку внутри метода, т.к. я могу двигать изображение и т.о. точка всегда меняется.

Мне не ясно почему вы учитываете х и у координаты вращаемого объекта, ведь точку надо задавать в координатах этого же объекта.

Akopalipsis 15.01.2014 15:23

Цитата:

+ я должен считать точку внутри метода, т.к. я могу двигать изображение и т.о. точка всегда меняется.
Если честно, то я уже не понимаю, что Вы хотите сделать. Если Вы изображение кладете в контейнер и двигаете при этом само изображение, то зачем вообще контейнер...
Но это уже Ваша история и помочь Вам я не могу. Удачи Вам! А я пойду экспериментировать с рамкой :)

Sonet 15.01.2014 16:03

Как бы есть некая область, куда пользователь может загрузить изображение (размеры получаются с сервера) - контейнер. Туда пользователь имеет возможность загрузить изображение. Оно может быть больше или меньше этой области, показываться должно изначально как есть. Соответственно если зображение больше, то лишние края прячутся контейнером. Пользователь может двигать, вращать и скейлить изображение внутри контейнера. Сам контейнер при этом должен оставаться неподвижен и не изменен. Получаается как бы окно, через которое мы видим кусок изображения и все модоификации должны производиться относительно этого окошка: скейлинг и вращение относительно центра окна, перемещение с учетом отступа относительно топлефт угла окна, а не картинки. И я все сделал, кроме поворота. Поворот работать не хочет никак. Лучший вариант валится из-за погрешности.

Akopalipsis 15.01.2014 16:28

Мне кажется я видел такое в ВК, аватара там вроде так же сделана.
И тут опять-таки мне кажется, что Вы немного сбились. Вот загрузил я большое фото и мне нужно его по желанию подогнать под размер. Во первых я должен видеть всё изображение , по верх которого нарисована рамка конечного результата. Вращение и скейл должен проходить относительно центра этой рамки. Как бы я фото не скейлил и не перемещал, то всё это для того, чтобы в итоге я мог подкрутить по отношению центра контейнера. А если сделать вращение да и скейл по отношению не центра рамк конечного результата, то получится не плохая головоломка. Код который показал Вам я, рабочий и если делать как у меня то не чего не смещается. Проблема не в коде а в Вашем видении.
Для примера разберём эту строчку -
Код AS3:

var xShift:Number = image.x + image.parent.width / 2;

Контейнер 100 на 100 в координатах 100 и 100.
Для поиска его центра нужно к координате х прибавить половину его ширины 50.
Но мы поворачиваем его на 45 градусов. Теперь его ширина не 100, а равна его диагонали в состоянии без вращения и координаты смещены. Под углом 90 градусов его координаты будут в 200, 200 и прибавив к ним ещё половину ширины вы центр смещаете воооообще не туда. Вам нужен центр РАМКИ!

Isfet 15.01.2014 16:32

вы отбраковываете нормальные варианты, и пытаетесь все усложнить.

есть главный контейнер- окно (назовем его window), в него в центр помещается другой контейнер(назщовем его innerBox и этот контейнер больше не двигается, или двигается при изменении размеров window ставится опять по центру ), в inner box помещаем изображение в координаты

Код AS3:

 img.x = -img.width *0.5;
      img.y = -img.height *0.5;

далеее картинка перемещается внутри innerBox -а , а если нужно повернуть картинку вокруг точки(а точка - будет центр innerBox ), то вращаем сам innerBox.

Sonet 15.01.2014 17:35

Цитата:

Сообщение от Isfet (Сообщение 1157336)
вы отбраковываете нормальные варианты, и пытаетесь все усложнить.

есть главный контейнер- окно (назовем его window), в него в центр помещается другой контейнер(назщовем его innerBox и этот контейнер больше не двигается, или двигается при изменении размеров window ставится опять по центру ), в inner box помещаем изображение в координаты

Код AS3:

 img.x = -img.width *0.5;
      img.y = -img.height *0.5;

далеее картинка перемещается внутри innerBox -а , а если нужно повернуть картинку вокруг точки(а точка - будет центр innerBox ), то вращаем сам innerBox.

Если innerBox не квадрат, то после его поворота стороны меняются местами. Такого быть не должно.

Akopalipsis
Это у меня очевидно не верная версия. Я пытался подогнать ваш код под свои нужны. Дело в том, что у меня картинка находится внутри статичного контейнера, который сам себе scrollRect. Т.е. скролл рект как бы имеет координаты (0,0) и ширину/высоту такую же, как у контейнера. И эти значения не меняются никогда.

Картинка внутри может иметь отрицательные координаты по этой причине. Поэтому по-хорошему должны быть вот такие сещения:

Код AS3:

var bounds:Rectangle = image.getBounds(image.parent);
shiftByX = image.parent.width / 2 - bounds.x;
shiftByY = image.parent.height / 2 - bounds.y;

Но они не работают. Хотя я проверял - получаются координаты точки вращения (центра моего контейнера, который сам и является рамкой) внутри изображения.

Isfet 15.01.2014 17:54

Цитата:

Сообщение от Sonet (Сообщение 1157359)
стороны меняются местами

можно тут поподробнее?

Sonet 15.01.2014 17:59

Цитата:

Сообщение от Isfet (Сообщение 1157363)
можно тут поподробнее?

Была у вас высоту иннербокса 100 и шририна 200, при повороте на 90 градусов станет наоборот.

Akopalipsis 15.01.2014 17:59

Код AS3:

shiftByX = image.parent.width / 2 - bounds.x;

Парент, это скрол 100 на 100?

Sonet 15.01.2014 18:14

Цитата:

у меня картинка находится внутри статичного контейнера, который сам себе scrollRect.
Т.е. да.
У меня всего 2 объекта: контейнер, который обрезает все, что за его пределами (т.е. его ширина, высота фиксированы, если в него поместить что-то большее, чем он сам, то они не изменятся, лишний контент будет невидим, контент может иметь отрицательные координаты), и картинка внутри него.

Isfet 15.01.2014 18:16

Цитата:

Сообщение от Sonet (Сообщение 1157364)
Была у вас высоту иннербокса 100 и шририна 200, при повороте на 90 градусов станет наоборот.

не берите "getRect" - размеры, внутри себя этот inner-box не изменил размеры, вытаскивайте размеры из него

Sonet 15.01.2014 18:32

К чему эта картинка? Кстати у меня задача немного проще, т.к. шаг поворота 90 градусов.

Akopalipsis 15.01.2014 18:35

Цитата:

К чему эта картинка?
я сделал все что мог, но Вы не как не понимаете :(

Sonet 15.01.2014 19:09

Вложений: 1
Akopalipsis
Я не понимаю, что вы хотите мне сказать. Всем ясно как будут менять координаты. Приклдадываю некоторую иллюстрацию.

Перед поворотом, как я понимаю, мы транслируем точку внутри изображения, которая для пользователя видна, как точка-центр контейнера в topLeft. Потом поворачиваем и транслируем обратно.

Кстати, вы не пробовали мой метод со switch-блоком? Он работает полностью как надо, но накапливает погрешность.

Он статический, на вход нужен компонент, который будем вращать (в моем случае объект класса Image, но подойдет любой) и новый угол вращения (90, 180, 270 и т.п. кратное 90).

Создайте контейнер, установите ему clipRect равный его же размерам и засуньте в него изображение.

Akopalipsis 15.01.2014 20:57

Делаю ещё одну попытку :)
Цитата:

Кстати, вы не пробовали мой метод со switch-блоком? Он работает полностью как надо, но накапливает погрешность.
Вам нужно нарисовать на листочке этот блок-switch и как следует подумать над тем, что Вы делаете.
Мой примитивный код, построен на том, что центр, будь то рект-контейнер или что-то другое, ПОСТОЯНЕН!
Тут я немного объясню то, что Вы должны знать, но все-же..
Есть сцена, у неё точка регистрации находится в topLeft. Вот мы создаём контейнер и присваеваем его точки регистрации (300, 300). В этот контейнер кладем картинку в координаты (0,0) и выглядеть это будет так, как буд-то она находится в координатах (300,300), так-как у контейнера уже другая система координат.
Продолжаю, если Вы двигаете картинку ( видимую её часть ) в пространстве, то это не как не должно сказываться на координаты центра контейнера!!!! Вы понимаете? Двигать контейнер или что-то в нем, это не значит, что его собственная система координат меняется! Точка центра как была в координатах (50,50), так она там и будет, даже если Вы сам контейнер за пределы монитора сдвинете!
Продолжаю, Вам нужно, как Вы сами говорите, двигать ОТНОСИТЕЛЬНО ЦЕНТРА КОНТЕЙНЕРА, ширина и высота которого ВСЕГДА ПОСТОЯННА! Так зачем же точку центра искать исходя из-за положения картинки? Центр как был в (50,50) так он там и будет.
Продолжаю, смотрите на свою картинку, видите в topLeft невидимой области находится настоящая точка регистрации картинки. Противоположная часть называется topRight. Вот Вы повернули картинку на 90 градусов, где будет точка регистрации картинки? Там, где в самом начале была точка topRight и то это с условием, что картинка КВАДРАТНАЯ!!! А ширина становиться равной длине!
Возьмите и нарисуйте мои слова и свои слова. Когда Вы это поймете, то я скажу что делать дальше.

Sonet 15.01.2014 21:28

Это все я понимаю.

Akopalipsis 15.01.2014 21:48

Расскажите какая у Вас вложенность, что в какой контейнер вставляется, и на сколько градусов Вам нужно крутить и относительно чего. я сделаю так же и покажу.

Sonet 15.01.2014 22:09

У меня 1 контейнер (сцену я не считаю за контейнер, т.к. мне не надо создавать ее вручную). Я задаю ему позицию и размеры, они никогда не меняются. В него я вкладываю изображение, которое может быть как больше, так и меньше, чем контейнер. У контейнера выставлено проперти clipAndEnableScrolling. Как я понимаю это равносильно выставлению проперти scrollRect со значниеми (0, 0, container.width, container.height) - контейнер сам себе scrollRect.

Вращение на величину кратную +-90 градусов. Повернуть надо изображение (внутри контейнера) относительно центра видимой области. В любой момент изображение может быть сдвинуто (просто меняю х и у координаты) или промасштабированно (тоже относительно центра, делаю без матрицы, просто применяю новый scale фактор и смещения по х и у).

Akopalipsis 15.01.2014 22:18

Пока могу сказать только одно, не знаю как у clipAndEnableScrolling, но у scrollRect ширина и высота равняется, так же как и у обычного контейнера, его содержимому.

Sonet 15.01.2014 22:21

Хмм. clipAndEnableScrolling влияет только на видимость контейнера. Т.е. допустим я выставил ширину и высоту контейнера по 100, а картинку вставил 200*200. Если это проперти установлено, то я буду видеть только то, что попало в прямоугольник 100*100 и размеры контейнера не будут увеличены.

У меня вопрос возник: matrix.translate изменяет x и y координаты компонента, или перемещает pivot point на заданные величины? Я почему-то считал, что последнее.

Akopalipsis 15.01.2014 23:10

я пока воздерживаюсь от комментариев, так как сам на данный момент не знаю железного решения.
Без сохранения начальных координат сделать можно, но на столько затратно, что я лучше промолчу..

Sonet 21.01.2014 18:02

Нашел решение без свича. Работает, но накапливает погрешность.

Код AS3:

                public static function rotateImageAroundCenterOfViewPort(image:Image, value:int):void
                {
                        // Calculate rotation and shifts
                        var center:Point = new Point(image.parent.width / 2, image.parent.height / 2);
                        center = image.parent.localToGlobal(center);
                        center = image.globalToLocal(center);
                        var angle:Number = value - image.rotation;
                        var radians:Number = angle * (Math.PI / 180.0);
                        var shiftByX:Number = center.x;
                        var shiftByY:Number = center.y;
                        // Perform rotation
                        var matrix:Matrix = new Matrix();
                        matrix.translate(-shiftByX, -shiftByY);
                        matrix.rotate(radians);
                        matrix.translate(+shiftByX, +shiftByY);
                        matrix.concat(image.transform.matrix);
                        image.transform.matrix = matrix;
                }

Добавлено через 24 часа 16 минут
Финальный вариант, может быть кому-то будет полезен. В конце чуть-чуть хитрим - округляем итоговый угол. На глаз все работает вроде хорошо.

Код AS3:

                public static function rotateImageAroundCenterOfViewPort(image:Image, value:int):void
                {
                        // Calculate rotation and shifts
                        var center:Point = new Point(image.parent.width / 2, image.parent.height / 2);
                        center = image.parent.localToGlobal(center);
                        center = image.globalToLocal(center);
                        var angle:Number = value - image.rotation;
                        var radians:Number = angle * (Math.PI / 180.0);
                        var shiftByX:Number = center.x;
                        var shiftByY:Number = center.y;
                        // Perform rotation
                        var matrix:Matrix = new Matrix();
                        matrix.translate(-shiftByX, -shiftByY);
                        matrix.rotate(radians);
                        matrix.translate(+shiftByX, +shiftByY);
                        matrix.concat(image.transform.matrix);
                        image.transform.matrix = matrix;
                        image.rotation = Math.round(image.rotation);
                }

Первый параметр - компонент Image, который надо повернуть, второй - новый угол вращения (тестировал только с углами, кратными 90 градусов).


Часовой пояс GMT +4, время: 23:57.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.