Стрелка рисования линии без вращения на холсте - PullRequest
1 голос
/ 26 марта 2020

Большая часть кода для рисования стрелок в html canvas включает в себя вращение контекста холста и рисование линий.

Мой вариант использования - рисовать их с помощью тригонометрии без вращения холста. или этот векторный алгоритм вы называете? Помощь приветствуется.

Это то, что у меня есть (забыл, где я получил большую часть кода). Dr aws 2 стрелки в начале и в конце на основе двух последних параметров arrowStart и arrowEnd, которые являются логическими.

drawLineArrowhead: function(context, arrowStart, arrowEnd) {

        // Place start end points here.
        var x1 = 0;
        var y1 = 0;
        var x2 = 0;
        var y2 = 0;

        var distanceFromLine = 6;
        var arrowLength = 9;
        var dx = x2 - x1;
        var dy = y2 - y1;
        var angle = Math.atan2(dy, dx);
        var length = Math.sqrt(dx * dx + dy * dy);

        context.translate(x1, y1);
        context.rotate(angle);
        context.beginPath();
        context.moveTo(0, 0);
        context.lineTo(length, 0);

        if (arrowStart) {
            context.moveTo(arrowLength, -distanceFromLine);
            context.lineTo(0, 0);
            context.lineTo(arrowLength, distanceFromLine);
        }

        if (arrowEnd) {
            context.moveTo(length - arrowLength, -distanceFromLine);
            context.lineTo(length, 0);
            context.lineTo(length - arrowLength, distanceFromLine);
        }

        context.stroke();
        context.setTransform(1, 0, 0, 1, 0, 0);
    },

1 Ответ

1 голос
/ 26 марта 2020

См. Код ниже, только немного тригонометрии.

canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.lineCap = "round";
ctx.lineWidth = 5;

function drawLineArrowhead(p1, p2, startSize, endSize) {
  ctx.beginPath()
  ctx.moveTo(p1.x, p1.y);
  ctx.lineTo(p2.x, p2.y);
  
  if (startSize > 0) {
    lineAngle = Math.atan2(p2.y - p1.y, p2.x - p1.x);
    delta = Math.PI/6  
    for (i=0; i<2; i++) {
      ctx.moveTo(p1.x, p1.y);
      x = p1.x + startSize * Math.cos(lineAngle + delta)
      y = p1.y + startSize * Math.sin(lineAngle + delta)
      ctx.lineTo(x, y);
      delta *= -1
    }
  }
  if (endSize > 0) {
    lineAngle = Math.atan2(p1.y - p2.y, p1.x - p2.x);
    delta = Math.PI/6  
    for (i=0; i<2; i++) {
      ctx.moveTo(p2.x, p2.y);
      x = p2.x + endSize * Math.cos(lineAngle + delta)
      y = p2.y + endSize * Math.sin(lineAngle + delta)
      ctx.lineTo(x, y);
      delta *= -1
    }
  }
  ctx.stroke();
}

drawLineArrowhead({x:10, y:10}, {x:100, y:20}, 0, 30)
drawLineArrowhead({x:20, y:25}, {x:140, y:120}, 20, 20)
drawLineArrowhead({x:140, y:20}, {x:80, y:50} , 20, 0)

drawLineArrowhead({x:150, y:20}, {x:150, y:90}, 20, 5)
drawLineArrowhead({x:180, y:90}, {x:180, y:20}, 20, 5)

drawLineArrowhead({x:200, y:10}, {x:200, y:140}, 10, 10)
drawLineArrowhead({x:220, y:140}, {x:220, y:10}, 10, 20)
<canvas id="canvas">

Если вы запустите его, вы увидите несколько образцов.
drawLineArrowhead имеет 4 параметра (p1, p2, startSize, endSize) первые два являются отправной точкой и конечная точка линии, последние две - размер стрелки, просто чтобы дать конечному пользователю некоторый контроль над тем, насколько велики эти стрелки в конце, если мы хотим удалить их, мы устанавливаем значение 0.

...