Вопрос:
Привет. Спасибо за ресурс. Впервые нормально оформлен, отлично описан, доходчиво рассказан, что для чего и почему. Что очень радует. И ещё раз спасибо. Хотел бы предложить наверное ещё одну тему из всеобщего обсуждения, “а как это сделать?” ;) А именно, флеш карта… С прокруткой, зумом описанием обьектов и других примочек.
Что скажешь?
Ответ:
А что я могу сказать? =) Конечно полностью делать за вас масштабируемую 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,
Вот к чему Я пришел (это на as2):
box - невидимый квадрат на весь екран
zone - невидимая полоса по горизонтале
box.onPress = function() { go = true; zone._y = _ymouse; } box.onRelease = function() { go = false; } if(go == true){ if(_ymouse > zone._y){ map._y += 10; } if(_ymouse < zone._y){ map._y -= 10; } }По горизонтале фактически также.
сделал перемещение с помощью нажатой клавиши мыши. удобно получилось. но столкнулся с проблемой. Карта векторная. загрузаю её и там где улицы, то есть пустое место просто напросто не зацепляется. Посоветуй чтонибудь :)
-----
и ещё столкнулся с проблемой. Если увеличить карту в самом краю, а потом её уменьшить, то она кудато за край экрана уходит. И потом надо искать её за краем флэшки. Что сделать, чтобы она в центр экрана уходила (уменьшалась)?
Вот как Я реализовал зум.
Кнопка с плюсиком - plus
Кнопка с минусиком - minus
Область выше ползунка - goplus
Область ниже ползунка - gominus
Изображение линии с ползунком (первый кадр - ползунок максимально в низу, а последний, ползунок максимально в верху) - zoom_line
zoom_line.gominus.onPress = function() { zoommn = true; } zoom_line.gominus.onRelease = function() { zoommn = false; } zoom_line.goplus.onPress = function() { zoompl = true; } zoom_line.goplus.onRelease = function() { zoompl = false; } minus.onPress = function() { zoommn = true; } // ZOOM -- if(zoommn == true){ zoommn = false; if(zm._xscale > 40){ zoom_line.prevFrame(); map._xscale -= 70; map._yscale -= 70; } } // ZOOM ++ plus.onPress = function() { zoompl = true; } if(zoomplus == true){ zoompl = false; if(zm._xscale < 2000){ // Тут уж надо самому подстраивать zoom_line.nextFrame(); map._xscale += 70; map._yscale += 70; } }1) Сделайте прозрачный фон или фон цвета фона флешки в клипе с картой.
2) Каждый раз при изменении размеров проверяйте положение карты, если она «уходит» куда-то, то возвращайте её на крайнюю возможную позицию.
по первому пункту сделал.
по второму трабл.
Как мне возвращать карту плавно? ЧТобы при уменьшении масштаба она к центру сдвигалась? может посоветуете логику...
И ещё.
А зачем там нужна маска? Что она даёт полезного?
Маска, в моём примере, нужна для того, чтобы если флешка открывалась бы не в HTML, а напрямую, то чтобы был виден только участок карты.
Чтобы карта сдвигалась к центру, при изменении масштаба, каждый раз когда изменяется масштаб сдвигайте её к центру. Что именно у вас не получается, я не знаю, постарайтесь описать точнее проблему.
Понтяненько с маской. Получается мне надо условие поставить: Если уменьшается масштаб то плюсовать или минусовать по координатам х и у. Как мне узнать что уменьшается масштаб ??? Есть ли такое средство?
У вас есть событие, которые вызывается для изменения масштаба, внутри него и производите все необходимые действия.
Добрый день! Такой вопросик: если мне надо разместить на карте объекты, которые не меняют свой масштаб при изменении масштаба карты, их надо размещать на отдельном слое или впихнуть в мувик карты? И как мне менять их координаты? Перебирая многомерный массив? Дергаться не начнет если будет до 20-30 объектов? А лучше, просто направьте на путь истинный... Заранее спасибо
Вообще самый простой способ сделать так, чтобы объекты не менялись в размерах — перебирать массив с ними и изменять их пропорции обратно тому, как изменяются пропорции самой карты, то есть, если карта увеличивается, то уменьшаем пропорции объектов, если карта уменьшается, то увеличиваем.
На счёт тормозов — сказать тяжело, всё будет зависеть от того, сколько у вас будет объектов в массиве, что это будут за объекты, что будет использоваться в качестве карты (растр или вектор), и т.п.
Подскажите пжалста, как организовать появление окошка комментариев при наведении курсора на объект.
Примного благодарен.
Событие onRollOver (в AS2) или MOUSE_OVER (в AS3). Как делается остальное — можно догадаться, если посмотреть исходники на сайте (например, урок по созданию окон, как в Windows).
На будущее, если есть вопросы, то пишите их в раздел вопросов, не стоит их постить в комментарии к другим статьям.
as2
Код пишеться на мувик, внутри которого НА ВСЕХ кадрах есть невидимая кнопка enter_btn. Когда мышка наведена на мувик, он проигрываеться вперед(nextFrame), а когда не наведена то назад(prevFrame)
onClipEvent (enterFrame) { if (go) { nextFrame(); } else { prevFrame(); } } onClipEvent (load) { var go; stop(); enter_btn.onRollOver = function() { go = true; }; enter_btn.onRollOut = function() { go = false; }; }всё вроде нормально получается с заготовкой, можно сказать карта готова. Но есть небольшой трабл если убираю 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. как сделать, чтобы при возвращении исходного размера, карта возвращалась в центр?
1. if(KeyIsDown(Key.SPACE)) (- это при нажатие на прабел).
Или if(KeyIsDown(107)){ (- это при нажатие на плюс)
Чтобы посмотреть список значений символов, напиши в гугле as2 key, и в первом запросе, ищи снизу, будет большая таблица.
2.
if(Key.isDown(Key.LEFT)){
map._y -= 20;
}
И тд. Если Я правильно понял.
3. Чтото вроде:
if(map._xscale == 9000){
map._x = 100500;
map._y = 100500
}
(значения условно написал)
Да пример хороший но при применении больших карт или скажем так при увеличении векторной карты изображение уходит в сторону что не удобно. Видел решение с привязкой масштабирования к курсору
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; } };