Pull to refresh
216
0
Владимир Агафонкин @Mourner

User

Send message
Насчёт дрожания — это следствие предварительного отсеивания точек, о котором я писал в статье. Можно сделать без него, но тогда будет работать раз в 10 медленнее, что недопустимо.

Насчёт дуг/окружностей — нет, таким не занимался.
Не знал, что Гугл проводил сертификацию по своим картам, интересно. :) Получили от этого пользу какую-то?
Во-первых ты забыл, что JavaScript теперь активно используется и на сервере. :) Во-вторых передавать полные данные на клиент имеет смысл тогда, когда визуализировать их нужно динамически в зависимости от выбранного масштаба. Скажем, когда пользователь выделяет область на графике, чтобы к ней зазумиться, упрощение нужно пересчитывать (т.к. координаты с изменением масштаба тоже поменяются).
Да, для меня написание подобных библиотек — отличное упражнение в умении писать чистый код. :) В маленьких масштабах это делать намного проще. И JSLint/JSHint помогает, конечно.
Да ладно вам, случайно пропустил человек предложение в тексте… Давайте жить дружно :)
Визуализация кривых из большого количества точек — карты с векторными данными, динамические графики и т.д. Вот пример реального использования (громадный маршрут на Leaflet-карте): leaflet.cloudmade.com/debug/vector/vector.html
И мне, интересно :)
У меня такая же модель, как в комментарии выше!
Спасибо на добром слове! Я сам нарвался. :)
Тайлы CloudMade теоретически должны обновляться каждую неделю, но на практике бывают задержки. Но с Лифлетом хорошо то, что можно в любой момент переключиться на другого провайдера, если что. :)
Идеи-идеями, а в первую очередь нужно сделать удобно пользователю. Лучше добавить n удобных шорткатов для разных провайдеров, чем заставлять писать такие мозгоразрывающие конструкции.

По-моему конструкции элементарные, абсолютно ничего сложного в них не вижу, и разве сложно написать один раз за весь проект пару строчек? Удобные шорткаты для провайдеров я лучше вынесу в плагины. Идея, о которой я говорил, достаточно принципиальна.

Мысль в том, что фабрики вместо (или вместе с) конструкторов выглядят гораздо красивее с чайнингом. Принципиально настаивать на обязательном использовании слова new несмотря на неудобства — это уже из области религии.

То, что фабрики выглядят красивее — это тоже из области религии.

Тогда тайловые слои надо переименовать.

Зачем? Я так и не понял, чем конкретно такое обобщение осложняет пользование библиотекой.

Посмотрите, как решена эта проблема в Гугле.
Есть урл на последнюю _стабильную_ версию, который рекомендован всем. Для разработки есть урл на последнюю выпущенную сборку + есть урлы на каждый конкретный релиз.

«Стабильность» версии не гарантирует отсутствия регрессий. И если уже сталкиваться с ними, то лучше при разработке, чем вдруг внезапно обнаружить у себя на продакшне.

Мне очень не нравится, что так сделано у гугла. И делает он так совсем не для того, чтобы у всех пользователей всё было стабильно и круто. А по одной причине — для лучшего контроля над пользователями библиотеки, например, втулить насильно рекламу, если им вдруг однажды взбредёт такое в голову.
И сразу вопрос — почему некоторые ссылки серые и никуда не ведут? Документация не готова? Сломалось что-то? Roadmap? Кстати, а к какой версии эта документация — к стабильной 0.2 или dev 0.3?

Всё, что серое, не успел написать еще — наметил то, что будет в скором времени. :) Насчёт путаницы с версиями согласен, всё уточним и исправим.

Гм. Если опции карты всегда перекрывают опции слоя и у них есть дефолтное значение — зачем тогда нужны опции слоя? Непонятно…

Если жёстко не ограничить зум карты вручную, ограничения высчитываются автоматически в зависимости от того, какие слои на карте. Надо уточить там формулировку, да.

Более интересно другое — почему ILayer-ы удостоены отдельной опции-массива layers, а IHandler-ы и IControl-ы — нет. Разве так не логичнее?


