带有jquery.animate()的CSS跨浏览器旋转
我正在创建一个跨浏览器兼容的旋转(ie9+),我在一个 CSS和HTML非常简单,仅用于演示:带有jquery.animate()的CSS跨浏览器旋转,jquery,css,rotation,jquery-animate,Jquery,Css,Rotation,Jquery Animate,我正在创建一个跨浏览器兼容的旋转(ie9+),我在一个 CSS和HTML非常简单,仅用于演示: .SomeDiv{ width:50px; height:50px; margin:50px 50px; background-color: red;} <div id="MyDiv1" class="SomeDiv">test</div> <div id="MyDiv2" class="SomeDiv">test&l
.SomeDiv{
width:50px;
height:50px;
margin:50px 50px;
background-color: red;}
<div id="MyDiv1" class="SomeDiv">test</div>
<div id="MyDiv2" class="SomeDiv">test</div>
.SomeDiv{
宽度:50px;
高度:50px;
保证金:50px 50px;
背景色:红色;}
测试
测试
旋转在使用.css()
时有效,但在使用.animate()
时无效;为什么会这样?有没有办法解决
谢谢。CSS转换还不能用jQuery来制作动画。您可以这样做:
function AnimateRotate(angle) {
// caching the object for performance reasons
var $elem = $('#MyDiv2');
// we use a pseudo object for the animation
// (starts from `0` to `angle`), you can name it as you want
$({deg: 0}).animate({deg: angle}, {
duration: 2000,
step: function(now) {
// in the step-callback (that is fired each step of the animation),
// you can use the `now` paramter which contains the current
// animation-position (`0` up to `angle`)
$elem.css({
transform: 'rotate(' + now + 'deg)'
});
}
});
}
您可以在此处阅读有关步骤回调的更多信息:
另外,顺便说一句:您不需要使用jQuery1.7作为css3转换的前缀+
更新
您可以将其封装在jQuery插件中,使您的生活更轻松:
$.fn.animateRotate = function(angle, duration, easing, complete) {
return this.each(function() {
var $elem = $(this);
$({deg: 0}).animate({deg: angle}, {
duration: duration,
easing: easing,
step: function(now) {
$elem.css({
transform: 'rotate(' + now + 'deg)'
});
},
complete: complete || $.noop
});
});
};
$('#MyDiv2').animateRotate(90);
更新2
我对它进行了一些优化,使放松
、持续时间
和完成
的顺序变得无关紧要
$.fn.animateRotate = function(angle, duration, easing, complete) {
var args = $.speed(duration, easing, complete);
var step = args.step;
return this.each(function(i, e) {
args.complete = $.proxy(args.complete, e);
args.step = function(now) {
$.style(e, 'transform', 'rotate(' + now + 'deg)');
if (step) return step.apply(e, arguments);
};
$({deg: 0}).animate({deg: angle}, args);
});
};
更新2.1
感谢世卫组织在完整的-回调
中指出了此
上下文的问题。如果通过在每个节点上将回调与jQuery.proxy
绑定来修复它
我以前从更新2将该版本添加到代码中
更新2.2
如果您想前后切换旋转,这是一个可能的修改。我只是在函数中添加了一个start参数,并替换了这一行:
$({deg: start}).animate({deg: angle}, args);
如果有人知道如何使此更通用于所有用例,无论他们是否想要设置开始程度,请进行适当的编辑
用法…非常简单! 主要有两种方法可以达到预期的效果。但首先,让我们来看看这些论点:
jQuery.fn.animateRotate(角度、持续时间、放松、完成)
除了“angle”之外,所有属性都是可选的,并返回到默认的jQuery.fn.animate
-属性:
duration: 400
easing: "swing"
complete: function () {}
第一
这是一个简短的方法,但我们传递的论点越多,它看起来就有点不清楚
$(node).animateRotate(90);
$(node).animateRotate(90, function () {});
$(node).animateRotate(90, 1337, 'linear', function () {});
第二
如果有三个以上的参数,我更喜欢使用对象,因此我最喜欢这种语法:
$(node).animateRotate(90, {
duration: 1337,
easing: 'linear',
complete: function () {},
step: function () {}
});
如果您通过jQuery处理CSS3动画,可能会使您的生活更轻松
编辑2014年3月
(因为我的建议自发布以来,一直被投赞成票和反对票)
让我解释一下为什么我最初暗示要使用上面的插件:
在每个步骤上更新DOM
(即$.animate
)在性能方面并不理想。
它可以工作,但很可能比纯的或纯的更慢
这主要是因为,如果您指出从开始到结束的过渡将是什么样子,浏览器就有机会提前思考
为此,例如,您可以为转换的每个状态创建一个CSS类,并且只使用jQuery切换动画状态
这通常非常简洁,因为您可以将动画与CSS的其余部分一起调整,而不是将其与业务逻辑混淆:
// initial state
.eye {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
transform: rotate(45deg);
// etc.
// transition settings
-webkit-transition: -webkit-transform 1s linear 0.2s;
-moz-transition: -moz-transform 1s linear 0.2s;
transition: transform 1s linear 0.2s;
// etc.
}
// open state
.eye.open {
transform: rotate(90deg);
}
// Javascript
$('.eye').on('click', function () { $(this).addClass('open'); });
如果任何变换参数是动态的,则当然可以使用“样式”属性:
$('.eye').on('click', function () {
$(this).css({
-webkit-transition: '-webkit-transform 1s ease-in',
-moz-transition: '-moz-transform 1s ease-in',
// ...
// note that jQuery will vendor prefix the transform property automatically
transform: 'rotate(' + (Math.random()*45+45).toFixed(3) + 'deg)'
});
});
关于这个问题有很多更详细的信息
然而还有一些其他的事情需要记住,如果你有复杂的动画、链接等,并且只是在引擎盖下做所有棘手的事情,所有这些都会变得有点棘手:
$('.eye').transit({ rotate: '90deg'}); // easy huh ?
谢谢你,卡丁车!伟大的贡献。我把你的插件充实了一点。为完全控制和跨浏览器css添加了startAngle
$.fn.animateRotate = function(startAngle, endAngle, duration, easing, complete){
return this.each(function(){
var elem = $(this);
$({deg: startAngle}).animate({deg: endAngle}, {
duration: duration,
easing: easing,
step: function(now){
elem.css({
'-moz-transform':'rotate('+now+'deg)',
'-webkit-transform':'rotate('+now+'deg)',
'-o-transform':'rotate('+now+'deg)',
'-ms-transform':'rotate('+now+'deg)',
'transform':'rotate('+now+'deg)'
});
},
complete: complete || $.noop
});
});
};
要完成包括IE7+在内的跨浏览器操作,您需要使用转换矩阵扩展插件。由于供应商前缀是在jQuery-1.8+中的jQuery中完成的,因此我将在
transform
属性中省略它
$.fn.animateRotate = function(endAngle, options, startAngle)
{
return this.each(function()
{
var elem = $(this), rad, costheta, sintheta, matrixValues, noTransform = !('transform' in this.style || 'webkitTransform' in this.style || 'msTransform' in this.style || 'mozTransform' in this.style || 'oTransform' in this.style),
anims = {}, animsEnd = {};
if(typeof options !== 'object')
{
options = {};
}
else if(typeof options.extra === 'object')
{
anims = options.extra;
animsEnd = options.extra;
}
anims.deg = startAngle;
animsEnd.deg = endAngle;
options.step = function(now, fx)
{
if(fx.prop === 'deg')
{
if(noTransform)
{
rad = now * (Math.PI * 2 / 360);
costheta = Math.cos(rad);
sintheta = Math.sin(rad);
matrixValues = 'M11=' + costheta + ', M12=-'+ sintheta +', M21='+ sintheta +', M22='+ costheta;
$('body').append('Test ' + matrixValues + '<br />');
elem.css({
'filter': 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\'auto expand\','+matrixValues+')',
'-ms-filter': 'progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\'auto expand\','+matrixValues+')'
});
}
else
{
elem.css({
//webkitTransform: 'rotate('+now+'deg)',
//mozTransform: 'rotate('+now+'deg)',
//msTransform: 'rotate('+now+'deg)',
//oTransform: 'rotate('+now+'deg)',
transform: 'rotate('+now+'deg)'
});
}
}
};
if(startAngle)
{
$(anims).animate(animsEnd, options);
}
else
{
elem.animate(animsEnd, options);
}
});
};
另请参见此演示
更新:您现在还可以在选项中传递extra:{}
。这将使您能够同时执行其他动画。例如:
obj.animateRotate(90, {extra: {marginLeft: '100px', opacity: 0.5}});
这将使元素旋转90度,并以100px的速度向右移动,使其在动画中同时半透明。这是我的解决方案:
var matrixRegex = /(?:matrix\(|\s*,\s*)([-+]?[0-9]*\.?[0-9]+(?:[e][-+]?[0-9]+)?)/gi;
var getMatches = function(string, regex) {
regex || (regex = matrixRegex);
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[1]);
}
return matches;
};
$.cssHooks['rotation'] = {
get: function(elem) {
var $elem = $(elem);
var matrix = getMatches($elem.css('transform'));
if (matrix.length != 6) {
return 0;
}
return Math.atan2(parseFloat(matrix[1]), parseFloat(matrix[0])) * (180/Math.PI);
},
set: function(elem, val){
var $elem = $(elem);
var deg = parseFloat(val);
if (!isNaN(deg)) {
$elem.css({ transform: 'rotate(' + deg + 'deg)' });
}
}
};
$.cssNumber.rotation = true;
$.fx.step.rotation = function(fx) {
$.cssHooks.rotation.set(fx.elem, fx.now + fx.unit);
};
然后可以在默认的动画fkt中使用它:
//rotate to 90 deg cw
$('selector').animate({ rotation: 90 });
//rotate to -90 deg ccw
$('selector').animate({ rotation: -90 });
//rotate 90 deg cw from current rotation
$('selector').animate({ rotation: '+=90' });
//rotate 90 deg ccw from current rotation
$('selector').animate({ rotation: '-=90' });
不带带setInterval的插件跨浏览器:
function rotatePic() {
jQuery({deg: 0}).animate(
{deg: 360},
{duration: 3000, easing : 'linear',
step: function(now, fx){
jQuery("#id").css({
'-moz-transform':'rotate('+now+'deg)',
'-webkit-transform':'rotate('+now+'deg)',
'-o-transform':'rotate('+now+'deg)',
'-ms-transform':'rotate('+now+'deg)',
'transform':'rotate('+now+'deg)'
});
}
});
}
var sec = 3;
rotatePic();
var timerInterval = setInterval(function() {
rotatePic();
sec+=3;
if (sec > 30) {
clearInterval(timerInterval);
}
}, 3000);
另一个答案是,因为jQuery.transit与jQuery.easing不兼容。此解决方案作为jQuery扩展提供。更为通用,旋转是一种特殊情况:
$.fn.extend({
animateStep: function(options) {
return this.each(function() {
var elementOptions = $.extend({}, options, {step: options.step.bind($(this))});
$({x: options.from}).animate({x: options.to}, elementOptions);
});
},
rotate: function(value) {
return this.css("transform", "rotate(" + value + "deg)");
}
});
用法非常简单,如下所示:
$(element).animateStep({from: 0, to: 90, step: $.fn.rotate});
jQuery不知道如何设置旋转的动画。也许使用CSS3转换?@JanDvorak-除了IE9不支持CSS3转换之外。我将投票支持“修复”部分(您可能最终实现了
步骤回调),但“为什么是那个”部分非常清楚。@Spudley:是的,我知道:IE9支持的目标是使用setInterval并多次调用DoRotate函数。顺便说一句,我在回答你的另一个问题时已经指出了CSS沙纸库,这是IE中CSS转换的多边形填充。你可能想试试。你能把它放在小提琴里吗?好的,非常酷:这是用于跨浏览器(IE9+)CSS3旋转的插件!!你可以说:那是你造的。干得好@matteo很抱歉反应太晚,谢谢你的测试。我需要一点时间来解决这个问题,但我成功了!顺便说一句,我在回答中提到了您的调查:)@matteo之所以此
不引用DOM对象,是因为上下文设置为调用对象animate()
,在这种情况下{deg:0}
设置为上下文。您可以通过使用apply()
/call()
或$.proxy()
更改每个回调函数的上下文来解决此问题(如@yckart所示)。下面是我修复所有回调并允许3d旋转的解决方案:如果要反复设置同一元素的动画,每次从0
度开始都不会导致预期的行为,因此需要使用c
$.fn.extend({
animateStep: function(options) {
return this.each(function() {
var elementOptions = $.extend({}, options, {step: options.step.bind($(this))});
$({x: options.from}).animate({x: options.to}, elementOptions);
});
},
rotate: function(value) {
return this.css("transform", "rotate(" + value + "deg)");
}
});
$(element).animateStep({from: 0, to: 90, step: $.fn.rotate});