如何使用KineticJS在现有形状内创建透明形状

时间:2013-06-05 19:55:23

标签: javascript kineticjs

是否有一种简单的方法可以使用KineticJS从另一个形状(或层)中“标记”透明部分?

例如,使用以下代码:

var stage = new Kinetic.Stage({
    container: 'canvas',
    width: 100,
    height: 100
});

var layer = new Kinetic.Layer();

var rect = new Kinetic.Rect({
    x: 1,
    y: 1,
    width: 96,
    height: 96,
    fill: 'green',
    stroke: 'black',
    strokeWidth: 2
});

layer.add(rect);

var star = new Kinetic.Star({
    x: stage.getWidth() / 2,
    y: stage.getHeight() / 2,
    numPoints: 5,
    innerRadius: 15,
    outerRadius: 40,
    fill: 'yellow'
});

layer.add(star);

stage.add(layer);

如何使绿色框内的星形透明,以便画布后面的元素可见。这是一个小例子:http://jsfiddle.net/ZPVxa/

我已经查看了过滤器,我认为这可能是要走的路,但我似乎无法找到我在文档中寻找的内容。

1 个答案:

答案 0 :(得分:1)

您可以使用动态形状对象进行自定义绘图,包括明星剪裁

Shape允许您访问上下文,使您可以访问所有画布操作。

从背景中“切割”你的星星所需的操作是globalCompositeOperation。

“目的地”合成将从任何现有图纸(绿色矩形)中剪切下一个绘制的形状(您的星星)。

以下是如何绘制绿色矩形并使用合成来切割星形。

var rect = new Kinetic.Shape({
    drawFunc: function(canvas){
        context=canvas.getContext("2d");
        context.save();
        context.beginPath();
        context.rect(0,0,96,96);
        context.fillStyle="green";
        context.fill();
        context.globalCompositeOperation="destination-out";
        drawStar(context,45,50,5,40,15);
        canvas.fillStroke(this);
        context.restore();
    },
    width: 96,
    height: 96,
    fill: 'green',
    stroke: 'black',
    strokeWidth: 2
});

由于星形不是原生帆布形状,因此您还需要使用此代码绘制星形:

function drawStar(ctx,cx,cy,spikes,outerRadius,innerRadius){
  var rot=Math.PI/2*3;
  var x=cx;
  var y=cy;
  var step=Math.PI/spikes;

  ctx.strokeSyle="#000";
  ctx.beginPath();
  ctx.moveTo(cx,cy-outerRadius)
  for(i=0;i<spikes;i++){
    x=cx+Math.cos(rot)*outerRadius;
    y=cy+Math.sin(rot)*outerRadius;
    ctx.lineTo(x,y)
    rot+=step

    x=cx+Math.cos(rot)*innerRadius;
    y=cy+Math.sin(rot)*innerRadius;
    ctx.lineTo(x,y)
    rot+=step
  }
  ctx.lineTo(cx,cy-outerRadius)
  ctx.closePath();
  ctx.fill();
}

这就是它!

这是代码和小提琴:http://jsfiddle.net/m1erickson/VVrZT/

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <div id="container"></div>
    <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.3.min.js"></script>
    <script defer="defer">
      var stage = new Kinetic.Stage({
        container: 'container',
        width: 300,
        height: 300
      });
      var layer = new Kinetic.Layer();
      stage.add(layer);

      var rect = new Kinetic.Shape({
          drawFunc: function(canvas){
              context=canvas.getContext("2d");
              context.save();
              context.beginPath();
              context.rect(0,0,96,96);
              context.fillStyle="green";
              context.fill();
              context.globalCompositeOperation="destination-out";
              drawStar(context,45,50,5,40,15);
              canvas.fillStroke(this);
              context.restore();
          },
          width: 96,
          height: 96,
          fill: 'green',
          stroke: 'black',
          strokeWidth: 2
      });
      layer.add(rect);
      layer.draw();


      function drawStar(ctx,cx,cy,spikes,outerRadius,innerRadius){
        var rot=Math.PI/2*3;
        var x=cx;
        var y=cy;
        var step=Math.PI/spikes;

        ctx.strokeSyle="#000";
        ctx.beginPath();
        ctx.moveTo(cx,cy-outerRadius)
        for(i=0;i<spikes;i++){
          x=cx+Math.cos(rot)*outerRadius;
          y=cy+Math.sin(rot)*outerRadius;
          ctx.lineTo(x,y)
          rot+=step

          x=cx+Math.cos(rot)*innerRadius;
          y=cy+Math.sin(rot)*innerRadius;
          ctx.lineTo(x,y)
          rot+=step
        }
        ctx.lineTo(cx,cy-outerRadius)
        ctx.closePath();
        ctx.fill();
      }

    </script>
  </body>
</html>