【问题标题】:Rotation precision issues旋转精度问题
【发布时间】:2014-12-04 15:43:16
【问题描述】:

我的画布上有我正在用图案图像绘制的线条。用户可以随意放大。

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

问题是当用户深入并且线条像素开始变得高负/正时,例如 -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 中重现 - 这很奇怪,因为绘图引擎不同,并且数据已经在缓冲区中。

【问题讨论】:

  • SVG(可缩放矢量图形)来救援?
  • 不。我在项目中太深入了。在这个阶段改变是不可接受的。无论如何,这个问题也以某种方式出现在 WebGL 中。我觉得是浏览器的问题。在 Firefox 中它运行良好
  • 举报bug in chrome。但很高兴听到一些想法

标签: html canvas rotation


【解决方案1】:

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

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

• 您正在画布之外开始画线,这似乎在 Chrome 中造成了舍入问题。该问题并未在 Firefox 中显示,但另一方面,Firefox 似乎正在舍入角度,因为它甚至不会尝试将模式旋转到给定阈值以下。

所以看起来 FF 和 Chrome 做出了不同的赌注:Chrome 试图尊重图案角度(但失败了),而 FF 只是忽略了它。

【讨论】:

  • - 我设置背景只是为了查看。我知道它没有显示在主画布中。 - 线点是他们应该的方式。我知道他们在画布之外。您可以在我的问题中看到用户放大并导致这种情况。问题是我是否可以在不触及线坐标的情况下解决它。顺便说一句,圆角并不能解决 chrome 中的问题
【解决方案2】:

找到了问题,找到了解决办法,希望对大家有所帮助。

问题在于纹理的重复次数(在画布和 webgl 中)。

当线很长时,意味着模式需要重复分配,在某些时候它会丢失它。可能有些溢出问题。

我的解决方案是将我的线切割成更小的段,这样每个段会更短,模式的重复次数会更少,然后重新开始每个段。 (当然我会处理

这是解决问题, 但我仍在等待 chrome 回复我的post

【讨论】:

    猜你喜欢
    • 2013-08-18
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多