'lineTo' 方法超出 canvas 维度时的性能

Performances of 'lineTo' method when going beyond canvas dimensions

使用 canvas 上下文,假设我调用 beginPath 然后两次 lineTox=-999, y=-999x=50, y=50 最后 stroke,它将从左上角到 (50,50) 点画一条线。

在这个过程中,线的左上外侧部分从外面绘制还是[=36] =]从可见的 canvas 部分绘制,在我们的例子中 (0,0).

参见上面的例子,我有两条没有安全坐标的红线和两条有安全坐标的绿线:

const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');

// Draw a line between two points
const drawLine = (color, fromX, fromY, toX, toY) => {
  context.beginPath();
  context.lineWidth = 5;
  context.lineTo(fromX, fromY);
  context.lineTo(toX, toY);
  context.strokeStyle = color;
  context.stroke();
}

// Without coordinates safing
drawLine('#F00', -999, -999, 50, 50);
drawLine('#F00', 150, 150, 999 + canvas.width, 999 + canvas.height);

const safeCoordinateX = value => 
  value < 0 ? 0 : value > canvas.width ? canvas.width : value;

const safeCoordinateY = value => 
  value < 0 ? 0 : value > canvas.height ? canvas.height : value;

const safeCoordinates = (fromX, fromY, toX, toY) => 
  [safeCoordinateX(fromX), safeCoordinateY(fromY), safeCoordinateX(toX), safeCoordinateY(toY)];

// With coordinates safing
drawLine('#0F0', ...safeCoordinates(150, 50, 999 +  canvas.width, -999));
drawLine('#0F0', ...safeCoordinates(50, 150, -999, 999 + canvas.height));
canvas {
  border: 1px solid rgba(0, 0, 0, .5)
}
<canvas width=200 height=200 />

为了回答您的问题,我们需要一个基准。看下面,安全抽签比不安全抽签花费的时间更长。可能是你多算了算。

const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');

// Draw a line between two points
const drawLine = (color, fromX, fromY, toX, toY) => {
  context.beginPath();
  context.lineWidth = 5;
  context.lineTo(fromX, fromY);
  context.lineTo(toX, toY);
  context.strokeStyle = color;
  context.stroke();
}

const safeCoordinateX = value => 
  value < 0 ? 0 : value > canvas.width ? canvas.width : value;

const safeCoordinateY = value => 
  value < 0 ? 0 : value > canvas.height ? canvas.height : value;

const safeCoordinates = (fromX, fromY, toX, toY) => 
  [safeCoordinateX(fromX), safeCoordinateY(fromY), safeCoordinateX(toX), safeCoordinateY(toY)];
 
   function drawSafe() {
  const t = Date.now();
  
  drawLine('#0F0', ...safeCoordinates(150, 50, 999 +  canvas.width, -999));
  drawLine('#0F0', ...safeCoordinates(50, 150, -999, 999 + canvas.height));
  
  return Date.now() - t;
}

function drawUnsafe() {
  const t = Date.now();
  
  drawLine('#F00', -999, -999, 50, 50);
  drawLine('#F00', 150, 150, 999 + canvas.width, 999 + canvas.height);
  
  return Date.now() - t;
}

function launchAndCalcTotTime(f) {
  let t = 0;

  for (let i = 0; i < 100000; i += 1) {
    t += f();
  }
  
  return t;
}

console.log(`Safe draw took ${launchAndCalcTotTime(drawSafe)}ms`);
console.log(`Unsafe draw took ${launchAndCalcTotTime(drawUnsafe)}ms`);
canvas {
  border: 1px solid rgba(0, 0, 0, .5)
}
<canvas width=200 height=200 />


为了确定这一点,您还可以尝试画一条额外的大线,看看它是否会改变结果。如果画了线,那么它应该减慢执行速度。但答案是否定的。

const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');

// Draw a line between two points
const drawLine = (color, fromX, fromY, toX, toY) => {
  context.beginPath();
  context.lineWidth = 5;
  context.lineTo(fromX, fromY);
  context.lineTo(toX, toY);
  context.strokeStyle = color;
  context.stroke();
}

const safeCoordinateX = value => 
  value < 0 ? 0 : value > canvas.width ? canvas.width : value;

const safeCoordinateY = value => 
  value < 0 ? 0 : value > canvas.height ? canvas.height : value;

const safeCoordinates = (fromX, fromY, toX, toY) => 
  [safeCoordinateX(fromX), safeCoordinateY(fromY), safeCoordinateX(toX), safeCoordinateY(toY)];
 
   function drawSafe() {
  const t = Date.now();
  
  drawLine('#0F0', ...safeCoordinates(150, 50, 999 +  canvas.width, -999));
  drawLine('#0F0', ...safeCoordinates(50, 150, -999, 999 + canvas.height));
  
  return Date.now() - t;
}

function drawUnsafe() {
  const t = Date.now();
  
  drawLine('#F00', -999999999, -999999999, 5000000000, 500000000);
  drawLine('#F00', 0, 0, 9990000000 + canvas.width, 9990000000 + canvas.height);
  
  return Date.now() - t;
}

function launchAndCalcTotTime(f) {
  let t = 0;

  for (let i = 0; i < 100000; i += 1) {
    t += f();
  }
  
  return t;
}

console.log(`Safe draw took ${launchAndCalcTotTime(drawSafe)}ms`);
console.log(`Unsafe draw took ${launchAndCalcTotTime(drawUnsafe)}ms`);
canvas {
  border: 1px solid rgba(0, 0, 0, .5)
}
<canvas width=200 height=200 />