Como girar um objeto de tela após o evento de movimentação do mouse com facilidade?
Não tenho certeza se usei a palavra certa aqui. Eu acho que facilitar significa que ele não segue o mouse imediatamente, mas com algum atraso?
No momento, a íris está girando na direção do meu mouse. E se eu quiser que ele tenha o mesmo efeito queesta? É muito difícil fazê-lo ou exige apenas alterações simples do código? Existe uma maneira / solução padrão para esse tipo de problema?
Aqui está meu código atual. Também pode ser encontrado emÍris rotativa .
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
class Circle {
constructor(options) {
this.cx = options.x;
this.cy = options.y;
this.radius = options.radius;
this.color = options.color;
this.angle = options.angle;
this.binding();
}
binding() {
const self = this;
window.addEventListener('mousemove', (e) => {
self.calculateAngle(e);
});
}
calculateAngle(e) {
if (!e) return;
let rect = canvas.getBoundingClientRect(),
vx = e.clientX - this.cx,
vy = e.clientY - this.cy;
this.angle = Math.atan2(vy, vx);
}
renderEye() {
ctx.setTransform(1, 0, 0, 1, this.cx, this.cy);
ctx.rotate(this.angle);
let eyeRadius = this.radius / 3;
ctx.beginPath();
ctx.arc(this.radius / 2, 0, eyeRadius, 0, Math.PI * 2);
ctx.fill();
}
render() {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.beginPath();
ctx.arc(this.cx, this.cy, this.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.strokeStyle = '#09f';
ctx.lineWidth = 1;
ctx.stroke();
this.renderMessage();
this.renderEye();
}
renderMessage() {
ctx.font = "18px serif";
ctx.strokeStyle = 'black';
ctx.fillText('Angle: ' + this.angle, 30, canvas.height - 40);
}
}
var rotatingCircle = new Circle({
x: 320,
y: 160,
radius: 40,
color: 'black',
angle: Math.random() * Math.PI * 2
});
function animate() {
rotatingCircle.render();
requestAnimationFrame(animate);
}
animate();
<canvas id='canvas' style='width: 700; height: 500;'></canvas>
Atualizado com a possível solução:
Na verdade, segui o link que postei na pergunta e usei uma maneira semelhante para facilitar a rotação, que eu acho que é semelhante ao que as categorias @ Blindman67 são como flexibilização não determinística.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
class Circle {
constructor(options) {
this.cx = options.x;
this.cy = options.y;
this.radius = options.radius;
this.color = options.color;
this.toAngle = 0;
this.angle = options.angle;
this.velocity = 0;
this.maxAccel = 0.04;
this.binding();
}
binding() {
const self = this;
window.addEventListener('mousemove', (e) => {
self.calculateAngle(e);
});
}
calculateAngle(e) {
if (!e) return;
let rect = canvas.getBoundingClientRect(),
// mx = parseInt(e.clientX - rect.left),
// my = parseInt(e.clientY - rect.top),
vx = e.clientX - this.cx,
vy = e.clientY - this.cy;
this.toAngle = Math.atan2(vy, vx);
}
clip(x, min, max) {
return x < min ? min : x > max ? max : x;
}
renderEye() {
ctx.setTransform(1, 0, 0, 1, this.cx, this.cy);
let radDiff = 0;
if (this.toAngle != undefined) {
radDiff = this.toAngle - this.angle;
}
if (radDiff > Math.PI) {
this.angle += 2 * Math.PI;
} else if (radDiff < -Math.PI) {
this.angle -= 2 * Math.PI;
}
let easing = 0.06;
let targetVel = radDiff * easing;
this.velocity = this.clip(targetVel, this.velocity - this.maxAccel, this.velocity + this.maxAccel);
this.angle += this.velocity;
ctx.rotate(this.angle);
let eyeRadius = this.radius / 3;
ctx.beginPath();
ctx.arc(this.radius / 2, 0, eyeRadius, 0, Math.PI * 2);
ctx.fill();
}
render() {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.beginPath();
ctx.arc(this.cx, this.cy, this.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.strokeStyle = '#09f';
ctx.lineWidth = 1;
ctx.stroke();
this.renderMessage();
this.renderEye();
}
renderMessage() {
ctx.font = "18px serif";
ctx.strokeStyle = 'black';
ctx.fillText('Angle: ' + this.angle.toFixed(3), 30, canvas.height - 40);
ctx.fillText('toAngle: ' + this.toAngle.toFixed(3), 30, canvas.height - 20);
}
}
var rotatingCircle = new Circle({
x: 250,
y: 130,
radius: 40,
color: 'black',
angle: Math.random() * Math.PI * 2
});
function animate() {
rotatingCircle.render();
requestAnimationFrame(animate);
}
animate();
<canvas id='canvas' style='width: 700; height: 500;'></canvas>