我不确定我是否在这里使用了正确的词。我想放松意味着它不会立即跟随鼠标,但有一些延迟?如何在鼠标移动事件后使用缓动来旋转画布对象?
目前虹膜旋转到我的鼠标方向。如果我想让它与this有相同的效果怎么办?这很难吗?或者只需要简单的代码更改?这种问题有没有标准的方法/解决方案?
这是我目前的代码。它也可以在Rotating Iris找到。
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>
有可能的解决方案更新时间:
我居然也跟着我张贴在问题的链接,并使用类似的方式来缓解旋转,我认为这是类似于什么@ Blindman67类别作为非确定性宽松。
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
class Circle {
\t constructor(options) {
\t 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() {
\t const self = this;
\t 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;
\t 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);
\t 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({
\t x: 250,
y: 130,
radius: 40,
color: 'black',
angle: Math.random() * Math.PI * 2
});
function animate() {
\t rotatingCircle.render();
\t requestAnimationFrame(animate);
}
animate();
<canvas id='canvas' style='width: 700; height: 500;'></canvas>
的你的方法两者都是非常有帮助的。我学到了很多。然而在这个例子中,在-2.9附近的角度出现了一个小故障,虹膜很快就会跳回到底部。我用一个可能的解决方案更新了我的问题,这个解决方案受到了我在问题中发布的链接的启发。你能看看这是否是好的吗? – newguy
@newguy是的,你的解决方案是一个非常好的解决方案.. – Blindman67
你也可以通过获得'Math.asin(crossProduct(v1,v2))'来找到两个矢量之间的角度,其中v1是当前来自眼睛中心的矢量和v2是前一个矢量。 (注意矢量必须标准化)。这会给你角度的相对变化,而不是绝对角度。交叉产品是'v1.x * v2.y - v1.y * v2.x' – Blindman67