2013-06-05 55 views
0

有没有简单的方法使用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

您可以使用动力学形状对象做自定义绘制,包括你的星切割出

形状,您可以访问它,您可以访问全系列帆布操作的上下文。

从您的背景中“剪切”您的明星所需的操作是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> 
+0

globalCompositeOperation就是我一直在寻找。对于我的使用,理想的解决方案将允许两个KineticJS形状对象(即Kinetic.Rect和Kinetic.Star)的组合,只是为了便于编码,但是这回答了我发布的问题,所以我会接受它。 – Divey