canvas的元素旋转问题

canvas's element rotation issue

好吧,我实际上找不到使用 canvas 使旋转圆居中的方法。

我想把圆的原点和一个元素(canna())的原点放在一起,我试过了,但效果不佳:

45 = 坦克宽度;
35 = 水箱高度;
50 = 灰条宽度 (canna());
10 = 灰条高度 (canna());

let c;
let player1;

function startGame() {
  map.start();
  c = new Console();
  player1 = new Tank1();
}

let map = {
  canvas: document.getElementById("game"),
  start: function() {
    this.canvas.width = window.innerWidth;
    this.canvas.height = window.innerHeight - 100;
    this.context = this.canvas.getContext("2d");
    this.interval = setInterval(updateMap, 20);
  },
  clear: function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }
}


function floor() {
  this.ctx = map.context;
  this.ctx.fillStyle = "#3D9970";
  this.ctx.fillRect(0, (map.canvas.height - 50), map.canvas.width, 50); //floor
}

class Console {
  constructor() {
    this.alpha = document.getElementById("angle");
  }

  deg() {
    degRange.value = this.alpha.value;
  }
}

class Tank1 {
  constructor() {
    this.colors = ["purple", "red", "yellow", "green"];
    this.moves = 3;
    this.speedX = 0;
    this.speedY = 0;
    this.gravity = 0.05;
    this.gravitySpeed = 0;
    this.x = Math.floor(Math.random() * ((map.canvas.width / 2) - 50) + 50);
    this.y = 100;
  }

  canna() {
    let rad = parseInt(c.alpha.value) * Math.PI / 180;
    this.ctx = map.context;

    //THE PROBLEM IS RIGHT HERE
    this.ctx.save();
    this.ctx.fillStyle = "gray";
    this.ctx.translate((this.x + 20 / 3.5) + 50 / 2, this.y + 10 / 2);
    this.ctx.rotate(-rad);
    this.ctx.translate(-((this.x + 20 / 3.5) + 50 / 2), -(this.y + 10 / 2));
    this.ctx.fillRect((this.x + 22.5), (this.y - 12), 50, 10);
    this.ctx.restore();
  }

  newPos() {
    this.gravitySpeed += this.gravity;
    this.x += this.speedX;
    this.y += this.speedY + this.gravitySpeed;
    this.hitBottom();
  }

  hitBottom() {
    let floorBottom = (map.canvas.height - 50) - 25;

    if (this.y > floorBottom) {
      this.y = floorBottom;
    }
  }

  update() {
    this.canna();
    this.ctx = map.context;
    this.ctx.fillStyle = this.colors[0];
    this.ctx.fillRect((this.x + 8), (this.y - 15), 30, 16);
    this.ctx.fillRect(this.x, this.y, 45, 25);
  }
}

function updateMap() {
  map.clear();
  floor();
  player1.newPos();
  player1.update();
}

//CONSOLE
startGame();
let degRange = document.querySelector('.displayAngle')
c.deg();

degRange.addEventListener('input', function() {
  if (!check.test(degRange.value)) {
    degRange.value = '';
  } else {
    c.alpha.value = degRange.value;
  }
});
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

html,
body {
  font-family: "Lato", sans-serif;
  width: 100%;
  height: 100%;
}

input[type="range"] {
  -webkit-appearance: none;
  background: #bdbdbd;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
}

input[type="range"]:hover {
  opacity: 1;
}

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  background: #39CCCC;
  cursor: pointer;
}

input[type="range"]::-moz-range-thumb {
  width: 25px;
  height: 25px;
  background: #39CCCC;
  cursor: pointer;
}

#game {
  display: block;
}

.console {
  position: absolute;
  display: flex;
  bottom: 0;
  width: 100%;
  height: 100px;
  background-color: #DDD;
}

.form-a {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  margin: auto;
}

.form-a>div {
  display: flex;
}

.form-a>div>p {
  padding-left: 10px;
}

.display {
  text-align: center;
  width: 50px;
  height: 25px;
  border: 0;
  font-size: 1.2em;
  outline-width: 0;
  background-color: #DDD;
}
<canvas id="game"></canvas>
<div class="console">
  <div class="form-a">
    <label>Angolation</label>
    <div>
      <input id="angle" type="range" oninput="c.deg()" value="0" max="360" />
      <input class="display displayAngle" type="text" />
    </div>
  </div>
</div>

如何让整个东西居中?

这可能是因为您在大炮上设置了 x 和 y 值,并且还试图将大炮平移相同的量。翻译字面意思是将 canvas 的整个 sheet 与绘制在其上的对象移动到您想要的位置。如果您还在对象上也设置了 x 和 y,它将移动两倍。当您翻译时,您几乎是在说将 canvas 的 sheet 的 (0,0)(左上角)放在可见 canvas 的 x 和 y 坐标处。很难解释,因为它是一个 canvas,但可以把它想象成每个绘制的对象都有自己的 sheet,可以移动和旋转。

试试这个,看看它是否是你想要做的

    this.ctx.save();
    this.ctx.fillStyle = "gray";
    this.ctx.translate(this.x + 22.5, this.y - 5);
    this.ctx.rotate(-rad);
    this.ctx.fillRect(0, -5, 50, 10);  
    this.ctx.restore();

使用 save()restore() 之后您不需要将对象翻译回来。我将大炮的 y 值设置为 -5,以便将大炮末端的中心定位在其 canvas 的 sheet 的 (0,0) 上。旋转时将确保它从那一端的中心旋转。