我正试图在转换的进度(而不是时间)中途触发一个事件。这听起来很简单,但由于过渡可以有任何曲线,因此非常棘手。在我的特殊情况下,它不会被暂停或任何其他因素,以免考虑。
(简体)基本上我可以在这样的修饰符上触发动画:
function scaleModifierTo(stateModifier, scale, animationDuration) {
stateModifier.setTransform(
Transform.scale(scale, scale, scale),
{
duration: animationDuration,
curve: this.options.curve
}
);
}
当Transitionable的插值状态达到0.5(中途)时,我想触发一个功能。
我还没有深入挖掘famo.us的来源,但可能需要做类似的事情
setTimeout
(或尝试使用所选曲线算法(ew)的几次迭代找到接近度)是否可以轻松完成此操作?我应该走哪条路?
答案 0 :(得分:2)
我可以想到几种方法来实现这一点,并且都可以使用Modifier over StateModifier。如果你是新手,并且还没有机会探索差异,Modifier会从transformFrom方法中消耗状态,该方法接受一个返回变换的函数。这是我们可以使用我们自己的Transitionable在我们的修饰符的生命周期内提供状态。
为了达到你想要的效果,我使用了一个带有基本transformFrom的Modifier,它将根据Transitionable的值改变曲面的X位置。然后,我可以监视可转换的以确定它何时最接近,或者在我的情况下大于或等于最终值的一半。 prerender函数将在引擎的每个tick上被调用和检查,并且在我们击中目标时被解除绑定。
这是一个例子..
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var Transform = require('famous/core/Transform');
var Transitionable = require('famous/transitions/Transitionable');
var SnapTransition = require('famous/transitions/SnapTransition');
Transitionable.registerMethod('snap',SnapTransition);
var snap = { method:'snap', period:1000, damping:0.6};
var context = Engine.createContext();
var surface = new Surface({
size:[200,200],
properties:{
backgroundColor:'green'
}
});
surface.trans = new Transitionable(0);
surface.mod = new Modifier();
surface.mod.transformFrom(function(){
return Transform.translate(surface.trans.get(),0,0);
});
context.add(surface.mod).add(surface);
function triggerTransform(newValue, transition) {
var prerender = function(){
var pos = surface.trans.get();
if (pos >= (newValue / 2.0)) {
// Do Something.. Emit event etc..
console.log("Hello at position: "+pos);
Engine.removeListener('prerender',prerender);
}
}
Engine.on('prerender',prerender);
surface.trans.halt();
surface.trans.set(newValue,transition);
}
surface.on('click',function(){ triggerTransform(400, snap); });
此示例的缺点是您要查询可转换的两次。另一种方法是在transformFrom方法中添加可转换检查权限。这可能有点奇怪,但基本上我们正在修改transformFrom方法,直到我们达到目标值,然后我们恢复到原来的transformFrom方法.. triggerTransform将定义如下..
希望这有帮助!
function triggerTransform(newValue, transition) {
surface.mod.transformFrom(function(){
pos = surface.trans.get()
if (pos >= newValue/2.0) {
// Do something
console.log("Hello from position: " + pos)
surface.mod.transformFrom(function(){
return Transform.translate(surface.trans.get(),0,0);
});
}
return Transform.translate(pos,0,0)
})
surface.trans.set(newValue,transition);
}
答案 1 :(得分:0)
感谢您的回复,尤其是prerender
事件的@johntraver,我不知道该事件是否存在。
我意识到我应该与我的移动动画一起处理这个逻辑更有意义,而不是规模之一。然后,我最终使用(非常hacky)方式访问转换的当前状态,并通过在px中定义阈值,我可以在需要时触发我的函数。
/**
* Move view at index to a specified offset
* @param {Number} index
* @param {Number} xOffset xOffset to move to
* @param {Object} animation Animation properties
* @return void
*/
function moveView(index, xOffset, animation) {
var rectModifier = this._views[index].modifiers.rect;
var baseXOffset = rectModifier._transformState.translate.state[0];
// After how long movement is reflow needed?
// for the sake of this example I use half the distance of the animation
var moveThreshold = Math.abs(baseXOffset - xOffset)/2;
/**
* Callback function triggered on each animation frame to see if the view is now covering
* the opposite so we can trigger a reflow of the z index
* @return void
*/
var prerender = function() {
var numPixelsMoved = Math.abs(baseXOffset - rectModifier._transformState.translate.state[0]);
if (numPixelsMoved > moveThreshold) {
Engine.removeListener('prerender', prerender);
// trigger a method when this is reached
_reflowZIndex.call(this);
}
}.bind(this);
rectModifier.setTransform(
Transform.translate(xOffset, 0, 0),
animation,
function() {
Engine.removeListener('prerender', prerender);
}
);
Engine.on('prerender', prerender);
}
显然._transformState.translate.state[0]
是一个完整的黑客攻击,但是如果不添加我自己的Transitionable
,我就无法想象得到这个值。 如果有更简洁的方法可以在Number
- 0.0
之间找到当前状态1.0
,那将是王牌;有人知道吗?