如何使fabric.js输出svg包括alpha颜色?

时间:2017-06-14 00:24:11

标签: svg transparency fabricjs alpha

我需要将结构画布图的结果输出到SVG文件。

我使用的是fabric.js版本1.7.6,当我有一个路径绘制到像rgba(255,0,0,.15)这样的rgba填充的画布时,生成的SVG填充了rgb(0,0,0)。我需要启用哪些设置才能输出alpha chanel?

在我的示例代码中,紫色圆圈正确转换为SVG,但矩形只显示为黑色。

示例HTML:

<html>
  <head>
    <script src="fabric.js"></script>
  </head>
  <body>

    <div id="canvasHolder" style="border: 3px solid black;">
      <canvas id="canvasElement" width="400" height="400" />
    </div>

    <div id="svgHolder" style="border: 3px solid blue;">
    </div>
  </body>

  <script>
    var canvas = new fabric.Canvas('canvasElement');

    var rect = new fabric.Path('M,0,0,h,100,v,100,h,-100,z',{
        top:100,
        left:100,
        stroke: 'green',
        fill: 'rgba(255,0,0,.15)'
    });
    canvas.add(rect);

    var circ = new fabric.Circle({
        radius: 30,
        top:30,
        left:30,
        stroke: 'blue',
        fill: 'purple'
    });
    canvas.add(circ);

    canvas.renderAll();

    // Make an SVG object out of the fabric canvas
    var SVG = canvas.toSVG();
   document.getElementById('svgHolder').innerHTML = SVG;
  </script>

</html>

输出SVG:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400" height="400" viewBox="0 0 400 400" xml:space="preserve">
<desc>Created with Fabric.js 1.7.6</desc>
<defs>
</defs>
<path d="M 0 0 h 100 v 100 h -100 z" style="stroke: rgb(0,128,0); stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" transform="translate(150.5 150.5) translate(-50, -50) " stroke-linecap="round"></path>
</svg>

2 个答案:

答案 0 :(得分:2)

正如我在评论中所说,这看起来像一个错误,您应该报告project's issue tracker

颜色全部转换为rgb()(rgba,hsl,hsla,hex,keywords),因此不支持alpha通道......

目前,这是一个繁重的解决方法:

toSVG接受 reviver 函数,该函数将接收所有svg节点标记。从那里,您可以重新应用正确的样式,但不是那么容易。

我能找到的唯一一个允许我们识别哪个对象对应于我们获得的svg标记的参数是id

  • 首先,我们将构建一个字典,它将通过id存储我们的颜色。
  • 然后,我们将id和颜色分配给织物的对象。
  • 最后,在 reviver 中,我们将解析我们的标记以将其转换为svg节点,检查其id属性,然后更改其style.fill和{{ 1}}属性,在返回此修改节点的序列化之前。

style.stroke
var canvas = new fabric.Canvas('canvasElement');

var colors_dict = {};
// an helper function to generate and store our colors objects
function getColorId(fill, stroke) {
  var id = 'c_' + Math.random() * 10e16;
  return colors_dict[id] = {
    id: id,
    fill: fill || 'black',
    stroke: stroke || 'black' // weirdly fabric doesn't support 'none'
  }
}

// first ask for the color object of the rectangle
var rect_color = getColorId('hsla(120, 50%, 50%, .5)', 'rgba(0,0,255, .25)');
var rect = new fabric.Path('M,0,0,h,100,v,100,h,-100,z', {
  top: 60,
  left: 60,
  stroke: rect_color.stroke, // set the required stroke
  fill: rect_color.fill, // fill
  id: rect_color.id  // and most importantly, the id
});
canvas.add(rect);

var circ_color = getColorId('rgba(200, 0,200, .7)');
var circ = new fabric.Circle({
  radius: 30,
  top: 30,
  left: 30,
  stroke: circ_color.stroke,
  fill: circ_color.fill,
  id: circ_color.id
});
canvas.add(circ);

canvas.renderAll();

var parser = new DOMParser();
var serializer = new XMLSerializer();
function reviveColors(svg){
  // first we parse the markup we get, and extract the node we're interested in
  var svg_doc = parser.parseFromString('<svg xmlns="http://www.w3.org/2000/svg">' + svg + '</svg>', 'image/svg+xml');
  var svg_node = svg_doc.documentElement.firstElementChild;
  var id = svg_node.getAttribute('id');
  if (id && id in colors_dict) { // is this one of the colored nodes
    var col = colors_dict[id]; // get back our color object
    svg_node.style.fill = col.fill; // reapply the correct styles
    svg_node.style.stroke = col.stroke;
    // return the new markup
    return serializer.serializeToString(svg_node).replace('xmlns="http://www.w3.org/2000/svg', '');
  }
  return svg;
}

// Make an SVG object out of the fabric canvas
var SVG = canvas.toSVG(null, reviveColors);
document.getElementById('svgHolder').innerHTML = SVG;

答案 1 :(得分:0)

颜色转换为RGB,因为svg规格要求CSS2格式的颜色,因此不支持rgba。

cit:https://www.w3.org/TR/2008/REC-CSS2-20080411/syndata.html#value-def-color

Fabric使用fill-opacity rull实现透明度。关键是fabric.Color颜色解析器看起来像窒息了alpha通道的.15表示法。

请使用0.15,它会起作用。

我同意fabric.Color可以为此修复。