Рабочая задача: карта + объекты

Ничего экстраординарного, просто задача по работе попалась.

Дана карта местности (картинка), на неё нанесено большое количество объектов, несколько тысяч. В каждый объект можно тыцнуть мышкой, карта большая, её надо позволять «таскать» мышкой.

Текущее решение тормозит, а надо сделать так, чтобы не тормозило.

У меня была гипотеза, что если нарисовать всё это дело на большущем CANVAS, выходящем за пределы экрана и позволить его таскать мышкой, то тормозит не будет.

В общем-то, похоже, подтвердилось. Я взял CANVAS 2000×2000 точек, накидал на него 4000 квадратов случайного цвета и в случайных координатах, CANVAS положил в DIV, растянутый 100% на 100% и скрыл у него скроллеры.

Муляж карты (38.97КиБ)

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

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

Поделиться
Отправить
35 комментариев
Счастливая Oki-Sun (happy-ksu.ya.ru)

это то, что я думаю?))

indeec17

А это правда карта? Насколько я понимаю, если это действительно карта и она очень широкая, то может быть надо смоделировать как освобождающееся место будет заполняться новыми объектами и самой картой, и замерить время, что быстрее: добавлять канвасы или преобразовывать имеющийся?

indeec17

прости за вопрос, а что это за оператор такой ~~ ?

SiMM (mr-simm.livejournal.com)

Комментарий для indeec17:

а что это за оператор такой ~~ ?

real to int, видимо (в JS не силён)
http://wdh.suncloud.ru/js04.htm#ref343

Евгений Степанищев (bolknote.ru)

Комментарий для happy-ksu.ya.ru:

это то, что я думаю?))

Ога :)

Евгений Степанищев (bolknote.ru)

Комментарий для indeec17:

А это правда карта?

Правда, но карта ограниченной местности. Она вся тут поместится.

прости за вопрос, а что это за оператор такой ~~ ?

Выше правильно ответили, это действительно приведение к целому. Точнее, это побочный эффект оператора „~“.

Orcinus Orca (orcinus.ru)

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

Тестировалоь на: UA: Mozilla/5.0 (Windows NT 5.1; rv:2.0) Gecko/20100101 Firefox/4.0

Kildor (kildor.ya.ru)

Комментарий для Евгения Степанищева:

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

По поводу карт, разработчики World of Tanks сделали карту на SVG,  http://challenge.worldoftanks.ru/uc/clanwars/maps/

indeec17

Комментарий для mr-simm.livejournal.com:

спасибо

indeec17

Комментарий для Евгения Степанищева:

Выше правильно ответили, это действительно приведение к целому. Точнее, это побочный эффект оператора „~“.

Спасибо, буду знать. Замечательно сокращает код. Как-то даже не подумал, что операция not отбрасывает дробную часть. Как-то, когда экспериментировал с C-​-​, там дробная часть имела битовое представление и нормально инвертировалась.

Евгений Степанищев (bolknote.ru)

Комментарий для orcinus.ru:

Есть маленький побочный эффект. Если тащить карту, за один из цветных прямоугольников, то после отпускания выводится информация об объекте на который тыкнули мышкой.

Спасибо! Это у меня проверочный прототип, скорее, чем реальный проект.

Евгений Степанищев (bolknote.ru)

Комментарий для kildor.ya.ru:

По поводу карт, разработчики World of Tanks сделали карту на SVG

SVG сильно тормозит, если отображается много объектов (у меня на карте их 4000, это смерть для SVG).

Это не сама технология плохая, просто она пока не «модная», поэтому разработчики браузеров не оптимизируют отображение SVG.

Евгений Степанищев (bolknote.ru)

Комментарий для indeec17:

Как-то, когда экспериментировал с C-​-​, там дробная часть имела битовое представление и нормально инвертировалась.

JS не умеет работать побитно с дробной частью. Примеры: 1.5|0, 1.5<<0 и так далее.

zve55 (openid.yandex.ru/zve55/)

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

Евгений Степанищев (bolknote.ru)

Комментарий для openid.yandex.ru/zve55/:

Спасибо! Там есть масса недоделок. Это потому что это прототип.

boltai-shaltai

Комментарий для Евгения Степанищева:

Интересный факт; кажется, пригодится. Но, поскольку до сих пор самому рисовать карту не доводилось, трудновато понять, на именно тут делается акцент.

Правильно ли я думаю, что тормоза в «текущем решении» происходят оттого, что тысячи нанесённых объектов физически являются отдельными дом-объектами (дивы, картинки)? И контейнер с этой тучей маркеров сдвигается с большой мукой? Но если контейнером маркеров сделать canvas, то ему-то сдвигаться становится легче?

