Идеи для рендеринга HTML *внутри* форм Raphael (SVG/VML)

Я работаю над приложением, которое использует Raphaelдля рисования примитивных фигур (прямоугольников, эллипсов, треугольников и т. д.) и линий, но позволяет пользователю перемещать/изменять размер этих объектов. также. Одним из основных требований является то, что на лицевой стороне фигур может быть форматированный текст. Фактический текст является подмножеством Markdown (простые элементы, такие как жирный шрифт, курсив, списки) и отображается как HTML.

FWIW. Я использую представления Backbone.js для модуляции логики формы.

Подход 1

Сначала я подумал использовать комбинациюForeignObjectдля SVGи прямого HTML с VML для IE. Однако IE9 не поддерживает foreignObject, поэтому от этого подхода пришлось отказаться.

Подход 2

К объекту рядом с холстом добавьте divs, которые содержат фактический HTML. Затем поместите их поверх фактической формы с прозрачным фоном. Я создал представление формы, в котором есть ссылки как на фактическую форму Рафаэля, так и на «наложение» div. У этого подхода есть несколько проблем:

  1. Использование оверлеев, которые не являются потомками контейнера SVG/VML , кажетсянеправильным.Вызывает ли наличие этого элемента наложения другие проблемы с рендерингом в будущем?

  2. События, которые обычно перехватываются Raphael (перетаскивание, щелчок и т. д.), необходимо пересылать из оверлея в объект Raphael. Для браузеров, поддерживающих pointer-events, это легко сделать:

    div.shape-text-overlay {
    положение: абсолютное;
    фон: нет;
    события-указатели: нет;
    }
    

    Однако другим браузерам (например, IE8 и ниже) требуется пересылка событий:

    var forwardedEvents = 'mousemove mousedown mouseup click dblclick mouseover mouseout';
    this.$elText.on(forwardedEvents, function(e) {
    
    var original = e.originalEvent;
    
    переменное событие;
    если (document.createEvent) {
    событие = документ.createEvent('HTMLEvents');
    event.initEvent(e.type, правда, правда);
     }
    еще {
    событие = документ.createEventObject();
    event.eventType = e.type;
     }
    
     // К сведению. Это самый упрощенный подход к пересылке событий.
     // Моя реальная реализация намного больше и использует MouseEvents и UIEvents отдельно.
    
    событие.eventName = e.type;
     _.extend(событие, оригинал);
    
    если (document.createEvent) {
    что.el.node.dispatchEvent(событие);
     }
    еще {
    that.el.node.fireEvent('on' + event.eventType, событие);
     }
    
    });
    
  3. Перекрывающиеся фигуры приводят к перекрытию текста, поскольку текст/фигуры находятся на разных слоях. Хотя перекрывающиеся формы не будут обычным явлением, это выглядит плохо:

    overlap

Этот подход — то, что я сейчас использую, но он просто кажетсяогромным хаком.

Подход 3

Почти такой же, как и Подход 1, но он предполагает непосредственное написание текстовых узлов/узлов VML.Самая большая проблема с этим - количество необходимых ручных преобразований. Похоже, что выход за пределы API Raphael можетвызвать проблемы со стабильностью других объектов Raphael.

Вопрос

Приходилось ли кому-нибудь еще делать что-то подобное (рендеринг HTML внутри SVG/VML)? Если да, то как вы решили эту проблему? Были ли учтены события?

15
задан TheCloudlessSky 10 May 2012 в 11:43
поделиться