使用Shadow DOM扩充SVG​​标记

时间:2016-11-25 18:00:00

标签: javascript html5 svg web-component shadow-dom

我一直在尝试使用HTML5和SVG;我对JavaScript和Web开发都很陌生,所以我可能会缺少一些东西。我正在尝试创建可重用的Web组件,利用一些新功能,如HTML Imports,Shadow DOM和扩展现有的Web元素。我有两个html文件:

的test.html

<html>
<head>
  <title>Test HTML5</title>
</head>
<body>
  <link rel="import" href="Elements/tank.html">

  <svg width="100%"
       viewBox="0 0 500 500"
       style="border: solid; border-width: thin; stroke-width: 2;">

    <polyline points="0,300 100,300 100,100 250,100 250,150 500,150"
              style="fill:none;stroke:black;stroke-width:3"
              onclick="window.alert('you clicked line')" />
    <svg is="my-tank" x="200" y="350" width="50" height="50"></svg>

  </svg>
</body>
</html>

tank.html

<html>
<body>
  <template id="tank">
    <rect fill="red" width="50" height="50"></rect>
  </template>

  <script type="text/javascript">
    var tankElement = document.currentScript.ownerDocument.querySelector('#tank');

    document.registerElement('my-tank', {
      prototype: Object.create(SVGSVGElement.prototype, {
        createdCallback: {
          value: function () {
            var root = this.createShadowRoot();

            //Works
            root.innerHTML = tankElement.innerHTML;

            //Doesn't work
            //var tankTemplate = document.importNode(tankElement.content, true);
            //root.appendChild(tankTemplate);
          }
        }
      }),
      extends: 'svg'
    });
  </script>
</body>
</html>

//Works注释下的代码绘制了一个红色矩形,我期望在SVG可绘制空间中。 //Doesn't work下的代码不会绘制任何内容或产生任何错误。

//Works的屏幕截图:Works

//Doesn't work的屏幕截图:Doesn't work

我一直在测试Opera 41.0。

2 个答案:

答案 0 :(得分:3)

您无法执行此操作,因为svg不能是影子主机。只有有限数量的元素可以是影子主机:

articleasideblockquotebodydivfooterh1h2h3h4h5h6headermainnavp,{ {1}},section

所以不仅span,而且svginput之类的其他人也不能拥有影子(我说的是Shadow-DOM v1

有关详细信息,请参阅textarea的定义:https://dom.spec.whatwg.org/#dom-element-attachshadow

另请注意:

  • attachShadow未实施SVGSVGElement
  • 还听说过SVG已经在其实现中包含阴影dom,以及自定义元素 v1 你可能只有一个影子(见这里:http://hayato.io/2016/shadowdomv1/)。

为什么不创建一个常规的自定义元素,在其阴影中可能包含HTMLElement个元素?

答案 1 :(得分:2)

这是因为在<template>中,<rect>元素不在<svg>标记内,因此它不会被识别为SVGRectElement而是HTMLUnknownElement而不是。

要使其有效,只需添加<svg>标记:

<template id="tank">
    <svg>
        <rect fill="red" width="50" height="50"></rect>
    </svg>
</template>

现在,您可以使用importNode()cloneNode()

导入元素
//Works
var rect = tankElement.content.querySelector('rect').cloneNode();
root.appendChild(rect);

更新导入多个SVG元素

将元素放入<g>

<template id="tank">
    <svg>
        <g>
            <rect fill="red" width="50" height="50"></rect>
            <rect fill="blue" width="25" height="50"></rect>
        </g>
    </svg>
</template>

克隆<g>及其内容:

var g = tankElement.content.querySelector('g').cloneNode(true);
root.appendChild(g);