【问题标题】:Merge multiple trapezoids into one shape将多个梯形合并为一个形状
【发布时间】:2021-07-07 14:17:25
【问题描述】:

我正在开发一个项目,用户可以通过将多个梯形添加在一起来绘制形状。目前它看起来像这样:

但我想要的是删除/隐藏形状内的线条,使其形成一个单一的形状:

形状是用 3 个点 {bsup;斌夫; h;}分别表示顶线的长度、底线的长度、形状的高度

export const drawPolygonComplex = (ctx, values, inputValues, 
  distanceUnits, displayCote = true) => {
  const hCumul = calcHeight(values);
  const middleX = ctx.canvas.width / 2;
  const middleY = ctx.canvas.height / 2;
  const startY = middleY - hCumul / 2;

  let nbPiece = 0;
  let currentY = startY;

  if (inputValues.length) {
let cotes = [];
for (let key in values) {
  //#region attribution des valeurs pour placer les cotes
  let intKey = parseInt(key);

  let upperLongestValue = values[intKey].b_sup;
  let lowerLongestValue = values[intKey].b_inf;

  if (values.length > 1) {
    if (intKey == 0) {
      if (values[intKey + 1].b_sup) {
        lowerLongestValue =
          values[intKey].b_inf > values[intKey + 1].b_sup
            ? values[intKey].b_inf
            : values[intKey + 1].b_sup;
      }
    } else if (intKey == values.length - 1) {
      upperLongestValue =
        values[intKey].b_sup > values[intKey - 1].b_inf
          ? values[intKey].b_sup
          : values[intKey - 1].b_inf;
    } else {
      lowerLongestValue =
        values[intKey].b_inf > values[intKey + 1].b_sup
          ? values[intKey].b_inf
          : values[intKey + 1].b_sup;
      upperLongestValue =
        values[intKey].b_sup > values[intKey - 1].b_inf
          ? values[intKey].b_sup
          : values[intKey - 1].b_inf;
    }
  }

  let coteUpLeft = { x: middleX - upperLongestValue / 2, y: currentY };
  let coteUpRight = { x: middleX + upperLongestValue / 2, y: currentY };
  let coteDownLeft = { x: middleX - lowerLongestValue / 2, y: currentY + values[key].h };
  let coteDownRight = { x: middleX + lowerLongestValue / 2, y: currentY + values[key].h };
  //#endregion

  //Définir les coins
  let upLeft = { x: middleX - values[key].b_sup / 2, y: currentY };
  let upRight = { x: middleX + values[key].b_sup / 2, y: currentY };
  let downLeft = { x: middleX - values[key].b_inf / 2, y: currentY + values[key].h };
  let downRight = { x: middleX + values[key].b_inf / 2, y: currentY + values[key].h };

  //Dessiner la shape
  ctx.lineWidth = 2;
  ctx.strokeStyle = 'black';
  ctx.fillStyle = ctx.createPattern(HatchPattern(), 'repeat');
  ctx.beginPath();
  ctx.moveTo(upLeft.x, upLeft.y);
  ctx.lineTo(upRight.x, upRight.y);
  ctx.lineTo(downRight.x, downRight.y);
  ctx.lineTo(downLeft.x, downLeft.y);
  ctx.lineTo(upLeft.x, upLeft.y);
  ctx.closePath();
  ctx.fill();
  ctx.stroke();

  if (displayCote) {
    //Placer les cotes
    if (nbPiece % 2 == 0) {
      cotes[intKey + 1] = drawRightCote(
        ctx,
        coteUpRight.x,
        coteDownRight.x,
        coteUpRight.y,
        coteDownRight.y,
        distanceUnits,
        inputValues[key].h,
        1
      );
    } else {
      cotes[intKey + 1] = drawLeftCote(
        ctx,
        coteUpLeft.x,
        coteDownLeft.x,
        coteUpLeft.y,
        coteDownLeft.y,
        distanceUnits,
        inputValues[key].h,
        1
      );
    }
  }

  //Calcul des variables
  currentY += values[key].h;
  nbPiece++;

  if (displayCote) {
    //Cote du haut et du bas
    if (intKey == 0) {
      cotes[0] = drawUpperCote(
        ctx,
        coteUpLeft.x,
        coteUpRight.x,
        startY,
        distanceUnits,
        inputValues[key].b_sup,
        1
      );
    }
    if (intKey == values.length - 1) {
      cotes[values.length + 1] = drawLowerCote(
        ctx,
        coteDownLeft.x,
        coteDownRight.x,
        currentY,
        distanceUnits,
        inputValues[key].b_inf,
        1
      );
      //Cote hauteur
      drawLeftCote(
        ctx,
        middleX - values[0].b_sup / 2,
        coteDownLeft.x,
        startY,
        currentY,
        distanceUnits,
        calcHeight(inputValues),
        2
      );
    }
  }
}

return cotes;

} };

