【问题标题】:How can I create a transparent shape within an existing shape using KineticJS如何使用 KineticJS 在现有形状中创建透明形状
【发布时间】:2013-06-06 08:03:04
【问题描述】:

有没有一种简单的方法可以使用 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/

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

【问题讨论】:

    标签: javascript kineticjs


    【解决方案1】:

    您可以使用动力学形状对象进行自定义绘图,包括您的星星切割

    Shape 使您可以访问一个上下文,该上下文使您可以访问所有画布操作。

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

    “destination-out”组合将从任何现有图纸(您的绿色矩形)中剪下下一个绘制的形状(您的星形)。

    这是绘制绿色矩形并使用构图切出星星的方法。

    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>
    

    【讨论】:

    • globalCompositeOperation 是我想要的。对于我的使用,理想的解决方案是允许组合两个 KineticJS 形状对象(即 Kinetic.Rect 和 Kinetic.Star),只是为了便于编码,但这回答了我发布的问题,所以我会接受它。
    猜你喜欢
    • 2014-02-14
    • 1970-01-01
    • 2014-08-20
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 2012-06-06
    • 1970-01-01
    相关资源
    最近更新 更多