【问题标题】:Adding outer stroke to colliding canvas rectangles将外部笔划添加到碰撞画布矩形
【发布时间】:2019-09-11 18:46:49
【问题描述】:

我在画布中添加了多个可能相互碰撞的矩形。外部笔划应显示在两个矩形的外部,或者应将矩形形状合并为一个,从而产生预期的结果。

见下图

它必须被剪切,因为它会在画布下显示内容。查看带有背景图片的实时示例:https://jsfiddle.net/0qpgf5un/

在下面的代码示例中,矩形被添加到彼此之上,正如您在图片的第一个示例中看到的那样。

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var offsetX = 150;
var offsetY = 150;
var w = 200;
var h = 100;

ctx.fillStyle = "red";
ctx.rect(0, 0, 600, 600);
ctx.fill();

ctx.clearRect(offsetX,offsetY, w, h);
ctx.strokeRect(offsetX, offsetY, w, h);

ctx.clearRect(offsetX-50,offsetY+50, w, h);
ctx.strokeRect(offsetX-50, offsetY+50, w, h);

有没有办法在不编写每条路径的复杂计算的情况下实现它,因为矩形的碰撞可能是无意的和多样化的?

编辑: 我想要实现的是类似 youtube 的反馈表单中的功能,在编辑屏幕截图时,您可以突出显示项目,然后合并边框。

【问题讨论】:

  • 您是否尝试过使用多边形填充? stackoverflow.com/questions/4839993/…
  • 谢谢,但就像我在问题中提到的那样,我不想计算每条路径,因为矩形可能会有所不同。
  • 是的,我明白了,我添加了一个简单的解决方案
  • 如果您担心保留笔画宽度,我会考虑到这一点...

标签: javascript canvas


【解决方案1】:

再添加一个clearRect()(第一个)

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var offsetX = 150;
var offsetY = 150;
var w = 200;
var h = 100;


ctx.fillStyle = "red";
ctx.rect(0, 0, 600, 600);
ctx.fill();

ctx.clearRect(offsetX,offsetY, w, h);
ctx.strokeRect(offsetX, offsetY, w, h);
ctx.clearRect(offsetX-50,offsetY+50, w, h);
ctx.strokeRect(offsetX-50, offsetY+50, w, h);
ctx.clearRect(offsetX,offsetY, w, h);

https://jsfiddle.net/kt3yjhpc/

【讨论】:

    【解决方案2】:

    您可以跳过清除第一个矩形,然后在描边第二个矩形后将其清除。

    clearPrev 函数将清除初始矩形笔划内的区域。

    let canvas = document.getElementById('canvas'),
        ctx = canvas.getContext('2d'),
        offsetX = 70,
        offsetY = 20,
        w = 200,
        h = 100,
        strokeWidth = 5;
    
    ctx.fillStyle = '#F00'
    ctx.rect(0, 0, 600, 600);
    ctx.fill();
    
    ctx.strokeStyle = '#0FF';
    ctx.lineWidth = strokeWidth;
    
    //ctx.clearRect(offsetX, offsetY, w, h); <-- Do not need to do this, if we clear below...
    ctx.strokeRect(offsetX, offsetY, w, h);
    
    ctx.clearRect(offsetX - 50, offsetY + 50, w, h);
    ctx.strokeRect(offsetX - 50, offsetY + 50, w, h);
    
    clearPrev(ctx, offsetX, offsetY, w, h); // Clear previous
    
    function clearPrev(ctx, x, y, w, h) {
      let startOffset = Math.round(ctx.lineWidth / 2) - 1,
          endOffset = strokeWidth - 1;
      ctx.clearRect(x + startOffset, y + startOffset, w - endOffset, h - endOffset);
    }
    &lt;canvas id="canvas" width="290" height="190"&gt;&lt;/canvas&gt;

    【讨论】:

      【解决方案3】:

      当你想清除具有复杂形状的画布时,忘记clearRect,它不是唯一能够产生透明像素的。

      相反,请查看compositing

      所以你的形状确实是边界线,但我认为你已经从使用它中受益了:

      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
      
      var offsetX = 150;
      var offsetY = 150;
      var w = 200;
      var h = 100;
      ctx.lineWidth = 2;
      ctx.fillStyle = "red";
      ctx.fillRect(0, 0, 600, 600);
      
      // declare our complex shape as a single sub-path
      ctx.beginPath()
      ctx.rect(offsetX,offsetY, w, h);
      ctx.rect(offsetX-50, offsetY+50, w, h);
      
      // now we can paint it
      
      // first the stroke, because we want to erase what's inside the fill-area
      ctx.stroke();
      
      // now to erase, we switch to destination-out compositing mode
      ctx.globalCompositeOperation = 'destination-out';
      // fill the inner path
      ctx.fill();
      
      // we're done
      // If you wish to go back to normal mode later
      ctx.globalCompositeOperation = 'source-over';
      body { background: linear-gradient(blue,yellow); }
      &lt;canvas id="canvas" width="600" height="600"&gt;&lt;/canvas&gt;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2017-11-07
        • 2013-04-19
        • 2016-04-05
        相关资源
        最近更新 更多