当用户使用jQuery单击按钮时,我想要一个接一个地调用一个函数。我在点击事件中使用了一个回调函数,如下所示:
$(document).ready(function() {
var form = $('form');
function scaleUp(callback){
var pageWidth = $('.container').width();
var formWidth = form.width();
var scaleX = pageWidth*.8 / formWidth;
var scaleamount;
if (pageWidth * .8 < 1200){
scaleamount = 1.2;
}else if(pageWidth * .8 < 1900){
scaleamount = 1.8;
}
else{
scaleamount = 2;
}
var scaleY = scaleX / scaleamount;
form.attr('style', 'transform:scale(' + scaleX + ',' + scaleY + ');transition : transform 1.5s ease;'
);
return true;
};
function getPos(){
var formTop = form.position().top;
var formLeft = form.position().left;
console.log(formLeft);
};
$('.button').click(function(){
scaleUp(getPos());
});
});
但是我总是得到旧的位置值,而不是表单转换后的新位置值。有什么想法吗?
JSfiddle:https://jsfiddle.net/k3j910ny/1/
答案 0 :(得分:1)
常规的ol'回调不起作用,因为CSS转换是异步的。
旧答案使用jQuery承诺。但是,有一个名为transitionend
的事件可以添加到表单中。基本上,当CSS转换完成时,它会发出transitionend
偶数。然后,当转换结束时,表单可以调用getPos
。这比使用jQuery promise更好。
var form = $('form');
console.log("The old left pos is:" + form.position().left);
function scaleUp() {
var pageWidth = $('.container').width();
var formWidth = form.width();
var scaleX = pageWidth * 0.8 / formWidth;
var scaleamount;
if (pageWidth * 0.8 < 1200) {
scaleamount = 1.2;
} else if (pageWidth * 0.8 < 1900) {
scaleamount = 1.8;
} else {
scaleamount = 2;
}
var scaleY = scaleX / scaleamount;
form.attr('style', 'transform:scale(' + scaleX + ',' + scaleY + ');transition : transform 1.5s ease;');
}
form.on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function(e) {
if(e.originalEvent.propertyName.toLowerCase() === 'transform') {
return getPos();
}
});
function getPos() {
var formTop = form.position().top;
var formLeft = form.position().left;
console.log("The new left pos is:" + form.position().left);
}
$('button').on('click', scaleUp);
见jsfiddle。它使用jQuery承诺:
var form = $('form');
console.log("The old left pos is:" + form.position().left);
function scaleUp() {
var deferred = $.Deferred();
var pageWidth = $('.container').width();
var formWidth = form.width();
var scaleX = pageWidth * 0.8 / formWidth;
var scaleamount;
if (pageWidth * 0.8 < 1200) {
scaleamount = 1.2;
} else if (pageWidth * 0.8 < 1900) {
scaleamount = 1.8;
} else {
scaleamount = 2;
}
var scaleY = scaleX / scaleamount;
form.attr('style', 'transform:scale(' + scaleX + ',' + scaleY + ');transition : transform 1.5s ease;');
setTimeout(function() {
deferred.resolve();
}, 1600); // needs to wait for the animation to complete
return deferred.promise()
}
function getPos() {
var formTop = form.position().top;
var formLeft = form.position().left;
console.log("The new left pos is:" + form.position().left);
}
$('button').on('click', function () {
$.when(scaleUp()).then(getPos);
});
动画是异步发生的,因此有一个setTimeout
可以在动画完成后稍微解析一个承诺。一旦承诺解决,$.when
就会调用getPos
。这有点像hacky,但这是因为改变style
属性并给它一个CSS动画的异步性。
换句话说,因为动画是异步的,所以在调用回调并获得新位置之前,需要等待它完成。 Promise等待异步事件完成,然后调用回调。
如果您不熟悉承诺,我建议您阅读有关该主题的jQuery docs,并在Google上搜索“javascript promises”。这是另一个主题。
您将函数的被调用版本作为回调传递(并且在scaleUp
中您甚至从未使用过回调),因此它不会将回调视为函数引用。
这样做:
function scaleUp(callback) {
// all your code... then
return callback(); // or just callback() without the return
}
$('.button').on('click', scaleUp.bind(null, getPos));
如果您传入getPos()
,则传递getPos
的返回值,而不是函数引用本身。顺便说一句,上面的点击处理程序是缩写。你也可以这样做:
$('button').on('click', function() {
scaleUp(getPos);
});
答案 1 :(得分:1)
你没有使用回调。您首先调用getPos()
并将结果传递给scaleUp
。然后在scaleUp
内,您实际上并没有使用该结果执行任何操作。
如果您希望它成为回调,只需传递函数参考:
scaleUp(getPos);
然后,在scaleUp
内,调用函数:
calllback();
当然,由于你没有做任何异步事情,你不需要做所有这些。只需在进行缩放后调用函数:
scaleUp();
getPos();