在*Raphael(SVG/VML)形状内呈现HTML*的想法

The*_*Sky 15 javascript raphael

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

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

方法1

我最初的想法是使用foreignObjectSVG和直接HTML与VML for IE的组合.但是,IE9不支持foreignObject,因此必须放弃这种方法.

方法2

使用canvas对象旁边,添加div包含实际HTML的s.然后,将它们放在具有透明背景的实际形状上.我创建了一个形状视图,它引用了拉斐尔的实际形状和"叠加" div.这种方法存在一些问题:

  1. 使用不是SVG/VML容器子代的叠加感觉不对.这个叠加元素会导致其他问题吗?

  2. 通常被Raphael困住的事件(拖动,点击等)需要从叠加层转发到Raphael对象.对于支持的浏览器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. 重叠的形状会导致文本重叠,因为文本/形状位于不同的图层上.虽然重叠的形状不常见,但这看起来很糟糕:

    交叠

这种方法是我目前使用的方法,但它只是感觉像一个巨大的黑客.

方法3

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

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

The*_*Sky 0

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