我正在开发一个使用Raphael绘制原始形状(矩形、椭圆、三角形等)和线条的应用程序,但也允许用户移动/调整这些对象的大小。主要要求之一是形状的表面可以有格式化的文本。实际文本是 Markdown 的子集(简单的东西,如粗体、斜体、列表)并呈现为 HTML。
FWIW - 我正在使用 Backbone.js 视图来模块化形状逻辑。
方法一
我最初的想法是使用foreignObject
SVG和直接 HTML 与 IE 的 VML 的组合。但是,IE9 不支持foreignObject
,因此不得不放弃这种方法。
方法二
在 canvas 对象旁边,添加div
包含实际 HTML 的 s。然后,将它们放置在具有透明背景的实际形状上。我创建了一个形状视图,其中引用了实际的 Raphael 形状和“叠加层” div
。这种方法有几个问题:
使用不是 SVG/VML 容器子级的叠加层感觉不对。拥有此覆盖元素是否会导致其他渲染问题?
通常被 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){ 事件 = document.createEvent('HTMLEvents'); event.initEvent(e.type, true, true); } 别的 { 事件 = document.createEventObject(); event.eventType = e.type; } // 仅供参考 - 这是最简单的事件转发方法。 // 我真正的实现要大得多,并且分别使用 MouseEvents 和 UIEvents。 event.eventName = e.type; _.extend(事件,原始); 如果(document.createEvent){ that.el.node.dispatchEvent(event); } 别的 { that.el.node.fireEvent('on' + event.eventType, event); } });
重叠的形状会导致文本重叠,因为文本/形状位于不同的图层上。虽然重叠的形状并不常见,但这看起来很糟糕:
这种方法是我目前正在使用的,但感觉就像一个巨大的 hack。
方法 3
几乎类似于方法 1,但这将涉及直接编写文本节点/VML 节点。最大的问题是所需的手动转换量。打破 Raphael 的 API 似乎可能会导致其他 Raphael 对象的稳定性问题。
问题
有没有其他人必须做类似的事情(在 SVG/VML 中渲染 HTML)?如果是这样,你是如何解决这个问题的?是否考虑了事件?