Пишу, по большей части, про историю, свою жизнь и немного про программирование.

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

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

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

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

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

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

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

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

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

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

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

indeec17 2011

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

indeec17 2011

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

SiMM (mr-simm.livejournal.com) 2011

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

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

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

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

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

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

Ога :)

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

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

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

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

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

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

Orcinus Orca (orcinus.ru) 2011

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

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

Kildor (kildor.ya.ru) 2011

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

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

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

indeec17 2011

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

спасибо

indeec17 2011

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

zve55 (openid.yandex.ru/zve55/) 2011

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

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

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

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

boltai-shaltai 2011

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

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

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

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

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

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

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

Точно.

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

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

boltai-shaltai 2011

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

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

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

Спасибо.

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

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

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

ded_flint (ded-flint.livejournal.com) 2011

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

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

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

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

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

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

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

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

ded_flint (ded-flint.livejournal.com) 2011

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

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

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

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

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

Shurik (shurshur.livejournal.com) 2011

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

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

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

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

Александр 2011

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

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

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

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

Александр 2011

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

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

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

Shurik (shurshur.livejournal.com) 2011

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

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

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

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

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

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

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

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

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

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

ded_flint (ded-flint.livejournal.com) 2011

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

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

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

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

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