在HTML画布上绘制线性渐变路径

时间:2019-01-06 07:41:40

标签: javascript canvas linear-gradients

我正在尝试制作一种能够绘制(通过鼠标按下)填充有以下颜色的路径的画布: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 :(得分:1)

在函数plotLine中,存在diststep为0的风险。在这种情况下,while循环将永远不会结束。

所以只需添加这一行:

if (!step) return;

或者,在循环条件下用<=替换<

while (i < dist) {