Я работаю над приложением, которое использует Raphael для рисования примитивных фигур (прямоугольников, эллипсов, треугольников и т.д.) и линий, но позволяет пользователь может перемещать/изменять размер этих объектов. Одним из основных требований является то, что лицо форм может иметь форматированный текст. Фактический текст - это подмножество Markdown (простые вещи, такие как жирный шрифт, курсив, списки) и отображается как HTML.
FWIW - Я использую Backbone.js для модуляции логики формы.
Подход 1
Моя первоначальная мысль заключалась в использовании комбинации foreignObject
для SVG и прямого HTML с VML для IE. Однако IE9 не поддерживает foreignObject
, и поэтому этот подход пришлось отказаться.
Подход 2
Рядом с объектом canvas добавьте div
, который содержит фактический HTML. Затем поместите их поверх фактической фигуры с прозрачным фоном. Я создал представление формы, которое имеет ссылки как на фактическую форму Рафаэля, так и на "наложение" div
. Существует несколько проблем с этим подходом:
-
Использование оверлей, которые не являются дочерними элементами контейнера SVG/VML, кажется неправильным. Имеет ли этот элемент оверлея другие проблемы при рендеринге по дороге?
-
События, которые обычно захватываются Рафаэлем (перетаскивание, клик и т.д.), необходимо перенаправить из оверлея в объект Рафаэля. Для браузеров, поддерживающих
pointer-events
, это легко сделать:div.shape-text-overlay { position: absolute; background: none; pointer-events: none; }
Однако другие браузеры (например, IE8 и ниже) нуждаются в пересылке событий:
var forwardedEvents = 'mousemove mousedown mouseup click dblclick mouseover mouseout'; this.$elText.on(forwardedEvents, function(e) { var original = e.originalEvent; var event; if (document.createEvent) { event = document.createEvent('HTMLEvents'); event.initEvent(e.type, true, true); } else { event = document.createEventObject(); event.eventType = e.type; } // FYI - This is the most simplistic approach to event forwarding. // My real implementation is much larger and uses MouseEvents and UIEvents separately. event.eventName = e.type; _.extend(event, original); if (document.createEvent) { that.el.node.dispatchEvent(event); } else { that.el.node.fireEvent('on' + event.eventType, event); } });
-
Перекрывающиеся фигуры заставляют текст перекрываться, потому что текст/фигуры находятся на разных уровнях. Хотя перекрывающиеся формы не будут распространены, это выглядит плохо:
Этот подход - это то, что я сейчас использую, но он просто чувствует себя как огромный хак.
Подход 3
Почти как Подход 1, но это касается непосредственного ввода текстовых узлов/узлов VML. Самая большая проблема с этим - это необходимое количество ручного преобразования. Нарушение API Raphael кажется, что это может вызвать проблемы стабильности с другими объектами Рафаэля.
Вопрос
Кто-нибудь еще должен был сделать что-то подобное (визуализация HTML внутри SVG/VML)? Если да, то как вы решили эту проблему? Учитывались ли события?