Сама карта ни при чём (неважно, огромная картинка или тайлы), она лишь подложка к оверлейному слою.
А фишка именно в отрисовке огромного количества мелких мулек поверх неважно какой карты?

Евгений Степанищев (bolknote.ru)

Комментарий для boltai-shaltai:

Правильно ли я думаю, что тормоза в «текущем решении» происходят оттого, что тысячи нанесённых объектов физически являются отдельными дом-объектами (дивы, картинки)? И контейнер с этой тучей маркеров сдвигается с большой мукой?

Точно.

Но если контейнером маркеров сделать canvas, то ему-то сдвигаться становится легче?

Канвас не контейнер. Это «холст», картинка.

boltai-shaltai

Комментарий для Евгения Степанищева:

Канвас не контейнер. Это «холст», картинка.

Понимаю; но визуально и функционально эффект достигается именно такой.

Спасибо.

Азат Разетдинов (razetdinov.ya.ru)
Евгений Степанищев (bolknote.ru)

Комментарий для razetdinov.ya.ru:

Я тебе в личку отвечу.

ded_flint (ded-flint.livejournal.com)

Комментарий для Евгения Степанищева:

На айпаде не работает :(
интересно, почему?

Евгений Степанищев (bolknote.ru)

Комментарий для ded-flint.livejournal.com:

Там другие события обрабатывать надо. Там мышки нет.

Евгений Степанищев (bolknote.ru)

Комментарий для ded-flint.livejournal.com:

Или квадратики не рисуются?

ded_flint (ded-flint.livejournal.com)

Комментарий для Евгения Степанищева:

Квадратики рисуются, но перетаскивание не работает. Так же как на сайте яндекс.карты в андроидных браузерах (nook color, viewsonic viewpad 10s)
а можно подробнее про различия в событиях?

Евгений Степанищев (bolknote.ru)

Комментарий для ded-flint.livejournal.com:

Вот, например:  http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

Shurik (shurshur.livejournal.com)

Вот тут люди тоже страдают канвасом: https://github.com/kothic/kothic-js
Там же есть обзор, что не работает в каких браузерах.

Евгений Степанищев (bolknote.ru)

Комментарий для shurshur.livejournal.com:

Многие «страют канвасом». А где обзор?

Александр

При таком решении сделать увеличение карты будет крайне сложно, а перемещение при увеличении еще сложнее :)

Евгений Степанищев (bolknote.ru)

Комментарий для Александр:

Почему это? С чего вдруг?

Александр

Предполагаю что квадраты-маркеры должны быть привязаны к географическим координатам.

При увеличении прийдется масштабировать весь canvas на 18-19 уровне увеличения из-за размера производительность уже может быть не такой хорошей, но самое неприятное что по-скольку маркеры уже отрисованы на канвасе, то для них нужно будет скомпенсировать масштабирование, чтобы они остались изначального размера. Для простых квадратов это может быть чуть легче, но если будет графика, то это проблема. Также если все-таки сделать масштабирование без потери качества, то может возникнуть необходимость чуть-чуть смещать маркеры чтобы они оставались по-центру, относительно изначальной точки. Т. е. по сути это будет такое же позициоранивание как в обычном подходе, просто без необходимости вычислять координаты на канвасе каждый раз.

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

Shurik (shurshur.livejournal.com)

Комментарий для Евгения Степанищева:

Тут:  https://github.com/kothic/kothic-js/wiki/Browser-bugs

Евгений Степанищев (bolknote.ru)

Комментарий для Александр:

Откуда столько уровней? Вот текущий вид — это уже максимальное увеличение. Больше в этой задаче не требуется. И вообще, карты не масштабируют до бесконечности, какой в этом смысл?

Кроме того, я всё-таки не понимаю в чём проблема. Сейчас какие-нибудь «Яндекс.Карты» (так же как и карты Гугла) — это куча растра для разных масштабов с нанесёнными объектами. Тут ровно то же. Только объекты на графику наносятся на клиенте.

Евгений Степанищев (bolknote.ru)

Комментарий для shurshur.livejournal.com:

Тут: https://github.com/kothic/kothic-js/wiki/Browser-bugs

Полезная ссылка, спасибо!

ded_flint (ded-flint.livejournal.com)

Комментарий для Евгения Степанищева:

отличную штуку нашёл, недалеко от темы  http://paperjs.org/about/

Евгений Степанищев (bolknote.ru)

Комментарий для ded-flint.livejournal.com:

Да их как грибов после дождя повылезало этих фреймворков. Чем именно этот-то хорош?

Популярное