Потому что layers по умолчанию пустой массив, его просто задавать сразу массивом, а в случае с контролами и хендлерами всё сложнее — есть определённый дефолтный набор для карты, который может еще и варьироваться в зависимости от браузера (напр., мобильный или десктопный). Поэтому их контролировать проще индивидуально, чем выяснять, какие должны быть в каких случаях, составлять массив в нём уже что-то добавлять/убирать.

А mouseup, contextmenu, mouseenter, mouseleave? Уж как-то совсем странно предоставлять событие mousedown и не давать слушать mouseup.

Всё есть, просто документацию доработать нужно. :)

Уберите неинициализированное состояние карты, и в этих двух событиях отпадёт нужда.

Изначально его не было, но со временем решил добавить. Бывают случаи, когда нужно инициализировать карту сначала частично (например, задать только зум и слои), а потом уже по какому-то событию доинициализировать. Чтобы убрать состояние инициализированности, нужно либо навязывать человеку инициализировать всё сразу в конструкторе и никак иначе (что неудобно), либо задавать дефолтные значения для центра и зума, что в примере выше приведёт к тому, что будет загружен сначала один набор тайлов, а потом другой. Событие load ничему не мешает, о нём в общем случае можно и не знать вообще, и использовать только в некоторых случаях, поэтому убирать нет причин.

А вот насчёт viewreset — не понял, как это отпадёт нужда? Это самый важный ивент для реализации всех слоёв карты. Он говорит слоям, когда нужно перепроецировать координаты.

Ну и многие методы просто избыточны — например, зачем нужны отдельные методы locate и locateAndSetView, если можно просто обойтись флагом setView в опциях метода locate?

Забыл удалить из документации. :)

Зачем нужны методы zoomIn/zoomOut, когда есть setZoom?

Для удобства. Чтобы не писать
map.setZoom(map.getZoom() + 1)
. Но в принципе не критично, может быть, и стоит убрать.

Вообще насчёт большого кол-ва и некоторой неконсистентности методов Map согласен, это я обязательно приведу в порядок вместе с документацией.

Невозможность перезадать иконку не радует

marker.setIcon(icon);
— опять же, пробел документации.

отсутствие нативной возможности связать с маркером какие-то данные

Идентификатор любого объекта в Leaflet можно получить так:
var id = L.Util.stamp(marker);
. А где хранить какие данные — мне кажется, это лучше оставлять на совесть разработчикам — как кому удобнее. Предлагаете сделать что-то типа jQuery
.data
?

Почему-то для других сервисов (WMS) отдельный класс для удобства заведён, а для родного — нет.

Потому что WMS — это открытый стандарт интерфейса сервиса, а конкретный сервис может быть какой угодно. То же самое с CloudMade — общий для подобных слоёв класс TileLayer заведён, а для конкретного сервиса будь добр, задай его опции. По-моему, очень логично.

Также непонятно, зачем введена настройка «размер тайла».

Не все тайл-сервисы предоставляют тайлы 256х256, бывают и другие размеры, скажем, 64х64 или 1024х1024 (например kothic.org/js/).

Опция noClip с комментарием «Disabled polyline clipping.» поставила меня в тупик. Особенно отсутствием такой же опции у остальных геометрий.


Клиппинг имеет смысл только для полилайнов и полигонов, а полигон наследует опции полилайна. Или вам непонятно, что такое клиппинг?

В упор не вижу отличий от просто Circle. По названию «CircleMarker» я бы подумал, что это круг + маркер, но описание никаких наводок не даёт.

Круг фиксированного размера в пикселях — это означает, что он будет радиусом в, скажем, 10 пикселей независимо от масштаба карты. Я думал, это очевидно…

Зачем это сделано? Кому мешал радиус в сигнатуре? Или это такой способ сделать доступным изменение радиуса?

CircleMarker применяется в тех же случаях, что и обычный маркер, т.е. не для обозначения определённого географического круга, а как круглый маркер, которому в отличие от обычного можно задать любой цвет, радиус и т.д. и менять всё это динамически. Поэтому он так и называется. Радиус можно задать, еще не добавил в документацию.

Группа LayerGroup, в которую можно класть не только слои, но и маркеры/графику — это очень странно. Ссылка ILayer всё ещё никуда не ведёт. Метод clearLayers, который удаляет всех детей группы (а не очищает тайловые слои, как лично я бы подумал из названия) — тоже очень странный.


