Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在鼠标移动事件后轻松旋转画布对象?_Javascript_Html_Html5 Canvas - Fatal编程技术网

Javascript 如何在鼠标移动事件后轻松旋转画布对象?

Javascript 如何在鼠标移动事件后轻松旋转画布对象?,javascript,html,html5-canvas,Javascript,Html,Html5 Canvas,我不确定我在这里用的词是否正确。我猜放松意味着它不会立即跟随鼠标,而是会有一些延迟 此时虹膜正朝着我的鼠标方向旋转。如果我想让它有和…一样的效果呢?。是很难做到这一点,还是仅仅需要简单的代码更改?这类问题有没有标准的解决方法 这是我目前的代码。也可在以下网址找到 var canvas=document.getElementById('canvas'); var ctx=canvas.getContext('2d'); canvas.width=window.innerWidth; canvas

我不确定我在这里用的词是否正确。我猜放松意味着它不会立即跟随鼠标,而是会有一些延迟

此时虹膜正朝着我的鼠标方向旋转。如果我想让它有和…一样的效果呢?。是很难做到这一点,还是仅仅需要简单的代码更改?这类问题有没有标准的解决方法

这是我目前的代码。也可在以下网址找到

var canvas=document.getElementById('canvas');
var ctx=canvas.getContext('2d');
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
班级圈子{
构造函数(选项){
this.cx=options.x;
this.cy=options.y;
this.radius=options.radius;
this.color=options.color;
this.angle=options.angle;
这是binding();
}
绑定(){
const self=这个;
window.addEventListener('mousemove',(e)=>{
自计算角(e);
});
}
计算角(e){
如果(!e)返回;
设rect=canvas.getBoundingClientRect(),
vx=e.clientX-this.cx,
vy=e.clientY-this.cy;
该角度=数学atan2(vy,vx);
}
伦德雷耶(){
setTransform(1,0,0,1,this.cx,this.cy);
ctx.旋转(此角度);
设eyeRadius=this.radius/3;
ctx.beginPath();
ctx.弧(this.radius/2,0,眼半径,0,Math.PI*2);
ctx.fill();
}
render(){
setTransform(1,0,0,1,0,0);
clearRect(0,0,canvas.width,canvas.height);
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();
这个.renderMessage();
这个。renderEye();
}
renderMessage(){
ctx.font=“18px serif”;
ctx.strokeStyle=‘黑色’;
ctx.fillText('Angle:'+this.Angle,30,canvas.height-40);
}
}
var rotatingCircle=新圆({
x:320,
y:160,
半径:40,
颜色:'黑色',
角度:Math.random()*Math.PI*2
});
函数animate(){
旋转圆。渲染();
请求动画帧(动画);
}
制作动画()

据我所知,使用h5 canvas,您可能需要自己编写ease函数。但是,css3动画有几个内置的ease函数,您可以编写
.foo{transition:bottom1s ease}
,当
.foo
元素
bottom
样式属性更改时,它们将以
ease
函数定义的速度移动。请参阅:


还有,看看这些令人惊叹的动画BB-8(用css动画制作):

有很多方法可以轻松地完成。我将简要描述的两种方法是确定性放松和(令人惊讶的)非确定性放松。区别在于,ease的目的地要么已知(已确定),要么未知(等待更多用户输入)

确定性宽松。

为此,您有一个起始值和一个结束值。您要做的是根据某个时间值在两者之间找到一个位置。这意味着开始值和结束值也需要与时间关联

比如说

var startVal = 10;
var startTime = 100;
var endVal = 100;
var endTime = 200;
您将希望在时间150处找到介于两者之间的值。为此,将时间转换为分数,其中时间100(开始)返回0,时间200(结束)返回1,我们称之为标准化时间。然后,可以将起始值和结束值之间的差值乘以该分数,以找到偏移量

因此,对于时间值150,要获得该值(theValue),我们执行以下操作

var time = 150;
var timeDif = endTime - startTime
var fraction = (startTime - time) / timeDif; // the normalised time
var valueDif = endVal - startVal;
var valueOffset = valueDif * fraction;
var theValue = startVal + valueOffset;
或者更简洁

// nt is normalised time
var nt = (startTime - time) / (endTime - startTime)
var theValue = startVal + (endVal - startVal) * nt;
现在,我们需要修改标准化时间来实施宽松政策。缓和函数只需获取0到1(含0到1)之间的值并对其进行修改。因此,如果输入0.25,缓和函数返回0.1,或0.5返回0.5,0.75返回0.9。正如您所见,修改会随时间改变变化率

缓和函数的示例

var easeInOut = function (n, pow) {
    n = Math.min(1, Math.max(0, n)); // clamp n
    var nn = Math.pow( n, pow);
    return (nn / ( nn + Math.pow(1 - n, pow)))
}
此函数接受两个输入,分数n(0到1,包括0到1)和幂。权力决定了缓和的程度。如果pow=1,则表示不缓和,函数返回n。如果pow=2,则该函数与CSS ease in-out函数相同,开始时缓慢加速,最后减慢。如果pow<1且pow>0,则ease start会在中途快速减速,然后加速到终点

在上述缓和值示例中使用缓和函数

// nt is normalised time
var nt = (startTime - time) / (endTime - startTime);
nt = easeInOut(nt,2); // start slow speed up, end slow
var theValue = startVal + (endVal - startVal) * nt;
这就是确定性宽松的做法

一个优秀的放松功能页面和代码,另一个页面

非确定性宽松

您可能不知道缓解功能的最终结果是什么,因为在任何时候,它可能会因新的用户输入而改变,如果您使用上述方法并在缓解过程中改变最终值,结果将是不一致和丑陋的。如果你做过微积分,你可能会认识到上面的ease函数是一个多项式,因此是一个简单函数的反导数。此函数仅确定每个时间步的更改量。所以对于非确定性解,我们所知道的只是下一时间步的变化。为了简化功能(在接近目的地时快速启动并减速),我们保留一个值来表示当前速度(变化率),并根据需要修改该速度

const ACCELERATION_COEFFICIENT = 0.3;
const DRAG_COEFFICIENT = 0.99;
var currentVal = 100;
var destinationVal = 200;
var currentSpeed = 0;
然后对每个时间步骤执行以下操作

var accel = destinationVal - currentVal;  // get the acceleration
accel *= ACCELERATION_COEFFICIENT; // modify it so we are not there instantly
currentSpeed += accel; // add that to the speed
currentSpeed *= DRAG_COEFFICIET; // add some drag to further ease the function as it approaches destination
currentVal += currentSpeed; // add the speed to the current value
现在currentVal将接近目标值,如果目标发生变化,则变化率(速度)也会以一致的方式发生变化。如果目的地一直在变化,则currentVal可能永远无法到达目的地,但是如果目的地停止变化,则当前val将接近并最终在目的地停止(我所说的停止是指速度将变得如此之小,以至于毫无意义)