HTML画布:旋转和平移图像以将图像中的点固定到画布中的坐标

时间:2018-04-03 00:00:37

标签: canvas

Codepen:https://codepen.io/anon/pen/XEYEKd

问题:给定在一个画布上渲染的场景,我需要应用哪些变换才能使第一个画布上的点(x1,y1已知)处于某个固定点上将旋转应用于画布1的图像/场景后,第二个画布(x2,y2已知,但相对于第二个画布,而不是相对于第一个画布)。

请参阅上面的codepen以了解要使用的游乐场。尝试让红点在视口中居中。操纵旋转(degrees变量)和p.x以及p.y为任意值,并测试您的转换代码是否仍然有效(将红点保持在视口中间)

我尝试过一系列应用罪,cos,逆sin,逆cos和毕达哥拉斯定理的东西,但没有取得任何成功。

2 个答案:

答案 0 :(得分:1)

您需要的是定义您在drawImage中使用的源坐标。

这些坐标是你的指针编号的负值+目标画布大小的一半,因此无论它在源画布上的哪个位置,都会在目标画布的中心绘制该点。

一旦你得到它,你所要做的就是应用基本的

translate(center, center);
rotate(angle);
drawImage(img, -center, -center);



function draw() {
  const scene = document.getElementById('canvas-scene')
  const ctx1 = scene.getContext('2d')
  const viewport = document.getElementById('canvas-viewport')
  const ctx2 = viewport.getContext('2d')
  const p = {
    x: (Math.random() * (ctx1.canvas.width - 20)) + 10,
    y: (Math.random() * (ctx1.canvas.height - 20)) + 10,
  };
  const radians = (Math.PI *2 * Math.random());

  let img = new Image();
  img.src = 'http://www.mngeo.state.mn.us/chouse/images/sibley_shillinglake_nc.jpg'

  img.onload = function() {
    ctx1.drawImage(img, 0, 0)
    ctx1.fillStyle = 'red'
    ctx1.fillRect(p.x - 5, p.y - 5, 10, 10);
    // get destination width and height
    const cw = ctx2.canvas.width,
      ch = ctx2.canvas.height,
      // new coords are the negative of our point coords + half the width of our new canvas
      newX = (p.x * -1) + cw/2,
      newY = (p.y * -1) + ch/2;
    // move to canvas center
    ctx2.translate(cw / 2, ch / 2);
    ctx2.rotate(radians);
    // draw by translating back to the top left corner
    ctx2.drawImage(scene, newX - cw/2, newY - ch/2);
  }
}
draw();

#canvas-viewport {
  border: 1px solid black;
  margin-bottom: 40px;
}

<h3>Viewport</h3>
<canvas id="canvas-viewport" width="256" height="128"></canvas>

<h3>Scene</h3>
<canvas id="canvas-scene" width="512" height="512"></canvas>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我得到了它的工作:https://codepen.io/anon/pen/Koeoxd

原则上根本不需要三角法。

function draw() {
  const scene = document.getElementById('canvas-scene')
  const ctx1 = scene.getContext('2d')
  const viewport = document.getElementById('canvas-viewport')
  const ctx2 = viewport.getContext('2d')

  let img = new Image();
  img.src = 'http://www.mngeo.state.mn.us/chouse/images/sibley_shillinglake_nc.jpg'

  const p = {
    x: 150,
    y: 200,
  }

  img.onload = function () {
    ctx1.drawImage(img, 0, 0)
    ctx1.fillStyle = 'red'
    ctx1.fillRect(p.x, p.y, 10, 10)

    const degrees = 60
    const radians = (Math.PI / 180) * degrees

    ctx2.translate(viewport.width/2, viewport.height/2)
    ctx2.rotate(radians)

    const imgX = -p.x
    const imgY = -p.y
    ctx2.drawImage(scene, imgX, imgY)
  }
}

(@ Kaiido同时给了我一个很好的解决方案。他的解决方案还考虑了调整以获得地图上红点的确切中心,这是我还没有做的事情。)