【问题标题】:Ideas for rendering HTML *within* Raphael (SVG/VML) shapes渲染 HTML *within* Raphael (SVG/VML) 形状的想法
【发布时间】:2012-05-17 23:30:36
【问题描述】:

我正在开发一个使用Raphael 绘制原始形状(矩形、椭圆、三角形等)和线条的应用程序,但也允许用户移动/调整这些对象的大小。主要要求之一是形状的表面可以有格式化的文本。实际文本是 Markdown 的子集(简单的东西,如粗体、斜体、列表)并呈现为 HTML。

FWIW - 我正在使用 Backbone.js 视图来模块化形状逻辑。

方法 1

我最初的想法是结合使用foreignObject for SVG 和直接HTML 与VML for IE。但是,IE9 doesn't support foreignObject,因此不得不放弃这种方法。

方法2

在画布对象旁边,添加包含实际 HTML 的 divs。然后,将它们放置在具有透明背景的实际形状上。我创建了一个形状视图,它引用了实际的 Raphael 形状和“覆盖”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){ 事件 = 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); } });
  3. 重叠的形状会导致文本重叠,因为文本/形状位于不同的图层上。虽然重叠的形状并不常见,但这看起来很糟糕:

我目前正在使用这种方法,但它感觉就像一个巨大的黑客攻击。

方法 3

几乎类似于方法 1,但这将涉及直接编写文本节点/VML 节点。最大的问题是所需的手动转换量。突破 Raphael 的 API 似乎可能会导致其他 Raphael 对象出现稳定性问题。

问题

有没有其他人不得不做类似的事情(在 SVG/VML 中渲染 HTML)?如果是这样,你是如何解决这个问题的?是否考虑了事件?

【问题讨论】:

    标签: javascript raphael


    【解决方案1】:

    我使用 Raphael 构建了 this project (不再存在)。我所做的实际上是放弃了在 SVG 中使用 HTML 的想法,因为它太乱了。相反,我绝对在 SVG 层之上放置了一个 HTML 层,并将它们一起移动。当我想要显示 HTML 时,我只是将其淡入并淡出相应的 SVG 对象。如果时间和排列正确,未经训练的人不会真正注意到它。

    虽然这不一定是您想要的,但也许它会让您思考解决问题的新方法!随意查看该页面上的 JS,因为它是未缩小的;)

    PS,该项目是一个潜在客户收集应用程序。如果您只是想看看它是如何工作的,请在第一个下拉菜单中选择“朋友”,您无需提供任何信息。

    【讨论】:

    • 漂亮的网站。您的方法几乎就是我现在为#2 所做的。 对我来说的“坏”之处在于,如果用户将两个形状重叠在一起,您会得到重叠,正如我在 OP 中展示的那样。另一个问题是需要将事件从覆盖元素转发到 Raphael 对象。但是感谢您展示这一点,因为它准确地显示了我前进的道路。
    • 是的,我认为它与您的 #2 相似。我不必担心碰撞或事件会被传递回 SVG,但您可以通过弄乱z-index 并在您的 html 元素上放置背景颜色(可能与相应的 SVG 对象相同)来避免重叠,如果那行得通。当然,我对您的项目了解不多,但鉴于提供的信息,这就是我将如何处理它:)
    【解决方案2】:

    除非可以提供另一个答案并且胜过我的解决方案,否则我会继续使用额外的 div 层。转发事件是最困难的部分(如果有人需要转发事件代码,我可以在这里发布)。同样,此解决方案的最大缺点是重叠的形状会导致它们的文本与实际绘制的形状重叠之上。

    【讨论】:

      猜你喜欢
      • 2012-03-30
      • 2013-02-15
      • 2012-04-24
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 2011-08-18
      • 2011-11-09
      • 2011-09-13
      相关资源
      最近更新 更多