Ну это, опять же, от непонимания концепции слоёв. :) Это не странно, а удобно и даёт много разных возможностей. Зачем делать для этого разные классы, если они будут одинаковыми и делать одно и то же?

Но группа FeatureGroup, которая к LayerGroup добавляет пропагацию событий и попап — это уже прямо совсем странно. Что должно кому сказать название Feature?

Feature — это всё, что на карте имеет смысл делать интерактивным. :) Да, объяснить в документации нужно.

Самое-то интересное и скрыто за «do something». А что сделать-то можно? Группа не даёт аксессоров до дочерних объектов. Если я добавил FeatureCollection через geojson — что я сделать-то с ней могу? Или FeatureCollection нельзя добавлять, затем и накопительный addGeoJSON?


Всё можно сделать. :) А у FeatureGroup есть еще setStyle.

Недостатки функционала, положим, можно легко списать на малый размер библиотеки (25Кб — рекорд). (Только вот что тут экономить, если библиотека весит меньше, чем один стандартный тайл?)

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

А насчёт недостатка в функционале — в ней в общем-то не так много всего осталось реализовать. Не хочется превращать библиотеку в здоровенного неповоротливого монстра, подобного OpenLayers, в которой 95% функционала используется 5% пользователей, если не хуже.

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

Конечно доработаю. :) И особенно документацию, а то, как вижу, слишком мало ей уделял внимания в последнее время, нужно исправляться…

В общем спасибо большое, тонны полезных комментариев, с множеством всего согласен, буду исправлять и дорабатывать!
Ох не представляю, что может написать forgotten в обзоре OpenLayers… :) Наверное, целую многотомную книгу с повышенным содержанием матов и WTF. :)
Спасибо большое за детальную критику, это невероятно полезно для проекта!
Комментировать придётся долго… Ну что ж, приступим. :)

«Пример начинается с создания слоя с тайлами от cloudmade. Само API вроде как тоже «by cloudmade». Внимание, вопрос: а что, для родительского/дружественного проекта нельзя сделать удобный способ добавления слоя тайлов?»

Идея была в том, чтобы создать абсолютно провайдеро-независимую опенсорс-библиотеку, подчеркивая то, что она не навязывает использование сервисов конкретных компаний и не содержит провайдер-ориентированного кода (это оставим плагинам и т.д.), и использовать можно любые тайлы, поэтому пример сразу такой, чтобы человек мог за две минуты поменять на тайлы, которые ему нравятся, например, от MapQuest или MapBox.

Согласен, что нужно это на сайте подчеркнуть, чтобы было понятнее — даже багрепорт такой есть в GitHub issues. :)

«Кстати, из приведённого примера хорошо заметно неудобство смешивания объектного подхода и чайнинга — (new X()).y() не самая красивая конструкция в JS.»

Библиотека не навязывает использование чейнинга. Главное, что есть выбор — можно так, можно эдак, это как человеку удобнее. Я лично предпочитаю, например, сначала создать объект и присвоить переменной, а потом уже с отдельной строки с ней проводить операции. По этой же причине в примерах используются разные подходы — чтобы подчеркнуть наличие выбора. Хотя, наверное, это тоже нуждается в дополнительном уточнении на сайте.

«Кстати, почему маркеры добавляются через addLayer? L.Layer в Leaflet — вполне понятная отдельная сущность — слой. Почему через addLayer добавляются и другие сущности — маркеры, геометрии?»

Потому что слой в Leaflet — это всё, что можно привязать к определённому географическому положению (или положениям) на карте, будь то слой тайлов, маркер или даже попап. Не вижу смысла разделять сущности типа карты и тайлов для самой карты — пускай этой не особо существенной разницей занимаются соответствующие реализации слоёв, а карта пускай всего поменьше знает — это loose coupling.

«Во-первых, откуда ж на моей странице возьмётся папка leaflet с кодом leaflet-а? Кажется, что вот как раз получение кода библиотеки и нужно описывать в разделе «Preparing your page».»

