Пишем редактор карт изображений (html image map) на javascript / html5 / inline SVG

в 19:09, , рубрики: html, html5, html5 file api, javascript, svg, векторная графика, метки: , , ,

Карты изображений применяются в том случае, когда требуется создать ссылку формы, отличной от прямоугольной. Например, для презентационных сайтов, отображения планов/схем и т.п.

Раньше создавать такие карты было удобно в Adobe ImageReady, но начиная с версии CS3 эта программа больше не поставляется с Фотошопом. На сегодняшний день подобный функционал есть в Adobe Fireworks, но устанавливать эту программу только из-за редактора карт (для работы мне нужен только Фотошоп) — не очень хорошая идея. Существуют и онлайн-редакторы, которые написаны, в основном, с использованием canvas. В них отсутствует возможность редактировать созданные области на карте. Если ошиблись — придется все переделывать. Да и создавать эти области не слишком удобно. Еще одно неудобство заключается в том, что картинку приходится загружать на сервер. В общем, надо писать что-то свое.

Итак, задача:
— написать на javascript редактор, который позволит создавать карты изображений — загружаем картинку, рисуем области, получаем html-код. Если ошиблись — должна быть возможность отредактировать карту. Редактор должен работать в оффлайн-режиме. Обеспечить поддержку только современных браузеров, в том числе Internet Explorer 9.

Summer html image map creator

Здесь отлично подойдет SVG

Для визуального отображения нарисованных областей карты вместо canvas отлично подойдет svg. Изменение размеров и координат создаваемой или редактируемой области можно будет отслеживать, меняя атрибуты у соответствующих svg-элементов. Чтобы использовать возможности DOM, необходимо встроить сам элемент svg на страницу (не через img, object, embed).

К счастью, в html5 появилась возможность встраивать инлайновый svg (поддерживается в современных браузерах, включая IE 9+). Для xhtml тоже есть возможность встроить svg, надо только не забыть про заголовок Content-Type: application/xhtml+xml, что не очень удобно.

Типы областей

Для карт изображений существует 3 возможных типа областей — прямоугольник, круг и многоугольник. Аналогами этих форм в svg являются элементы rect, circle, polygon (на стадии рисования polyline):

Прямоугольник

rectangle

html
<area shape="rect" coords="50, 20, 150, 70" />

svg
<rect x="50" y="20" width="100" height="50"/>
Круг

circle

html
<area shape="circle" coords="100, 50, 35" />

svg
<circle cx="100" cy="50" r="35"/>
Многоугольник

polygon

html
<area shape="poly" coords="100, 20, 150, 70, 50, 70" />

svg
<polyline points="100 20 150 70 50 70" />
<polygon points="100 20 150 70 50 70" />

Для каждой области необходимы также вспомогательные точки — хелперы (маленькие прямоугольники 5x5) — для указания ключевых узлов области и возможности по точкам эту область редактировать.

Для прямоугольника это будет 9 точек — 4 в вершинах, 4 в середине каждой стороны и одна в центре. Для круга — 5 (одна в центре и 4 на окружности). Для многоугольника — по числу вершин.

Чтобы потом было проще удалять область вместе с хелперами, объединим их в группы — в svg-элементе <g>.

Стили для SVG-элементов

Теперь SVG-элементы rect, circle, polygon надо стилизовать средствами CSS.
С помощью свойства stroke зададим цвет обводки (красный для прямоугольника, зеленый для круга и синий для многоугольника), а с помощью свойства fill зададим фон для областей, используя классы для различных состояний (режим редактирования / режим рисования / при наведении курсора / с указанным href / без href). Так как фон нужен полупрозрачный, его цвет укажем в RGBA, где последний параметр — прозрачность. Хелперы всегда имеют белый непрозрачный фон и черную обводку.

#svg rect {
    stroke-width: 3px;
    stroke: #F00;
    fill: rgba(255,255,255,0.3);
}
#svg rect.with_href {
    fill: rgba(0,0,0,0.3);
}
.edit#svg rect:hover {
    fill: rgba(50,200,50,0.3);
}
#svg rect.active {
    fill: rgba(0,0,0,0.5);
}
#svg circle {
    stroke-width: 3px;
    stroke: #0F0;
    fill: rgba(255,255,255,0.3);
}
#svg circle.with_href {
    fill: rgba(0,0,0,0.3);
}
.edit#svg circle:hover {
    fill: rgba(50,200,50,0.3);
}
#svg polyline, #svg polygon {
    stroke-width: 3px;
    stroke: #00F;
    fill: rgba(255,255,255,0.3);
}
#svg polygon.with_href {
    fill: rgba(0,0,0,0.3);
}
.edit#svg polygon:hover {
    fill: rgba(50,200,50,0.3);
}
#svg .selected {
    fill: rgba(50,200,50,0.5) !important;
}
#svg rect.helper {
    fill: #FFF;
    stroke: #000;
    stroke-width: 2px;
}
#svg rect.helper:hover {
    fill: #F00;
}

