Учебное пособие по тексту SVG: текстовые аннотации в Интернете

Опубликовано: 2022-03-11

С HTML5 и CSS3 веб-браузеры приобрели ряд удивительных технологий: 3D-графику, сокеты, потоки и многое другое. С их помощью веб-приложения могут использовать некоторые из самых сложных возможностей компьютеров и операционных систем, на которых они используются. Веб-браузер предлагает надежную универсальную экосистему для разработки приложений, о чем свидетельствует недавнее появление множества мощных веб-приложений, без которых мы не можем жить. Однако чего-то еще не хватает, так это красоты текстовых аннотаций и оформления HTML. Что такое оформление текста? Волнистые подчеркивания, неровные выделения и волнистые зачеркивания — вот некоторые из вещей, которые веб-браузеры не обеспечивают нативной поддержкой. Это может показаться более сложным, чем полезным, но возможность разработчиков JavaScript создавать эти стили может оказаться полезной в таких аспектах, как ресурсы для электронного обучения и веб-читатели электронных книг. Более того, это может способствовать улучшению пользовательского опыта в веб-приложениях, основанных на принципах естественного дизайна. По крайней мере, создание такого инструмента доставляет удовольствие и дает представление о многих причудах веб-браузера.

Учебное пособие по тексту SVG - текстовая аннотация

Разработчики нашли множество обходных путей для ограничения веб-браузера. Многие из этих обходных путей включают использование CSS менее интуитивными способами, поскольку некоторые используют изображения в псевдоэлементах «::after». Это работает, но поддержка множества изображений для каждой пары стиль-цвет часто оказывается сложной задачей. В этой статье рассматривается анатомия библиотеки JavaScript, которая пытается изящно решить эту проблему.

Библиотека с открытым исходным кодом доступна на GitHub: Text Annotator.

Обзор

При разработке этой библиотеки особое внимание уделялось обеспечению совместимости с наиболее популярными веб-браузерами (включая IE 9+). Однако, в отличие от того, как большинство решает эту проблему, библиотека не полагается на особо непонятные приемы CSS; или, что еще хуже, специальные символы Unicode. Вместо этого он использует SVG для более качественного и чистого оформления текста.

По сути, библиотека реализует «класс» Annotator, который можно использовать для автоматического создания элементов DIV, размещения их под комментируемым текстом и заполнения их фона изображениями SVG. Несколько DIV можно комбинировать для дальнейшей настройки оформления. Этот подход совместим с разными браузерами, обеспечивает гибкость при размещении декоративных элементов и упрощает расширение с помощью пользовательских шаблонов.

Библиотека была разработана с использованием Google Closure Tools, поскольку она является модульной и кросс-браузерной, что помогает создавать компактный и быстрый код JavaScript без каких-либо дополнительных зависимостей.

Архитектура

Библиотека была разработана как набор «классов» JavaScript и предоставляет пользователю все необходимые функции через аннотатор «класса»:

библиотека текстовых аннотаторов

Вот краткий обзор доступных функций:

  • annotateDocument — аннотирует элементы, отмеченные атрибутом «data-annotate».

  • underline - подчеркивает элемент

  • highlight - выделяет элемент

  • strike - элемент удара

  • underlineSelected — подчеркивает выделенный текст

  • highlightSelected — выделяет выделенный текст

  • strikeSelected — зачеркивает выделенный текст

  • unannotateElement — удаляет аннотацию из элемента

  • getTemplates — возвращает словарь шаблонов аннотаций

  • setUnderlineOptions — устанавливает настройки для подчеркивания аннотатора

  • setHighlightOptions — устанавливает настройки для выделения аннотатора

  • setStrikeOptions - устанавливает настройки для аннотатора ударов

Класс аннотатора содержит три экземпляра класса AnnotatorImpl для каждой функции аннотирования: подчеркивания, выделения и зачеркивания.

 tvs.Annotator = function() { this.underliner_ = new tvs.AnnotatorImpl( 'underliner', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.underlinePositioner); this.highlighter_ = new tvs.AnnotatorImpl( 'highlighter', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.highlightPositioner, {opacity: 0.45}); this.striker_ = new tvs.AnnotatorImpl( 'striker', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.strikePositioner); };

