Рисование линейных путей градиента на холсте HTML - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь сделать холст с возможностью рисовать (с mousedown) пути, которые заполнены цветом, например так: enter image description here

У меня есть этот код, который вроде работает, но обычно он вылетает, когда я начинаю рисовать, возможно из-за слишком большой вычислительной нагрузки на функцию plotLine.

Мне интересно, смогу ли я сделать это более эффективно, чтобы предотвратить сбой, если это возможно.

// Some setup code
var c = document.querySelector("canvas"),
  ctx = c.getContext("2d"),
  colors = [
    { r: 198, g: 232, b: 250 },
    { r: 249, g: 213, b: 228 },
    { r: 254, g: 250, b: 214 }
  ],
  cIndex = 0,
  maxColors = colors.length,
  total = 0,
  segment = 500,
  isDown = false,
  px,
  py;

setSize();

c.onmousedown = c.ontouchstart = function(e) {
  isDown = true;
  var pos = getPos(e);
  px = pos.x;
  py = pos.y;
};

window.onmousemove = window.ontouchmove = function(e) {
  if (isDown) plot(e);
};
window.onmouseup = window.ontouchend = function(e) {
  e.preventDefault();
  isDown = false;
};

function getPos(e) {
  e.preventDefault();
  if (e.touches) e = e.touches[0];
  var r = c.getBoundingClientRect();
  return {
    x: e.clientX - r.left,
    y: e.clientY - r.top
  };
}

function plot(e) {
  var pos = getPos(e);
  plotLine(ctx, px, py, pos.x, pos.y);
  px = pos.x;
  py = pos.y;
}

function plotLine(ctx, x1, y1, x2, y2) {
  var diffX = Math.abs(x2 - x1),
    diffY = Math.abs(y2 - y1),
    dist = Math.sqrt(diffX * diffX + diffY * diffY),
    step = dist / 50,
    i = 0,
    t,
    b,
    x,
    y;

  while (i <= dist) {
    t = Math.min(1, i / dist);

    x = x1 + (x2 - x1) * t;
    y = y1 + (y2 - y1) * t;

    ctx.fillStyle = getColor();
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI * 2);
    ctx.fill();
    i += step;
  }

  function getColor() {
    var r, g, b, t, c1, c2;

    c1 = colors[cIndex];
    c2 = colors[(cIndex + 1) % maxColors];
    t = Math.min(1, total / segment);

    if (++total > segment) {
      total = 0;
      if (++cIndex >= maxColors) cIndex = 0;
    }

    r = c1.r + (c2.r - c1.r) * t;
    g = c1.g + (c2.g - c1.g) * t;
    b = c1.b + (c2.b - c1.b) * t;

    return "rgb(" + (r | 0) + "," + (g | 0) + "," + (b | 0) + ")";
  }
}

window.onresize = setSize;
function setSize() {
  c.width = window.innerWidth;
  c.height = window.innerHeight;
}
document.querySelector("button").onclick = function() {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
};
html,
body {
  background: #777;
  margin: 0;
  overflow: hidden;
}
canvas {
  position: fixed;
  left: 0;
  top: 0;
  background: #333;
}
button {
  position: fixed;
  left: 10px;
  top: 10px;
}
<canvas></canvas>
<button>Clear</button>

1 Ответ

0 голосов
/ 06 января 2019

В функции plotLine существует риск того, что dist и step равны 0. В этом случае цикл while никогда не закончится.

Так что просто добавьте эту строку:

if (!step) return;

Или, иначе замените <= на < в условии цикла:

while (i < dist) {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...