Вопрос:
Привет. Спасибо за ресурс. Впервые нормально оформлен, отлично описан, доходчиво рассказан, что для чего и почему. Что очень радует. И ещё раз спасибо. Хотел бы предложить наверное ещё одну тему из всеобщего обсуждения, “а как это сделать?” ;) А именно, флеш карта… С прокруткой, зумом описанием обьектов и других примочек.
Что скажешь?
Ответ:
А что я могу сказать? =) Конечно полностью делать за вас масштабируемую Flash карту я не буду, но заготовочку, как пищу для размышлений, подкину. Кстати, хочется сказать, что это чуть-ли не единственное письмо, которое я опубликовал без исправлений/сокращений, приятно и понятно всё написано, вы уж не обессуйте, что я полторы недели вас заставлял ждать, уж совсем не было времени.
Масштабируемая флешка
Собственно ничего сложного нет… Что такое “масштабируемая”? Это когда флешку / объект внутри флеш, можно уменьшать/увеличивать без потери качества и другого гемороя. Как известно, в этом плане Flash с растром не очень дружат. При увеличении, что естественно, растр ухудшается в качестве, на нём появляются квадратики и прочее. Так же при поворотах и “сжатии”, растр любит “ломаться”, что тоже, согласитесь, не очень красиво. Что остаётся? А остаётся нам использовать вектор, благо Илюстратором и Корелом сейчас мало кого удивишь, да и Flash, сама по себе программа для векторной графики/анимации, так что пробуем =)
Ах да, что-то я так увлёкся рассказом теоретической части «что-использовать-и-зачем» и совсем забыл упомянуть о функциях и свойствах, которые мы будем юзать для создания нужного эффекта в нашей флешке. Тут, тоже, ничего нового я вам не открою, использовать мы будем _xscale и _yscalse свойства Movie Clip объектов. Именно эти два свойства отвечают за масштабирование в процентах по оси X (ширина) и оси Y (высота). Единственное, что я вам посоветую, так это центрировать нужный вам объект не по левому верхнему углу, а по центру, чтобы центральная точка рисунка или клипа, совпадала с началом координат его родительского объекта.
Непосредственно код
В приведённом мною примере я создал на рабочем поле объект logo_mc, который, собственно, и масштабируется, а так же ползунок pan_mc, в котором помещается изображение “шкалы” делений, и непосредственно сам красный ползунок, имя ему тоже pan_mc. Для пущей красоты, вы можете, как и я, наложить маску на масштабируемый объект, нарисовать рамочку, но это всё не так важно, основной функционал можно осуществить и без этого. В общем ориентируйтесь на то, что вам надо, и смотрите код:
/*
Сегодня по просьбе телезрителей, хоть и с запозданием, н овсё же, мы разбираем урок по ЗУМУ (приближению/
/масштабированию) объектов
*/
//Делаем, чтобы флешка не масштабировалась
Stage.scaleMode = “noScale”;
_root._quality = “BEST”;
//
//Функция МАСШТАБИРОВАНИЯ
//
function zoom_func() {
trace(“zoom_func”);
//
//Проверяем положение позунка
//
//Сразу надо отметить, что функция Math.round - округляет не целые числа, до ближайшего целого числа.
//Т.е. число 0.5 вернёт нам 1, а число 0.3 - ноль
//Функция Math.abs - возвращает нам модуль числа, т.е. всё время будет возвращать положительные значения
//Так, запись Math.abs(-5) и Math.abs(5) вернёт абсолютно одинаковые значения, т.е. 5
//
//Кто не знает, свойства _xscale и _yscale отвечают за масштабирование обхекта по X и Y соответственно,
//стандартное значение этих свойств у объекта без искажений по ширине или высоте будет 100,
//если ширина/высота увеличиваются, то значения _xscale и _yscale будут больше 100,
//если ширина/высота уменьшаются, то и значения свойств будут меньше 100.
if (_root.pan_mc.pan_mc._y<-1) {
//Если он выше координаты 0 по Y
_root.logo_mc._xscale = _root.logo_mc._yscale=100+1900/50*Math.round(Math.abs(_root.pan_mc.pan_mc._y));
} else if (_root.pan_mc.pan_mc._y>1) {
//Если он ниже координаты 0 по Y
_root.logo_mc._xscale = _root.logo_mc._yscale=100-95/50*Math.round(Math.abs(_root.pan_mc.pan_mc._y));
} else {
//Если ползунок находится в районе нулевой координаты
_root.logo_mc._xscale = _root.logo_mc._yscale=100;
}
//Присваиваем текстовому полю текущее значение масштаба объекта logo_mc
_root.zoom_txt.text = _root.logo_mc._xscale+“%”;
//Запускаем функцию, которая будет смещать объект logo_mc в зависимости от положения курсора
//и размеров объекта (см. ниже)
_root.onMouseMove();
}
//
//ПОЛЗУНОК РЕГУЛИРОВАНИЯ МАСШТАБА ОБЪЕКТА
//
//Создаём событие “НАЖАТЬ”
pan_mc.pan_mc.onPress = function() {
//Когда на ползунок нажали, для бОльшей наглядности, меняем цвет ползунка, на более блеклый
this.gotoAndStop(2);
//Начинаем перетаксивать ползунок
this.startDrag(false, this._x, -50, this._x, 50);
//При движении мышью запускаем функцию МАСШТАБИРОВАНИЯ, которая была описана выше
this.onMouseMove = _root.zoom_func;
};
//Создаём событие “ОТПУСТИТЬ”
pan_mc.pan_mc.onRelease = pan_mc.pan_mc.onReleaseOutside=function () {
//Возвращаем начальный цвет ползунку
this.gotoAndStop(1);
//Останавливаем перетаскивание
this.stopDrag();
//Удаляем событие, которое срабатывало каждый раз при движении мышки
delete this.onMouseMove;
};
//
//Создаём событие на движение мышки, в зависимости от положения курсора мы будемсдвигать клип logo_mc
//либо левее, либо правее центра экрана
//
onMouseMove = function () {
//Проверяем, если мышка находится в пределах рамки, размером 650 на 400 пикселей, то активируем
//перемещение объекта logo_mc
if (_xmouse>0 and _xmouse<650 and _ymouse>0 and _ymouse<400) {
//Расчитываем коэфициент “СДВИГА”, грубо говоря, он нам будет показывать на сколько левее или правее
//от центра флешки находится курсор мышки в процентном соотношении.
//Этот коэфициент будет изменяться от -1 до 1, где -1 - это курсор находится в самой крайней левой
//по оси X, ещё чуть чуть и курсор выйдет за край рамки слева. 0 - это курсор находится на середине
//флешки. 1 - курсор находится в крайней правой точке.
varKoefX = (_xmouse/325)-1;
trace(“varKoef “+varKoefX);
//Расчитываем разницу, между шириной объекта и шириной рамки (рабочей области). Полученное значение
//делится на 2, потому что есть правй и левый край. Не знаю, как объяснить лучже даже, в общем
//примите это как есть =)
varDif = (650-logo_mc._width)/2;
trace(“varDif “+varDif);
//Проверяем, меньше или больше ширина клипа ширины рабочей области.
//В зависимости от условий проверки применяем свой алгоритм расчёта смещения клипа от центра.
//
//325 - это ширина рабочей области, делённая по-полам, т.е., грубо говоря, СЕРЕДИНА.
if (logo_mc._width<650) {
logo_mc._x = 325-(varDif*varKoefX);
} else {
logo_mc._x = 325+(varDif*varKoefX);
}
//ПРОВОДИМ АНАЛОГИЧНЫЕ ДЕЙСТВИЯ С ВЫСОТОЙ ОБЪЕКТА И СМЕЩЕНИЕМ ЕГО ПО ОСИ Y
varKoefY = (_ymouse/200)-1;
trace(“varKoefY “+varKoefY);
varDifY = (400-logo_mc._height)/2;
trace(“varDifY “+varDifY);
if (logo_mc._height<400) {
logo_mc._y = 200-(varDifY*varKoefY);
} else {
logo_mc._y = 200+(varDifY*varKoefY);
}
}
};
//
//Создаём событие на ВРАЩЕНИЕ КУРСОРА
//
//В качестве слушателя события подключаем _root
Mouse.addListener(this);
//Создаём само событие вращения колёсика (подробнее о нём можете почитать здесь:
// http://www.flashist.ru/2007/12/08/vrashhenie-kolyosika-myshki-i-peremotka/
this.onMouseWheel = function(varDelta:Number) {
trace(“onMouseWheel”);
//Смещаем положение ползунка
_root.pan_mc.pan_mc._y -= varDelta;
//Проверяем, если ползунок поднимается выше отметки -50 по Y, то ставим его на положение -50
if (_root.pan_mc.pan_mc._y<-50) {
_root.pan_mc.pan_mc._y = -50;
} else if (_root.pan_mc.pan_mc._y>50) {
//Если опускается ниже 50, то ставим на 50
_root.pan_mc.pan_mc._y = 50;
}
//Запускаем функцию МАСШТАБИРОВАНИЯ
_root.zoom_func();
};
Вот, собственно, и всё, масштабируемый объект создан, как он работает вы можете посмотреть в примере, ну и скачать fla исходник, в котором обильно содержатся комментарии к коду. Good Luck — удачи, по-нашему =)
Сама флешка (swf) | Исходник (fla) |
Огромное спасибо. Будет от чего оттолкнутья.
Огромное пожалуйста, рад, что вам пригодился этот урок =)
А такую карту сделать реально????
Подкиньте маленький исходничек для размышлений.
Очень Вас прошу.
В конце новости есть ссылка на исходник, качайте его.
Я качал.
Спасибо -но вот меня интересует такой вопрос как реализовать такой поиск по улицам ,как показивать всю улицу и как добавлять метки?
Буду очень признателен
Тут в один комментарий тяжело будет уместить весь ответ. В целом, изучайте (если ещё не знаете) работу с массивами. Я бы, скорее всего, создал массив, с объектами, у которых были бы свойства _x, _y, _name (и возможно какие-то другие), потом, когда нужно было бы организовать поиск перебирал бы массив и сравнивал значения свойства _name с необходимым значением, если бы значение совпадало, то передвигал бы карту к координатам _x и _y, примерно вот такой вот принцип.
Спасибо буду пробовать
Как бы сделать передвижение по карте с помощью нажатой левой клавиши мышки и как бы рука в кулак становится?, а то зависимость от простого движения мыши мне кажется неудобной.
1. Чтобы двигать объекты при зажатой кнопке мышки можно использовать startDrag()/stopDrag() функции, а можно реализовывать свои методы при событиях onPress/onRelease/onReleaseOutside.
2. Менять изображение курсора можно, если скрыть курсор через Mouse.hide(), и подключить на поле клип с изображением курсора, которое вам будет нужно. Потом это изображение курсора нужно будет двигать при событии onMouseMove в координаты _xmouse, _ymouse,
сделал перемещение с помощью нажатой клавиши мыши. удобно получилось. но столкнулся с проблемой. Карта векторная. загрузаю её и там где улицы, то есть пустое место просто напросто не зацепляется. Посоветуй чтонибудь :)
-----
и ещё столкнулся с проблемой. Если увеличить карту в самом краю, а потом её уменьшить, то она кудато за край экрана уходит. И потом надо искать её за краем флэшки. Что сделать, чтобы она в центр экрана уходила (уменьшалась)?
1) Сделайте прозрачный фон или фон цвета фона флешки в клипе с картой.
2) Каждый раз при изменении размеров проверяйте положение карты, если она «уходит» куда-то, то возвращайте её на крайнюю возможную позицию.
по первому пункту сделал.
по второму трабл.
Как мне возвращать карту плавно? ЧТобы при уменьшении масштаба она к центру сдвигалась? может посоветуете логику...
И ещё.
А зачем там нужна маска? Что она даёт полезного?
Маска, в моём примере, нужна для того, чтобы если флешка открывалась бы не в HTML, а напрямую, то чтобы был виден только участок карты.
Чтобы карта сдвигалась к центру, при изменении масштаба, каждый раз когда изменяется масштаб сдвигайте её к центру. Что именно у вас не получается, я не знаю, постарайтесь описать точнее проблему.
Понтяненько с маской. Получается мне надо условие поставить: Если уменьшается масштаб то плюсовать или минусовать по координатам х и у. Как мне узнать что уменьшается масштаб ??? Есть ли такое средство?
У вас есть событие, которые вызывается для изменения масштаба, внутри него и производите все необходимые действия.
Добрый день! Такой вопросик: если мне надо разместить на карте объекты, которые не меняют свой масштаб при изменении масштаба карты, их надо размещать на отдельном слое или впихнуть в мувик карты? И как мне менять их координаты? Перебирая многомерный массив? Дергаться не начнет если будет до 20-30 объектов? А лучше, просто направьте на путь истинный... Заранее спасибо
Вообще самый простой способ сделать так, чтобы объекты не менялись в размерах — перебирать массив с ними и изменять их пропорции обратно тому, как изменяются пропорции самой карты, то есть, если карта увеличивается, то уменьшаем пропорции объектов, если карта уменьшается, то увеличиваем.
На счёт тормозов — сказать тяжело, всё будет зависеть от того, сколько у вас будет объектов в массиве, что это будут за объекты, что будет использоваться в качестве карты (растр или вектор), и т.п.
Подскажите пжалста, как организовать появление окошка комментариев при наведении курсора на объект.
Примного благодарен.
Событие onRollOver (в AS2) или MOUSE_OVER (в AS3). Как делается остальное — можно догадаться, если посмотреть исходники на сайте (например, урок по созданию окон, как в Windows).
На будущее, если есть вопросы, то пишите их в раздел вопросов, не стоит их постить в комментарии к другим статьям.
всё вроде нормально получается с заготовкой, можно сказать карта готова. Но есть небольшой трабл если убираю Stage.scaleMode = “noScale”; то масштабируется абсолютно всё. Что прописать, чтобы не увеличивалась шкала масштаба? И ещё Есть ли средства стандартные чтобы при нажати накарту, её движении появлялась сомкнутая ладонь курсора
1) Если вы убираете "noScale", то всё и будет масштабироваться. Если вам нужно, чтобы масштабировались какие-то определённые объекты, то ставьте "noSCale" и при событии onResize масштабируйте те объекты, которые вам нужны.
2) Таких средств, на сколько я знаю, нет.
несколько неудобно, что карта постоянно бегает за мышкой (при наличии менюшек и управляющих кнопок, карта постоянно съезжает в сторону при наведении на них).
Поставил движение карты по событию onPress. Чтобы элементы на карте оставались активными, событие onPress привязал к мувику, который лежит между картой и активными элементами.
Работает не плохо. Но появилась новая проблема, над которой бьюсь уже третий день.
При увеличенной карте, если начинаю вращать колесиком мыши карту сильно "швыряет" в стороны. Если хочу приблизить какой-то участок в углу отображаемой области, меня "выкидывает" в самый угол карты :(
Как сделать, чтобы при вращении колесика карта масштабировалась, но тот участок карты, на котором находиться указатель мыши никуда не съезжал, а оставался на том же месте?
Все замечательно, но объясните пожалуйста, в этих строках:
_root.logo_mc._xscale = _root.logo_mc._yscale=100+1900/50*Math.round(Math.abs(_root.pan_mc.pan_mc._y)); } else if (_root.pan_mc.pan_mc._y>1) { //Если он ниже координаты 0 по Y _root.logo_mc._xscale = _root.logo_mc._yscale=100-95/50*Math.round(Math.abs(_root.pan_mc.pan_mc._y));откуда взялся коэффициент 1900/50* и 95/50. Что 100 - это 100%, натуральная величина, это понятно.
Скажите а можно флеш ролик или флеш приложение поместить в вашу карти и отменить увеличение \уменьшение прогрес баром а зделать скролом. пож покажите наоочно если можно.
спасибо за урок!
есть несколько вопросов:
1. как сделать "zoom" еще и клавишами "+" и "-"? если это возможно
2. как сделать перемещение вправо, влево, вниз, вверх кнопками и клавишами, при увеличении изображения и выхода его за рамки?
3. как сделать, чтобы при возвращении исходного размера, карта возвращалась в центр?
Да пример хороший но при применении больших карт или скажем так при увеличении векторной карты изображение уходит в сторону что не удобно. Видел решение с привязкой масштабирования к курсору
function onLoad(){ Mouse.addListener(this); } function onMouseWheel (delta:Number, scrollTarget:String) { this._x = this._x-5*this._xmouse*delta/100; this._y = this._y-5*this._ymouse*delta/100; this._xscale = this._xscale+5*delta; this._yscale = this._yscale+5*delta; }Единственный нюанс, что при загрузке такой флешки прелоадером код перестаёт работать.Может кто подскажет решение.
Здравствуйте! Меня интересует вот какой вопрос. Как сделать так, чтобы при движение мышкой, карта под зумом двигалась медленнее... А то при большом зуме объекты на карте просто пролетают. Можно ли сделать так, чтобы к примеру движении мышки в правый верхний угол карта как бы „подтягивалась“ к курсору.
Заранее спасибо!
to inclean
Я могу ответить тока на второй твой вопрос
Нужно добавить вот этот скрипт
var speed:Number = 4; logo_mc.onEnterFrame = function() { if (Key.isDown(Key.RIGHT)) { this._x = this._x+speed; } else if (Key.isDown(Key.LEFT)) { this._x = this._x-speed; } if (Key.isDown(Key.UP)) { this._y = this._y-speed; } else if (Key.isDown(Key.DOWN)) { this._y = this._y+speed; } };