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) 上。旋转时将确保它从那一端的中心旋转。
好吧,我实际上找不到使用 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) 上。旋转时将确保它从那一端的中心旋转。