【问题讨论】:

  • 您必须在另一个画布上绘制所有形状(带有轮廓)。然后擦除形状相交的线条。最后,从该画布中获取绘图数据并将其写入主画布。
  • 我怎样才能找到线的交汇点?

标签: javascript reactjs canvas html5-canvas


【解决方案1】:

您可以找出一种方法来跟踪连接点,然后清除它们。首先,您需要找到形状连接在一起的位置。

const drawTrapezoid = (ctx, x, y, width, height, indent = 0) => {
  ctx.beginPath();
  ctx.moveTo(x + indent, y);
  ctx.lineTo(x - indent + width, y);
  ctx.lineTo(x + width, y + height);
  ctx.lineTo(x, y + height);
  ctx.closePath();
  ctx.stroke();
}

const ctx = document.querySelector('#drawing').getContext('2d');

Object.assign(ctx.canvas, { width: 300, height: 300 });

const
  x = 20, y = 20,
  height = 160, width = 60,
  thickness = 6;

ctx.lineWidth = thickness;
ctx.strokeStyle = 'green';
drawTrapezoid(ctx, x, y, width, 20, -10);
ctx.strokeRect(x, y + 20, width, height - 40);
drawTrapezoid(ctx, x - 10, y + height - 20, width + 20, 20, 10);

const thickHalf = thickness / 2;
ctx.fillStyle = 'red';
ctx.fillRect(x + thickHalf, y - thickHalf + 20, width - thickness, thickness);
ctx.fillRect(x + thickHalf, y - thickHalf + height - 20, width - thickness, thickness);
<canvas id="drawing"></canvas>

确定点连接的位置后,擦除线条。不要像上面示例的后半部分那样调用fillRect,而是调用clearRect。在单独的画布上绘制此形状后,抓取数据并将其绘制到主画布上。

const drawTrapezoid = (ctx, x, y, width, height, indent = 0) => {
  ctx.beginPath();
  ctx.moveTo(x + indent, y);
  ctx.lineTo(x - indent + width, y);
  ctx.lineTo(x + width, y + height);
  ctx.lineTo(x, y + height);
  ctx.closePath();
  ctx.stroke();
}

const ctx = document.querySelector('#drawing').getContext('2d');

Object.assign(ctx.canvas, { width: 300, height: 300 });

const
  x = 20, y = 20,
  height = 160, width = 60,
  thickness = 6;

ctx.lineWidth = thickness;
ctx.strokeStyle = 'green';
drawTrapezoid(ctx, x, y, width, 20, -10);
ctx.strokeRect(x, y + 20, width, height - 40);
drawTrapezoid(ctx, x - 10, y + height - 20, width + 20, 20, 10);

const thickHalf = thickness / 2;
ctx.clearRect(x + thickHalf, y - thickHalf + 20, width - thickness, thickness);
ctx.clearRect(x + thickHalf, y - thickHalf + height - 20, width - thickness, thickness);
<canvas id="drawing"></canvas>

绘制到主画布。

const drawTrapezoid = (ctx, x, y, width, height, indent = 0) => {
  ctx.beginPath();
  ctx.moveTo(x + indent, y);
  ctx.lineTo(x - indent + width, y);
  ctx.lineTo(x + width, y + height);
  ctx.lineTo(x, y + height);
  ctx.closePath();
  ctx.stroke();
}

const ctx = document.querySelector('#drawing').getContext('2d');
const ctxTmp = document.querySelector('#tmp-drawing').getContext('2d');

Object.assign(ctx.canvas, { width: 300, height: 300 });
Object.assign(ctxTmp.canvas, { width: 300, height: 300 });

ctx.fillStyle = 'yellow';
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

const
  x = 20,
  y = 20,
  height = 160,
  width = 60,
  thickness = 6;

ctxTmp.lineWidth = thickness;
ctxTmp.strokeStyle = 'green';
drawTrapezoid(ctxTmp, x, y, width, 20, -10);
ctxTmp.strokeRect(x, y + 20, width, height - 40);
drawTrapezoid(ctxTmp, x - 10, y + height - 20, width + 20, 20, 10);

const thickHalf = thickness / 2;
ctxTmp.clearRect(x + thickHalf, y - thickHalf + 20, width - thickness, thickness);
ctxTmp.clearRect(x + thickHalf, y - thickHalf + height - 20, width - thickness, thickness);

const img = document.createElement('img');
img.src = ctxTmp.canvas.toDataURL('image/png');
img.onload = () => ctx.drawImage(img, 0, 0);
#tmp-drawing { display: none; }
<canvas id="drawing"></canvas>
<canvas id="tmp-drawing"></canvas>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-24
    • 2017-07-22
    • 2022-01-25
    • 2015-08-26
    • 1970-01-01
    • 2016-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多