PDA

Просмотр полной версии : Позиционирование увеличивающегося MovieClip-а


fish_r
27.02.2011, 21:45
Увеличиваю MovieClip размерами больше сцены (окна) приложения. При этом мувик произвольно смещён относительно центра сцены, но важно, чтобы пропорции смещения не изменялись. То есть:

http://www.flasher.ru/forum/attachment.php?attachmentid=26105&stc=1&d=1298827448


Где прямоугольник без заливки - сцена, окно приложения. Желтый прямоугольник - мувик. Точка "А" находится на мувиклипе, в данный момент в центре окна приложения. Важно чтобы при увеличении мувика точка "А" так и оставалась в центре сцены.

Как я это делаю:
Вычисляю смещение левой стороны мувиклипа относительно окна

var leftShoulderX:Number = Math.abs(oldX / (oldWidth - this.stage.stageWidth));
var leftShoulderY:Number = Math.abs(oldY / (oldHeight - this.stage.stageHeight));


где old'ы это соотв. параметры мувика до его масштабирования, а leftShoulder'сы степень смещения относительно сцены.

Позиционирую

_pictMovie.x = (this.stage.stageWidth - _pictMovie.width) * leftShoulderX;
_pictMovie.y = (this.stage.stageHeight - _pictMovie.height) * leftShoulderY;


где _pictMovie.x/y - имя мувика, а leftShouldrX/Y степень смещения относительно центра окна при-
ложения.

Теоретически все выглядит правильно, пересчет в ручную дает погрешность в 1, 2 пиксела на 5000, в данном случае это вполне приемлемо. Но правктически мувик в окне "едет" при увеличении вправо и вниз на 100-200 пикс. Что я делаю не так? Замылил уже мозг, мне надо чтобы кто то свежим взглядом глянул :).

undefined
27.02.2011, 22:06
как раз для таких случаев у DisplayObject есть методы globalToLocal, localToGlobal.
Делается так:
1) Есть мувик с именем mc.
2) Получаем координаты его центра до начала скейла в системе координат его парента:

var p1:Point=new Point(0,0);
p1=mc.localToGlobal(p1);
p1=mc.parent.globalToLocal(p1);

3) Скейлим и снова вычисляем координаты центра:

var p2:Point=new Point(0,0);
p2=mc.localToGlobal(p2);
p2=mc.parent.globalToLocal(p2);

4) Если (p1.x!=p2.x || p1.y!=p2.y) корректируем положение мувика

var delta:Point=new Point(p2.x-p1.x,p2.y-p1.y);
mc.x+=delta.x;
mc.y+=delta.y;

код писал из головы поэтому может потребуется поменять знаки у delta.

UPD: если мувик лежит непосредственно на стейдже, то можно сэкономить и вычислять координаты центра мувика в системе координат стейджа. Тогда не надо дважды вызывать достаточно ресурсоемкую операцию globalToLocal

fish_r
27.02.2011, 23:00
как раз для таких случаев у DisplayObject есть методы globalToLocal, localToGlobal.


Эти методы не для этого.


2) Получаем координаты его центра до начала скейла в системе координат его парента:...


Так вы получаете не координаты его центра, а координаты его левого верхнего угла ,если конечно это не окружность (а это не окружность), у которой точка регистрации в центре.


...

и да - мувик лежит на сцене и его лок. координаты совпадают с его глоб. координатами.

undefined
27.02.2011, 23:21
Так вы получаете не координаты его центра, а координаты его левого верхнего угла ,если конечно это не окружность (а это не окружность), у которой точка регистрации в центре.
ты путаешь localToGlobal c getRect. localToGlobal(new Point(0,0)) вернет как раз координаты центра, точнее того черного крестика который видно при редактировании символа в flash ide.
В твоем случае коррдинаты в new Point(0,0) надо заменить на координаты точки A относительно mc.

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

mikhailk
27.02.2011, 23:56
Где прямоугольник без заливки - сцена, окно приложения. Желтый прямоугольник - мувик. Точка "А" находится на мувиклипе, в данный момент в центре окна приложения. Важно чтобы при увеличении мувика точка "А" так и оставалась в центре сцены.

Можно положить все в спрайт с таким смещением, чтобы точка А была у него в точке 0,0.
Спрайт спозиционировать на сцене так, чтобы точка А была в нужном месте.
После этого при применении скалирования к спрайту точка А двигаться не будет, а все, что лежит в спрайте, будет равномерно скалироваться относительно нее.

undefined
28.02.2011, 00:06
тоже неплохой вариант
сам последнее время пытаюсь всю графику внутри символов выравнивать так, чтоб точка (0,0) была в геометрическом центре символа. Тогда при изменение размера стейджа надо просто пропорционально изменить координаты мувиков и не надо вызывать гетеры width и height. Работает не всегда, но достаточно часто.

fish_r
28.02.2011, 00:16
А, понял! я вас немного в заблуждение ввел этой точкой "А". Дело в том, что точка "А" это не объект, точкой "А" , здесь, я обозначаю место которое сейчас находится в центре сцены, и это место всегда должно оставаться в центре. Спрайт не подходит, так как я заранее не знаю, где именно будет точка "А". Ближайший аналог, такой системы, который приходит на ум - карты гугла и яндекса, или средство просм. изображений в винде.