Для хелперов также укажем свойство cursor в зависимости от класса (в режиме редактирования это будет являться подсказкой, какой тип редактирования будет применяться при нажатии на данный хелпер).

.edit#svg rect, .edit#svg circle, .edit#svg polygon {
    cursor: move;
}
.edit#svg .pointer {
    cursor: pointer;
}
.edit#svg .e-resize {
    cursor: e-resize;
}
.edit#svg .ne-resize {
    cursor: ne-resize;
}
.edit#svg .nw-resize {
    cursor: nw-resize;
}
.edit#svg .n-resize {
    cursor: n-resize;
}
.edit#svg .se-resize {
    cursor: se-resize;
}
.edit#svg .sw-resize {
    cursor: sw-resize;
}
.edit#svg .s-resize {
    cursor: s-resize;
}
.edit#svg .w-resize {
    cursor: w-resize;
}

Стили для SVG-элементов поместим вместе со стилями для страницы — в main.css.

Интерфейс

Вначале нужно «загрузить» в редактор изображение, для которого требуется создать карту. Самый простой способ — указать путь к этому изображению. Такой способ удобен, если картинка находится на каком-либой сайте, тогда нужно просто скопировать ее путь. Но если картинка хранится на вашем компьютере, то это уже не слишком удобно. Хорошо было бы выбирать картинку, например, с помощью <input type="file" />, то есть средствами проводника. Но в этом случае в ряде браузеров можно получить доступ только к имени выбранного файла, но не к полному пути (из-за политики безопасности). И тут на помощь приходят HTML5 Drag and drop и File api (не поддерживается в IE9, для которого останется только первый способ). Перетаскиваем картинку, с помощью FileReader читаем ее содержимое и получаем ee base64 — вариант. Все, теперь нужная картинка отображается в редакторе. Теперь можно рисовать карту.

В редакторе предусмотрено 3 основных режима:

  • режим рисования (кнопки rectangle, circle, polygon) — первый клик по полю — начинается рисование соответствующего объекта. Второй клик — рисование области для прямоугольника и круга завершается. В случае многоугольника фигура замыкается при клике на первый хелпер или по нажатию ENTER;
  • режим редактирования (кнопка edit) — позволяет перемещать, удалять выделенные области (по нажатию DELETE), редактировать их параметры с помощью точек-хелперов и добавлять атрибуты href, title, alt (по двойному клику на области);
  • режим просмотра (кнопка preview) — скрывается svg и отображается сгенерированная карта изображения. Клик по области приводит к переходу по соответствующей ссылке (если для области был добавлен href).

Остальные кнопки:

  • clear — очиcтить поле (удалить все нарисованные области);
  • to html — сгенерировать и отобразить html-код карты;
  • new image — очистить поле и вернуться к выбору изображения для карты.

Многие идеи я позаимствовала у векторного редактора Inkscape, в котором часто рисую. Кстати, Inkscape использует формат SVG для сохранения изображений, да и Adobe Illustrator тоже умеет сохранять рисунок в SVG.

Что получилось в итоге

Редактор карт изображений (Summer html image map creator)
Github

Хоткеи:

F1 — отобразить справку

Загрузка изображения:

F5 — перезагрузить страницу и вновь отобразить форму для загрузки изображения

Режим рисования (прямоугольник, круг, многоугольник)

ENTER — завершить рисование многоугольника (или клик по первому хелперу)
ESC — отменить создание новой области
SHIFT — рисовать квадрат в случае прямоугольника или линию под прямым углом в случае многоугольника

Режим редактирования

DELETE — удалить выбранную область
ESC — отменить редактирование выбранной области
SHIFT — при редактировании сохранить пропорции прямоугольника
i — редактировать атрибуты(href, title, alt) выбранной области (или двойной клик на области)
— переместить выбранную область вверх
— переместить выбранную область вниз
— переместить выбранную область влево
— переместить выбранную область вправо

Автор: summerstyle

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js