Экземпляры AnnotatorImpl создаются с разными идентификаторами и вспомогательными объектами позиционера. Переданные идентификаторы используются позже в именах классов CSS и именах внутренних полей, требуя, чтобы идентификаторы были уникальными. Также передается ссылка на список известных шаблонов (может быть изменена позже).

Каждый объект позиционера является реализацией интерфейса IPositioner, который имеет только метод «getPosition» и выглядит следующим образом:

 /** * Underline positioner * @implements {tvs.IPositioner} */ tvs.AnnotatorCore.underlinePositioner = /** @type {!tvs.IPositioner} */ ({ /** * @param {Object} elementRect * @param {number} annotationHeight * @return {{left: number, top: number, width: number, height: number}} */ getPosition: function(elementRect, annotationHeight) { return { width: elementRect.width, height: annotationHeight, left: elementRect.left, top: elementRect.bottom - (elementRect.height * 0.1) }; } });

Это позволяет использовать каждый шаблон с подчеркиванием, выделением или зачеркиванием текста. Когда аннотация применяется к элементу, ограничивающая рамка для элемента получается путем вызова «getElementRects», как показано ниже:

 var rects = elemOrEv.getClientRects();

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

Шаблоны текстовых аннотаций SVG

Как упоминалось ранее, существует только один набор шаблонов, которые используются для всех видов текстовых аннотаций SVG. Каждый шаблон состоит из частей шаблона. Часть шаблона — это объект, который представляет содержимое части, ширину шаблона и режим рисования.

Содержание

Контент — это набор элементов SVG, представленных в виде строки. Поскольку этот контент не имеет корневого узла SVG, в котором задаются ширина и высота окна просмотра (в пикселях), конструктор части шаблона принимает их в качестве параметров. Например, вы можете указать размер области просмотра 100 x 100 пикселей и нарисовать линию (50, 50) и (25, 25). После применения аннотации все элементы svg будут иметь нужный размер. Значение содержимого может использовать строку «{0}», которая будет заменена цветом, выбранным пользователем.

Следующий SVG отображает диагональную линию. Мы будем использовать это как одну из частей в следующем примере стиля аннотации:

 <line x1="0" y1="0" x2="5" y2="5" stroke-width="2" stroke="red" />

Ширина

Ширина шаблона — это строка, которая может быть «*», «высота» или что-то еще:

  • «*» устанавливает ширину всех элементов со звездочкой, равную друг другу

  • «height» устанавливает ширину, равную высоте элемента аннотации.

Все остальное, установленное здесь, будет напрямую установлено в свойства CSS width и min-width.

CSS-свойства

Режим рисования

Режим рисования — это строка, которая может быть либо «повторной», либо «растянутой». Как показывают значения, при установке значения «repeat» содержимое повторяется, а при установке значения «stretch» ​​содержимое растягивается.

Вот пример того, чего мы можем добиться, настроив эти три параметра:

текстовая аннотация

Текстовая аннотация в приведенном выше примере состоит из 4 частей. Первая часть представляет собой диагональную линию с шириной шаблона, установленной на «высоту», и режимом рисования, установленным на «повторить». Вторая часть имеет ширину шаблона, установленную на «*», и режим рисования, установленный на «повторить». Третья часть имеет ширину «15 пикселей» и рисуется в режиме «повторения». Наконец, ширина последней части установлена ​​​​на «*», а режим ее рисования установлен на «растяжение».

При оценке этих значений ширины первая часть занимает 5 пикселей (равных высоте элемента аннотации), третья часть занимает 15 пикселей (как задано), а оставшееся пространство поровну делится между второй и четвертой частями.

Когда один и тот же фрагмент текста выделяется с помощью одного и того же шаблона, мы получаем следующее:

режим рисования

Как вы можете видеть, высота элемента аннотации больше, как и ширина первой части (поскольку ширина шаблона для этой части установлена ​​​​на «высота»). Естественно, ширина третьей части осталась неизменной по сравнению с предыдущим примером.

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

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

Несмотря на то, что эти текстовые аннотации кажутся сложными (то, как они выглядят, состоят из четырех отдельных частей), все они используют очень простые элементы SVG. В качестве дополнительного примера, для создания волнистой линии требуется одна часть со следующим простым содержимым SVG:

 var t = new tvs.Template(new tvs.SvgTemplatePart( '<line y2="16.00" x2="20" y1="4.00" ' + 'x1="10" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>' + '<line y2="4.00" x2="10" y1="16.00" ' + 'x1="0" stroke-linecap="round" ' + 'stroke-width="5" stroke="{0}" fill="none"/>', 20, 20, 'repeat' ))