Подразумевалось, что люди, которые этого не понимают, будут скачивать библиотеку с leaflet.cloudmade.com/download.html, а там это написано. :) Хотя вы правы, нужно чётче это прописать в примере и оставить ссылку на эту страницу.

«Далее, зачем заставлять вебмастера самого размещать код подключения css? Почему не оставить эту работу js-скрипту?»

Раньше я так и делал, но в этом подходе обнаружилось очень много проблем. Во-первых появление нестилизованной карты перед тем, как скрипт догрузит стили. Во-вторых, что более серьёзная проблема, для корректной инициализации и работы карты многие элементы должны быть стилизованными, но мало того, что отслеживание onload динамически загруженного стиля нетривиальная задача, так еще и код для карты может исполняться до того, как стиль загрузился, и придумывать для этого хорошее решение намного больше мороки, чем просто попросить человека добавить дополнительно стиль на странице. Последний подход намного надёжнее и работает лучше.

«Удивляет другое — почему не хостите эту библиотеку сами и заставляете подключать с домена пользователя? Не ахти ж какая нагрузка, да и договориться с партнером каким-нибудь можно. Зато у ваших пользователей не будет проблем с обновлением версий (и с критическими багами в старых версиях, которые рано или поздно появятся) + с распространением библиотеки она очень скоро окажется у большинства пользователей в кэше.»

Тоже применяли такой подход раньше, но на практике выяснилось, что это ОЧЕНЬ плохая затея (по крайней мере URL типа "[...]/somelib-latest.js". Представьте, что у вас сайт с тысячами пользователей в день, и всё у вас прекрасно работает, ничего не трогаете, вы уезжаете в отпуск, возвращаетесь и вдруг обнаруживаете, что последние две недели нифига не работало из-за мелкой специфичной регрессии в последней версии, которая проявляется только в вашем конкретном случае и поэтому не была замечена разработчиками библиотеки (ВСЕ баги всё равно отловить невозможно, что-нибудь да вылезает время от времени). А вот будь у вас урл на конкретную версию, тогда всё бы работало, а обновляясь вручную, вы имели бы возможность всё проверить перед деплойментом на продакшн-сервер. Именно по этой причине практически ни один популярный фреймворк не представляет подобной возможности и всё по версиям тоже.

Вот сделать CDN с урлами на конкретные версии хочется, но пока не добрались до этого.

Дальше отвечу в следующем комментарии. :)
Отличный обзор! Было бы здорово, если бы вы так прошлись по моему leaflet.cloudmade.com/. :)
Здорово! Я думал в этом направлении развивать свою стереографическую демку СанКалка 10k.aneventapart.com/2/Uploads/660/, но запнулся на сборе данных звёзд, созведий и их соединений. Может, объединим усилия как-нибудь :)
Ну если кто-то чувствует опасность, можно воспользоваться описанным в комментарии методом и заменить на что душе угодно. :) Главное, что есть выбор.
Это просто для удобства, чтобы не загромождать код одним и тем же постоянно встречающимся словом. Я позаимствовал идею из jQuery с его $: вместо того, чтобы рекомендовать конструкции вроде
(function () { var L = Leaflet; ... }());
в каждом месте, где используется библиотека, я решил сделать наоборот — создавать переменную L безопасно, сохраняя старое значение (если есть), и дать возможность восстановить его, объявив для Leaflet любой другой неймспейс:
var Leaflet = L.noConflict(); // после этого L указывает на старое значение

Или писать безопасно в стиле jQuery Plugins:
(function (L) {
    ...
}(L.noConflict()));
Спасибо за упоминание Leaflet. :)

Насчёт L вместо Leaflet — как уже прокомментировали выше, тут различие только в названии переменной, в случае же с new меняется семантика кода. Я предпочитаю, чтобы различие между созданием объекта с помощью определённой функции в качестве конструктора и просто вызовом функции было явным, а не скрытым какими-то магическими конструкциями — как по мне, это делает код более читабельным и понятным, особенно людям, привычным к активному применению ООП.
Кстати говоря, уже есть библиотека для онлайн-карт, которая полностью построена на работе с канвасом — tile5.org. Посмотрите на досуге, может, почерпнёте что-нибудь полезное. :)
Спасибо за упоминание Leaflet, стараемся :)

Information

Rating
Does not participate
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity