При использовании .rotate () он оставляет 1px Lines позади - PullRequest
3 голосов
/ 19 февраля 2020

В настоящее время я изучаю холст html5, и я делал программу, которая вращает квадрат вокруг центра страницы, используя функцию .rotate (), но она оставляла позади 1px строк от квадрата Раньше, хотя я заполнял холст после каждого хода, и в коде ничего не было 1px. поэтому кто-то может объяснить, почему это происходит и как это предотвратить

спасибо!

const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")

canvas.width = 300;
canvas.height = 300;

//debugger;
/*
canvas.addEventListener("mousedown", mouseDown, false)
canvas.addEventListener("mouseup", mouseUp, false)
canvas.addEventListener("mousemove", mouseMove, false)
*/

ctx.fillStyle = "#303030";
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.translate(150, 150)

let turnSquare = setInterval(() =>{
	ctx.fillStyle = "#303030"
	ctx.fillRect(0, 0, canvas.width, canvas.height)

	ctx.rotate(degree(10))

	ctx.beginPath()
	ctx.fillStyle = "lime"
	ctx.fillRect(0, 0, 100, 100)

}, 1000 / 20)

function degree(input){
	return 2 * Math.PI / 360 * input
}
<canvas id="canvas">

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Край сглаживания.

Причина, по которой вы получаете линию ~ 1px, заключается в том, что ctx.fillRect, который вы используете для очистки холста, преобразуется тем же преобразованием, которое использовалось для рисования прямоугольника.

Когда фигура отображается, ее края имеют сглаживание , некоторые из краевых пикселей отображаются полупрозрачными, что означает, что при рисовании в этом же поле некоторые оригинальные пиксели останутся позади.

Для исправления

  • Сбросьте преобразование по умолчанию до очистки холста. ctx.setTransform(1,0,0,1,0,0);
  • Используйте переменную для хранения общего поворота окна (см. Пример)
  • Используйте setTransform для замены текущего преобразования, а не для поэтапного построения преобразования с использованием ctx.translate и ctx.rotate.

    Основы преобразования , помогая понять, как setTransform можно использовать для позиционирования, масштабирования и поворота визуализированных объектов в API 2D-холста.

Другие точки

  • Используйте requestAnimationFrame вместо setInterval для вызова анимации l oop, чтобы обеспечить максимально плавную анимацию.
  • Используйте один объект для хранения связанных данных , Например, объект box в примере содержит все соответствующие данные, необходимые для анимации блока.
  • Попробуйте express анимации осмысленным образом. В этом примере частота вращения блока box.rotSpeed устанавливается как число оборотов в секунду

Пример

requestAnimationFrame(mainLoop);
const ctx = canvas.getContext("2d")
canvas.height = canvas.width = 300;
canvas.style.backgroundColor = "#303030"

const box = {
   color: "lime",
   cx: 0.25,  // x rotation center as fraction of box size
   cy: 0.25,  // y rotation center as fraction of box size
   x: 150,
   y: 150,
   size: (150 * 150 / 2) ** 0.5, // makes diagonal size of box 150
   rot: 0,
   rotSpeed: 0.5,  // in rotations per second
};
function drawBox(box) {
   box.rot += box.rotSpeed * Math.PI / 30; // 2*PI/60 is one rotation per second at 60FPS
   ctx.fillStyle = box.color;
   const xa = Math.cos(box.rot);
   const ya = Math.sin(box.rot);
   ctx.setTransform(xa, ya, -ya, xa, box.x, box.y);
   ctx.fillRect(-box.cx * box.size, -box.cy * box.size, box.size, box.size);
} 
function mainLoop() {
   ctx.setTransform(1, 0, 0, 1, 0, 0); // set default transform
   ctx.clearRect(0, 0, canvas.width, canvas.height);
   drawBox(box);
   requestAnimationFrame(mainLoop);
}
<canvas id="canvas">
1 голос
/ 19 февраля 2020
  • Используйте переменную let deg = 0
  • Используйте clearRect перед перерисовкой холста
  • .save() контекст перед поворотом *
  • Поверните и переведите контекст перед окраской квадрата
  • .restore() контекст

let deg = 0; // Prepare degrees
const degree = input => 2 * Math.PI / 360 * input;
const ctx = document.getElementById("canvas").getContext("2d");

ctx.canvas.width = 300;
ctx.canvas.height = 300;

const rotateSquare = () => {
    deg += degree(10); // Increment degrees 
    deg %= 360;        // Loop degrees 
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    
    // BACKGROUND:
    ctx.fillStyle = "#303030"
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height)

    // SQUARE:
    ctx.save();
        ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);
        ctx.rotate(deg);
        ctx.fillStyle = "lime";
        ctx.fillRect(0, 0, 100, 100);
    ctx.restore();
}

let turnSquare = setInterval(rotateSquare, 1000 / 20)
<canvas id="canvas"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...