При оценке этих шаблонов размер содержимого изменяется, и «{0}» автоматически заменяется указанным цветом. Более того, добавить новые шаблоны так же просто, как добавить их в объект JavaScript:

 tvs.AnnotatorDictionary.svgTemplates['brush'] = new tvs.Template(new tvs.SvgTemplatePart( svgContent, 50, 50, '*', 'stretch' ));

Результаты

Каждая аннотация применяется путем добавления элемента div с абсолютным позиционированием на страницу:

 <div class="tvs-annotate-element"> <div class="tvs-wrap-div"> <table> <tr> <td></td> <td></td> <td></td> </tr> </table> </div> </div>

Элемент div заполняется таблицей, в которой каждая добавленная ячейка соответствует одной из частей шаблона. Содержимое каждой части шаблона добавляется в виде URI данных в кодировке Base64 с применением выбранного цвета:

 tvs.SvgTemplatePart.prototype.getBackground = function(color) { var image = tvs.AnnotatorCore.formatString(this.content, [color]); var encodedSVG = goog.crypt.base64.encodeString(image); return 'data:image/svg+xml;base64,' + encodedSVG; };

Встраивание

Для лучшего взаимодействия с пользователем, особенно при попытке использовать эту библиотеку JavaScript с редактируемыми областями содержимого, важно, чтобы текстовый аннотатор знал границы текста, выделенного в данный момент пользователем. Rangy, аккуратная библиотека JavaScript, работающая с диапазоном и выбором, была использована для достижения этой цели в кросс-браузерной манере. Rangy предоставляет простой основанный на стандартах API для выполнения общих задач DOM Range и Selection во всех основных браузерах, абстрагируя сильно отличающиеся реализации этой функциональности от Internet Explorer до браузеров, совместимых с DOM. Это единственная зависимость проекта.

После того, как Text Annotator встроен, использовать его очень просто:

 var annotator = new tvs.Annotator(); annotator.underlineSelected();

Каждый аннотированный элемент помечен классом «tvs-annotated-text», а каждый элемент аннотации имеет класс «tvs-annotate-element». Удаление аннотаций еще проще, однострочным:

 annotator.unannotateElement(annotatedElement);

причуды

При изменении размера окна элементы могут перемещаться, что требует «обновления» аннотированных элементов. Этим занимается библиотека. Однако; чтобы уменьшить влияние на производительность, вызов обновления аннотаций регулируется:

 tvs.AnnotatorImpl = function(id, templates, positioner, options) { // ... this.throttle = new goog.Throttle(goog.bind(this.refreshAllAnnotations, this), 50); tvs.AnnotatorCore.registerForWindowResize( this.id,goog.bind(this.throttle.fire, this.throttle)); }; tvs.AnnotatorImpl.prototype.refreshAllAnnotations = function() { var elems = goog.dom.getElementsByClass(this.getCssClassForAnnotated()); var refFunc = goog.bind(this.refreshAnnotation, this); goog.array.forEach(elems, refFunc); };

После обновления элементы аннотации могут быть добавлены, изменены в размере или удалены со страницы по мере необходимости.

Удобство

Чтобы упростить аннотирование статического текста на странице, достаточно простого атрибута данных в элементе-контейнере:

 data-annotate='underline squiggly green'

Это аннотирует содержимое элемента волнистой зеленой линией.

Заключение

Что еще я могу сказать об этом текстовом руководстве по SVG? Забавный, но мощный инструмент был легко реализован. Я не думаю, что мы выиграем, обеспечив поддержку Internet Explorer 8, поскольку вместо этого мы можем усложнить всю реализацию. Однако с некоторыми улучшениями и небольшой работой над ядром мы можем расширить библиотеку, чтобы иметь возможность создавать декоративные рамки для нетекстовых элементов. Кроме того, может оказаться интересной задача реализовать какой-либо механизм для сохранения и последующего восстановления состояния редактируемого содержимого аннотации.

На данный момент возможности ограничены только вашим воображением (и возможностями браузера). Возможно, вам нужны линии микропечати, или градиенты, или даже анимация. С Text Annotator вы можете.