【问题标题】:Canvas in foreign object of svg doesn't apply the transformationsvg 异物中的画布不应用转换
【发布时间】:2018-06-01 18:09:55
【问题描述】:

我在 svg 中使用画布时遇到问题,使用 foreignObject。

问题是画布被插入到一个组中,该组具有变换(平移或旋转或缩放),但画布没有打印变换。

我在 Chrome 上。

你可以在那里看到我的例子:

https://jsfiddle.net/Surre/qjrvxgos/

<body>
  <svg width="400px" height="300px" viewBox="0 0 400 300"
       xmlns="http://www.w3.org2000/svg">
       <g transform='translate(250,10)rotate(40)'>
         <foreignObject height="700" width="370" y="0" x="0">
             <span xmlns="http://www.w3.org/1999/xhtml">
             <canvas id="canvas" width="400px" height="300px" fill-style="#FF0000"></canvas>
             <div>Comment</div>
             </span>
         </foreignObject>
       </g>
  </svg>
</body>

“评论”有很好的转换,但画布没有。 但是,如果您使用开发工具并检查元素画布,您会发现他在转换中处于有利位置。

希望你能帮助我。

谢谢

【问题讨论】:

  • 抱歉,我更正了
  • 大概是一个 Chrome 错误,为什么不向他们的 bugtracker 报告呢?
  • 问题:为什么要在 SVG 中使用画布元素?这看起来像 HTML5 页面中使用的 SVG,所以这里应该做一些事情: 1) svg 是 HTML5 的一部分,正式地,所以没有 XML 命名空间。 2) 所有其他元素都相同:没有命名空间。 3) 为什么不把画布放在页面本身而不是 SVG 内部?你在这里具体想做什么,因为这只是一个网页,看起来你正在使用 SVG 来做 CSS 已经可以做的事情。
  • @Mike'Pomax'Kamermans 只有 SVGRoot 节点在 html 命名空间中,它的所有子节点都在 svg 中。包含在不属于 svg 命名空间的 foreignObject 中的元素需要声明自己的命名空间,至少在所有第一个父节点上。但是 svg root 的 xmlns 声明有错字,这会导致 chrome 的错误行为吗?我会对此感到惊讶,但如果设置,OP 应该正确设置它。
  • 不,你没有抓住重点。 SVG HTML5,HTML5 中没有“命名空间”,&lt;svg&gt; 元素是像 &lt;p&gt;&lt;div&gt; 这样的一等公民,并且 not 需要命名空间,您只需像使用任何其他 HTML 元素一样使用它。这也意味着您不会为&lt;span&gt; 之类的东西“转义” SVG 命名空间。 all 只是 HTML 元素。

标签: javascript html canvas svg transformation


【解决方案1】:

据我了解,这实际上是自 2015 年以来已知的 chrome 中的一个错误 https://bugs.chromium.org/p/chromium/issues/detail?id=467484 正在讨论修复它

不过,我也需要一个解决方案,所以这就是我整理的;我将图像元素(在 svg 中运行良好)与隐藏的画布结合使用。系统将它喜欢的所有内容绘制到画布上,然后将画布数据传输到图像元素。

imageElement.setAttribute('href',hiddenCanvas.toDataURL("image/png"));

这是一个额外的步骤,但它产生的结果基本相同。在我的项目中,我将所有这些都捆绑到了一个 JS 元素生成器中

this.canvas = function(id=null, x=0, y=0, width=0, height=0, angle=0, res=1){
    var canvas = document.createElement('canvas');
        canvas.setAttribute('height',res*height);
        canvas.setAttribute('width',res*width);

    var image = document.createElementNS('http://www.w3.org/2000/svg','image');
        image.id = id;
        image.style = 'transform: translate('+x+'px,'+y+'px) scale('+1/res+') rotate('+angle+'rad)';
        image.setAttribute('height',height*res);
        image.setAttribute('width',width*res);

    return {
        element:image,
        canvas:canvas,
        context:canvas.getContext("2d"),
        c:function(a){return a*res;},
        print:function(){
            this.element.setAttribute('href',this.canvas.toDataURL("image/png"));
        }
    };
};

这有点笨重,但我认为这是你需要的。它还使用“res”参数和“c”函数(您可以与任何画布绘图函数一起使用)处理分辨率

canvas.context.fillRect(canvas.c(0), canvas.c(0), canvas.c(width), canvas.c(height));

【讨论】:

    【解决方案2】:

    我认为您既不旋转也不变换画布。如果你想旋转/变换它,你可以使用 CSS 样式。请参阅下面的代码。

    .transform {
        -ms-transform:translateX(200px) rotate(40deg) translateY(130px); /* IE 9 */
        -webkit-transform:translateX(200px) rotate(40deg) translateY(130px); /* Chrome, Safari, Opera */
        transform:translateX(200px) rotate(40deg) translateY(130px);
        background:#FF0000;
    }
    

    此 css 代码适用于大多数浏览器。您可以在示例中使用此类,如下所示。

    <canvas id="canvas" width="400px" height="300px"  class="transform"></canvas>
    

    您可以在 https://jsfiddle.net/qjrvxgos/3/ 上看到您的示例以及我的更新。

    【讨论】:

    • 我把画布放在组中,它有一个变换并希望它跟随,就像组中的其他对象一样。当您打开开发工具并检查画布元素时,您会发现画布不是工具显示的位置。工具显示它按应有的方式平移和旋转。
    • 它是一组必须应用一些转换的对象的成员,这就是为什么我更愿意避免只为它使用 css。
    【解决方案3】:

    Canvas 和 SVG 是不同的库,不能一起使用。您可以将一个转换为另一个以执行您需要的操作。看看下面的链接可能对你有帮助http://www.inkfood.com/svg-to-canvas/你也可以像下面的例子一样做你的例子

    <svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
    <g transform='translate(250,10)rotate(40)'>
     <rect x="10" y="20" height="50" width="75"
          style="stroke: #ffff00; fill: #ff0000"/>
        <text x="10" y="90" style="stroke: #660000; fill: #ff0000">
        Comment</text>
    </g>
    

    【讨论】:

    • 感谢您的链接,它可能会有所帮助。但在正常情况下,我们可以在 svg 中使用带有异物的画布。但是如何处理我提到的这个错误呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 2013-06-09
    相关资源
    最近更新 更多