旋转精度问题

时间:2014-12-02 11:48:43

标签: html5 canvas rotation

我的画布上有线条,我正在用图案图像绘制。用户可以根据需要放大。

我的线条有一些世界值,每次绘制都会转换为像素。

问题是当用户走得很深并且线像素开始变为高负值/正值时,例如-40000和50000.当线条旋转较小时,我们会看到意外的结果,如我创建的演示中所示这里。

在演示中我们可以看到我们正在绘制的主画布和一个代表我的模式的小画布。我们可以在主画布中看到模式不正确

// JavaScript source code

requestAnimationFrame(draw);
var ctx = mainCanvas.getContext('2d');

var center = {
  x: mainCanvas.width / 2,
  y: mainCanvas.height / 2
};



var angle = 0;


// Creating the pattern image
var imgCtx = imgLine.getContext('2d');
imgCtx.strokeStyle = 'red';
imgCtx.lineWidth = 2;
imgCtx.beginPath();
imgCtx.moveTo(0, imgLine.height / 2);
imgCtx.lineTo(imgLine.width, imgLine.height / 2);
imgCtx.stroke();
imgCtx.beginPath();
imgCtx.strokeStyle = 'blue';
imgCtx.moveTo(imgLine.width * 0.3, 0);
imgCtx.lineTo(imgLine.width * 0.3, imgLine.height);
imgCtx.stroke();
imgCtx.beginPath();
imgCtx.strokeStyle = 'green';
imgCtx.moveTo(imgLine.width * 0.8, 0);
imgCtx.lineTo(imgLine.width * 0.8, imgLine.height);
imgCtx.stroke();


ctx.fillStyle = ctx.strokeStyle = ctx.createPattern(imgLine, "repeat");

onDataChanged(true);


function rotateAtPoint(p_objContext, center, p_dblAngle) {
  p_objContext.translate(center.x, center.y);
  p_objContext.rotate(p_dblAngle);
  p_objContext.translate(-center.x, -center.y);
}

function draw() {
  ctx.clearRect(0, 0, mainCanvas.width, mainCanvas.height);

  var lineWidth = imgLine.height * scale;
  ctx.lineWidth = lineWidth;

  ctx.save();
  rotateAtPoint(ctx, center, angle);
  ctx.beginPath();
  ctx.moveTo(center.x, center.y);
  ctx.lineTo(center.x + lineLength, center.y);
  ctx.stroke();

  //ctx.fillRect(center.x,center.y + 30, lineLength, lineWidth);
  ctx.restore();
}


function onDataChanged(skipDraw) {
  scale = parseFloat(txtFactor.value);
  center.x = parseFloat(txtX.value);
  center.y = parseFloat(txtY.value);
  lineLength = parseFloat(txtLineLength.value);
  angle = parseFloat(txtAngle.value);
  draw();
}
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
  <meta charset="utf-8" />
  <title></title>
</head>

<body>
  <div style="padding:10px">
    Angle:
    <input id="txtAngle" type="number" value="0.001" min="0" step="0.0001" max="360" onchange="onDataChanged()" />X:
    <input id="txtX" type="number" value="-40000" min="-1000000" step="1" max="1000000" onchange="onDataChanged()" />Y:
    <input id="txtY" type="number" value="150" min="-1000000" step="1" max="1000000" onchange="onDataChanged()" />Length:
    <input id="txtLineLength" type="number" value="100000" min="0" step="5" max="5000000" onchange="onDataChanged()" />Factor:
    <input id="txtFactor" type="number" value="1" min="0" step="0.1" max="500" onchange="onDataChanged()" />
  </div>

  <div id="canvasesDiv">
    <canvas id="mainCanvas" width="300" height="300" style="border: 1px solid black; margin-right: 20px; background-color: lightgray; "></canvas>
    <canvas id="imgLine" width="16" height="16" style="border: 1px solid black; margin-right: 20px;background-color:lightgreen"></canvas>
  </div>

</body>

</html>

任何人都知道该怎么做?

将线切割为仅可见部分对我来说不好,因为这个问题也在WebGL中重现 - 这很奇怪,因为绘制引擎不同,并且数据已经存在于缓冲区中。

2 个答案:

答案 0 :(得分:0)

你得到的奇怪结果是两个因素的结果:

•您正在模式画布上定义绿色CSS背景:当您将其用作模式时,它将不会显示,这是预期的行为。

•您正在开始走出画布,这似乎会在Chrome中产生舍入问题。这个问题没有在Firefox中显示,但另一方面,似乎Firefox正在转向角度,因为它甚至没有尝试将模式旋转到给定阈值以下。

所以似乎FF和Chrome做出了不同的赌注:Chrome尝试尊重模式角度(并失败),FF只是忽略它。

答案 1 :(得分:0)

发现问题,并找到一些解决方案,希望它能帮助别人。

问题是纹理的重复次数(包括canvas和webgl)。

当线条很长时,意味着图案需要重复分配,在某些时候它会失去它。也许有些溢出问题。

我的解决方案是将我的线条切割成较小的线段,这样每个线段都会更短,模式的重复次数会更少,并重新启动每个线段。 (当然我是handl

这解决了这个问题, 但我还在等待chrome回答post