5
// t: current time, b: begInnIng value, c: change In value, d: duration

def: 'easeOutQuad',
swing: function (x, t, b, c, d) {
    //alert(jQuery.easing.default);
    return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
},
easeInQuad: function (x, t, b, c, d) {
    return c*(t/=d)*t + b;
},
easeOutQuad: function (x, t, b, c, d) {
    return -c *(t/=d)*(t-2) + b;
},

我正在尝试将 Robert Penner 的缓动函数转换为 python 并卡住了!有任何帮助或其他人以前做过吗?

https://github.com/danro/jquery-easing/blob/master/jquery.easing.js

4

5 回答 5

6

在 JavaScript 和 Python 中,/=都是“增强赋值”运算符,含义几乎相同。

在 JS 中:

var i = 10;
i /= 2;

… 相当于:

var i = 10;
i = i / 2;

并且,在 Python 中:

i = 10
i /= 2

……同样等价于(不完全相同,但对于数字来说足够接近):

i = 10
i = i / 2

但是,有一个非常大的区别。

在 JavaScript 中,赋值是一个表达式——它有一个值,这个值就是赋给变量的值。所以:

var i = 10;
var j = i /= 2;

……大致相当于:

var i = 10;
i /= 2;
var j = i;

在 Python 中,赋值是一个语句。它没有值,也不能在表达式中使用。所以:

i = 10
j = i /= 2

... 提出一个SyntaxError.


移植在表达式中间使用赋值(增强或其他方式)的代码通常需要将该表达式分成多行和/或找到一种方法来重写表达式以不需要任何赋值。(但通常,这不是一件坏事,因为原来的表达方式本来就不是很可读……)

例如,假设 JS 从左到右评估操作数(我不确定是否保证?):

def easeInQuad(x, t, b, c, d):
    t /= d
    return c*t*t+b

更一般地说,你这样做:

old_t = t
t /= d

然后您将t之前的任何实例t/=d替换为old_t,并保留所有实例 fromt/=d和 later 单独。幸运的是,在这种情况下,没有以前的实例,所以我们不需要那些old_t东西。

而且,如果您考虑一下,您可以t通过以下任何一种方式轻松获得相同的效果,而无需在一行中进行更改,并且更具可读性:

return c * (t/d) * (t/d) + b
return c * (t/d)**2 + b
return c * t*t / d*d + b

用 C 语言思考的人会立即抱怨这些都“太慢”。毕竟,第一个执行额外的除法,第二个执行取幂而不是乘法,第三个执行两次乘法而不是一次。恐怖!

当然,您始终可以使用临时变量:

t_over_d = t/d
return c * t_over_d * t_over_d + b

……但同样,对于 C 程序员来说,这意味着您正在用完一个有价值的寄存器。当然,在 1985 年之后编写的每个编译器都会t在出现时立即检测到已死t_over_d并重用相同的寄存器,但如果可以的话,为什么不强制它重用寄存器,特别是如果它也节省了几次击键呢?

在 JS 或 Python 中,乘法的成本只是调用函数和解释字节码等成本的一小部分,你甚至都不会注意到它。同时,重新绑定局部变量的成本(尤其是在 V8 风格或 PyPy 风格的 JIT 解释器中)可能比传递一个未命名的临时结果的成本要高得多。

因此,这是一个误导性“优化”的范例案例,使代码更难理解,同时可能会减慢而不是加快速度,并且在一个无论如何都不可能成为值得优化的瓶颈的领域。


由于 gnibbler 提出了 JavaScript 是否确实保证了这种评估顺序的问题……</p>

首先,JavaScript 被有效地定义为“Firefox 所做的事情”(和“Spidermonkey 所做的事情”,但这应该是同一件事——如果不是,那么 JavaScript 做了两件事,所以好两倍, 对?)。但是 ECMAScript由标准定义的,而且每个 JS 实现(不管名称)都在口头上支持这些标准,我们可以假装 ECMAScript 5.1 是所有实现都遵循的标准(只要“所有实现"的意思是“歌剧”)。你可以在这里找到它。

因此,在 ES 5.1 中:11.5 乘法运算符保证 的结果(t/=d)将在 之前评估t,而11.13.2 复合赋值保证评估将在其完成之前t/=d设置值。t(您必须阅读“评估”GetValue的含义和SetValue含义,但我很确定这确实得到了保证。)

于 2013-03-20T22:24:16.580 回答
1

/=是增广赋值运算符。t /= d是一样的t = t / d+=, -=, 并且*=还存在,等等……

于 2013-03-20T22:17:21.650 回答
1

好吧,它是一个速记运算符,就像除+=而不是添加它。这是长表格

t = t / d
于 2013-03-20T22:17:49.357 回答
1
c*(t/=d)*t + b;

相当于

t /= d            # or t = t / d
c * t * t + b

因为 Python 不能在表达式内部赋值

请记住,如果td都是int/ long,这将是 Python2 中的截断除法

同样easeOutQuad会是

def easeOutQuad (x, t, b, c, d):
    t /= d
    return -c * t * (t - 2) + b
于 2013-03-20T22:17:52.113 回答
0

划分和分配。

>>> p = 6
>>> p /= 2
>>> p
3
于 2013-03-20T22:16:59.980 回答