Добавлено через 6 минут
ты путаешь localToGlobal c getRect. localToGlobal(new Point(0,0)) вернет как раз координаты центра, точнее того черного крестика который видно при редактировании символа в flash ide...

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

Впрочем мы все равно не о том говорим, не вижу разницы между выявлением отношения координат центра и края к координатам другого объекта, если они в одном координатном пространстве, техника будет одна и та же.

mikhailk
28.02.2011, 00:31
Ну да, а черный крестик показывает точку регистрации, которая у символов обычно в верхнем левом углу, а не в центре, так, что ничего я не путаю

Точка регистрации может быть и в центре.

undefined
28.02.2011, 00:34
не вижу разницы между выявлением отношения координат центра и края к координатам другого объекта
Тоже не вижу.
Идея в том, что, зная какая точка мувиклипа должна быть в центре стейджа, независимо от точки регистрации, можно пригвоздить эту точку к стейджу, надо только узнать какую точку внутри мувика надо приклеить. Это моментально делается с помощью панели properties.

fish_r
28.02.2011, 00:44
Точка регистрации может быть и в центре.

Если вы сами ее измените, или если это окружность... К чему это замечание?

Добавлено через 2 минуты
Идея в том, что, зная какая точка мувиклипа должна быть в центре стейджа....

Да, не знаем мы где эта точка, она будет выбрана пользователем. Я не баннер делаю :), какие пропертис? :)

alexniks
28.02.2011, 00:54
создай спрайт mc1 и расположи его в нужной точке (точка А допустим). Положи в mc1 объект, который надо увеличивать (допустим mc2).
Увеличивай или уменьшай mc1, а не mc2. При этом начальная координата mc1 будет являться тем местом на экране, куда как бы увеличивается или уменьшается объект. А чтобы поменять центр увеличения или уменьшения у самого объекта передвигай mc2.

Вроде всё просто, а объяснить тяжело :)

undefined
28.02.2011, 00:57
Если вы сами ее измените, или если это окружность... К чему это замечание?
Почему ты считаешь что расположение точки регистрации как-то зависит от того какая форма у содержимого мувика? Точка регистрации может находиться где угодно не зависимо от того окружность это или нет.
Да, не знаем мы где эта точка, она будет выбрана пользователем. Я не баннер делаю , какие пропертис?
попробую еще раз: панель пропертис нужна чтоб ты узнал какая именно точка в ЛОКАЛЬНОЙ системе координат твоего мувика не должна смещаться. Это можно сделать и на глаз, но во flash ide сделать все-таки удобнее/точнее.

UPD: сорри, перечитал последний пост. Если неподвижная точка не известна сразу то можно её получить когда юзер кликнет по мувику. Надо только пересчитать координаты клика. Делается конечно без панели пропертиес, но с помощью тех-же методов localToGlobal и globalToLocal. Или как вариант можно взять mc.tansform.matrix у кликнутого мувика и умножить её на Point(mouseX,mouseY). По идеи результат должен быть одинаковым.

alexniks
28.02.2011, 01:18
Ааа....догнал, что ты хочешь.
Вот простой пример просмотра изображений в винде. Здесь только увеличение, уменьшение по тому же принципу.


var scale:Number = 1;

mc1.mc2.addEventListener(MouseEvent.CLICK,clickevent);

function clickevent(e:MouseEvent):void{
scale += 0.2;
mc1.scaleX = mc1.scaleY = scale;
mc1.mc2.x = -mc1.mc2.mouseX;
mc1.mc2.y = -mc1.mc2.mouseY;
}

fish_r
28.02.2011, 01:28
создай спрайт mc1 и расположи его в нужной точке (точка А допустим)....

Нет. "Хрен редьки не слаще" :). Сейчас я расчитываю смещение мувика относительно сцены, а в вашем варианте, мне нужно будет расчитывать смещение мувика относительно спрайта.

alexniks
28.02.2011, 02:14
тогда используй матрицу


import flash.geom.Matrix;
import flash.geom.Transform;

var scale:Number = 1;

mc1.addEventListener(MouseEvent.CLICK,clickevent);

function clickevent(e:MouseEvent):void{
scale += 0.2;
var mat:Matrix = new Matrix();
mat.scale(scale,scale);
mat.translate(-mc1.mouseX * scale +stage.stageWidth/2,-mc1.mouseY * scale + stage.stageHeight/2);
mc1.transform.matrix = mat;
}


или пример без матрицы


var scale:Number = 1;

mc1.addEventListener(MouseEvent.CLICK,clickevent);

function clickevent(e:MouseEvent):void{
scale += 0.2;
mc1.x = -mc1.mouseX * scale +stage.stageWidth/2;
mc1.y = -mc1.mouseY * scale + stage.stageHeight/2;
mc1.scaleX = mc1.scaleY = scale;
}

fish_r
28.02.2011, 03:07
...

Не подходит. Работает также как и мой алгоритм с центробежным смещением сцены... :(

Добавлено через 23 минуты
Спасибо всем! Так я и не поборол эту штуку! Но нашёл костыль... Работает как надо.

Добавлено через 4 часа 1 минуту
Дошло до меня. Растягиваем и смещаем мувик. Это мы учитываем. Не учитываем то, что изображение в нем тоже растягивается а значит точка растет и смещается к центру. Здесь надо подбирать каэффициент этого растяжения. Не стал, так как, как уже писал, решил через костыль.