将canvas转换为svg时只需要裁剪内容

时间:2017-10-06 10:18:38

标签: javascript html5 canvas svg fabricjs

我正在使用HTML5 CANVAS和fabric js。最后将它转换为SVG.we可以上传图像并裁剪成圆形,矩形,...。图像也被裁剪并在其上添加文字。我面临的问题是图像没有被裁剪成svg.It显示如下图所示的完整图片。我也在viewBox中尝试toSVG。请建议我做什么或者我做错了什么。



$(function(){
var canvas = new fabric.Canvas('Canvas',{backgroundColor: '#ffffff',preserveObjectStacking: true});
canvas.clipTo = function (ctx) {
ctx.arc(250, 300, 200, 0, Math.PI*2, true);
};

fabric.Image.fromURL('https://fabric-canvas.s3.amazonaws.com/Tulips.jpg', function(oImg) {
              canvas.add(oImg);
            });       
            
canvas.add(new fabric.IText('Welcome ', {
              left : fabric.util.getRandomInt(50,50),
              top:fabric.util.getRandomInt(430, 430)
              }));
              
       
            canvas.renderAll();
            

$('#tosvg_').on('click',function(){
$('#svgcontent').html(canvas.toSVG());
});
            
});
            
            

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.18/fabric.js"></script>

<div class="container">
    <div id='canvascontain' width='1140' height='600' style='left:0px;background-color:rgb(240,240,240)'>
    <canvas id="Canvas" width='1140' height='600'></canvas>
    </div>
    
    <input type='button' id='tosvg_' value='create SVG'>
    <div id='svgcontent'></div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

我查看了结构文档,找不到任何方法将画布的clipTo属性传递给生成的SVG。所以我认为将SVG图像裁剪成圆形的最佳(唯一)方法是在其中插入一些额外的SVG元素。我不是一块一块地解释,而是粘贴一些我想出的注释JS代码。

$(function(){
  var canvas = new fabric.Canvas('Canvas',{backgroundColor: '#ffffff',preserveObjectStacking: true});
  canvas.clipTo = function (ctx) {
    ctx.arc(250, 300, 200, 0, Math.PI*2, true);
  };
  
  // Using a JQuery deferred object as a promise.  This is used to
  // synchronize execution, so that the SVG is never created before
  // the image is added to the canvas.
  var dImageLoaded = $.Deferred();
  
  fabric.Image.fromURL('https://fabric-canvas.s3.amazonaws.com/Tulips.jpg', function(oImg) {
    // Insert the image object below any existing objects, so that
    // they appear on top of it.  Then resolve the deferred.
    canvas.insertAt(oImg, 0);
    dImageLoaded.resolve();
  });
  
  canvas.add(new fabric.IText('Welcome ', {
    left : fabric.util.getRandomInt(50,50),
    top:fabric.util.getRandomInt(430, 430)
  }));
  
  canvas.renderAll();
  
  
  $('#tosvg_').on('click',function(){
    // Wait for the deferred to be resolved.
    dImageLoaded.then(function () {
      // Get the SVG string from the canvas.
      var svgString = canvas.toSVG({
        viewBox: {
          x: 50,
          y: 100,
          width: 400,
          height: 400,
        },
        width: 400,
        height: 400,
      });
      
      // SVG content is not HTML, nor even standard XML, so doing
      // $(svgString) might mutilate it.  Therefore, even though we
      // will be modifying the SVG before displaying it, we need to
      // insert it straight into the DOM before we can get a JQuery
      // selector to it.
      
      // The plan is to hide the svgcontent div, append the SVG,
      // modify it, and then show the svcontent div, to prevent the
      // user from seeing half-baked SVG.
      var $svgcontent = $('#svgcontent').hide().html(svgString);
      var $svg = $svgcontent.find('svg');
      
      // Create some SVG elements to represent the clip path, and
      // append them to $svg.  To create SVG elements, we need to use
      // document.createElementNS, not document.createElement, which
      // is also what $('<clipPath>') and $('<circle>') would call.
      var $clipPath = $(document.createElementNS('http://www.w3.org/2000/svg', 'clipPath'))
          .attr('id', 'clipCircle')
          .appendTo($svg);
      var $circle = $(document.createElementNS('http://www.w3.org/2000/svg', 'circle'))
          .attr('r', 200)
          .attr('cx', 250)
          .attr('cy', 300)
          .appendTo($clipPath);
      
      // This part is brittle, since it blindly writes to the
      // transform attributes of the image and text SVG elements.
      
      // SVG clip paths clip content relative to the pre-transformed
      // coordinates of the element.  The canvas.toSVG method places
      // the image and the text each inside of group elements, and
      // transforms the group elements.  It does not transform the
      // image and text.  Because transforms work equally well on
      // image and text as on groups, we move the transform attribute
      // from the two groups to their contents.  Then, we can use the
      // same clip-path on all groups.
      
      // If the contents of the groups already had transforms, we
      // would need to create multiple clip paths - one for each group
      // - based on the groups' transforms.
      $svg.find('g').each(function () {
        var $g = $(this);
        // Move transform attribute from group to its children, and
        // give the group a clip-path attribute.
        $g.children().attr('transform', $g.attr('transform'));
        $g.removeAttr('transform').attr('clip-path', 'url(#clipCircle)');
      });
      $('#svgcontent').show();
    });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.18/fabric.js"></script>

<div class="container">
    <div id='canvascontain' width='1140' height='600' style='left:0px;background-color:rgb(240,240,240)'>
    <canvas id="Canvas" width='1140' height='600'></canvas>
    </div>
    
    <input type='button' id='tosvg_' value='create SVG'>
    <div id='svgcontent'></div>
</div>

我注意到欢迎文字的一部分会被剪裁,但我会留给你移动它。