在the following demo(仅限WebKit)中,我不明白为什么在CSS部分中为一个转换属性进行双翻译和旋转。
transform: translate(100px, 100px) rotate(45deg) translate(-100px, -100px) rotate(-45deg);
这真是一个奇怪的例子。为什么圆圈会这样移动?
完整演示:
// NOTE: The change to red signifies the start of
// the animation
// Allows elements to be accessed in a clean way
var circle = document.getElementById('circle'),
button = document.getElementById('button');
// Gets element to show current percentage
var result = document.getElementById('result'),
// Current position of circle around its path
// in percent in reference to the original
totalCurrentPercent = 0,
// Percent of circle around its path in
// percent in reference to the latest origin
currentPercent = 0;
// Updates the percent change from the latest origin
var showPercent = window.setInterval(function() {
if(currentPercent < 100)
{
currentPercent += 1;
}
else {
currentPercent = 0;
}
result.innerHTML = currentPercent;
}, 39); // Runs at a rate based on the animation's
// duration (milliseconds / 100)
// Checks to see if the specified rule is within
// any of the stylesheets found in the document;
// returns the animation object if so
function findKeyframesRule(rule) {
var ss = document.styleSheets;
for (var i = 0; i < ss.length; ++i) {
for (var j = 0; j < ss[i].cssRules.length; ++j) {
if (ss[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && ss[i].cssRules[j].name == rule) { return ss[i].cssRules[j]; }
}
}
return null;
}
// Replaces the animation based on the percent
// when activated and other hard coded
// specifications
function change(anim) {
// Obtains the animation object of the specified
// animation
var keyframes = findKeyframesRule(anim),
length = keyframes.cssRules.length;
// Makes an array of the current percent values
// in the animation
var keyframeString = [];
for(var i = 0; i < length; i ++)
{
keyframeString.push(keyframes[i].keyText);
}
// Removes all the % values from the array so
// the getClosest function can perform calculations
var keys = keyframeString.map(function(str) {
return str.replace('%', '');
});
// Updates the current position of the circle to
// be used in the calculations
totalCurrentPercent += currentPercent;
if(totalCurrentPercent > 100)
{
totalCurrentPercent -= 100;
}
// Self explanatory variables if you read the
// description of getClosest
var closest = getClosest(keys);
var position = keys.indexOf(closest),
firstPercent = keys[position];
// Removes the current rules of the specified
// animation
for(var i = 0, j = keyframeString.length; i < j; i ++)
{
keyframes.deleteRule(keyframeString[i]);
}
// Turns the percent when activated into the
// corresponding degree of a circle
var multiplier = firstPercent * 3.6;
// Essentially this creates the rules to set a new
// origin for the path based on the approximated
// percent of the animation when activated and
// increases the diameter of the new circular path
keyframes.insertRule("0% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 0) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 0) + "deg); background-color:red; }");
keyframes.insertRule("13% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 45) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 45) + "deg); }");
keyframes.insertRule("25% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 90) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 90) + "deg); }");
keyframes.insertRule("38% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 135) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 135) + "deg); }");
keyframes.insertRule("50% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 180) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 180) + "deg); }");
keyframes.insertRule("63% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 225) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 225) + "deg); }");
keyframes.insertRule("75% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 270) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 270) + "deg); }");
keyframes.insertRule("88% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 315) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 315) + "deg); }");
keyframes.insertRule("100% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 360) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 360) + "deg); }");
// Shows the circle again
circle.style.display = "inherit";
// Sets the animation to the newly specified rules
circle.style.webkitAnimationName = anim;
// Resets the approximate animation percent counter
window.clearInterval(showPercent);
currentPercent = 0;
showPercent = self.setInterval(function() {
if(currentPercent < 100)
{
currentPercent += 1;
}
else {
currentPercent = 0;
}
result.innerHTML = currentPercent;
}, 39);
}
// Attatches the change function to the button's
// onclick function
button.onclick = function() {
// Removes the animation so a new one can be set
circle.style.webkitAnimationName = "none";
// Temporarily hides the circle
circle.style.display = "none";
// Initializes change function
setTimeout(function () {
change("rotate");
}, 0);
}
// Gets the animation's closest % value based on
// the approximated % found below
function getClosest(keyframe) {
var curr = keyframe[0];
var diff = Math.abs (totalCurrentPercent - curr);
for (var val = 0, j = keyframe.length; val < j; val++) {
var newdiff = Math.abs(totalCurrentPercent - keyframe[val]);
if (newdiff < diff) {
diff = newdiff;
curr = keyframe[val];
}
}
return curr;
}
// Check out http://zachsaucier.com/ for more of my projects
&#13;
@-webkit-keyframes rotate {
0% {
-webkit-transform:translate(100px, 100px) rotate(0deg) translate(-100px, -100px) rotate(0deg);
background-color:red;
}
13% {
-webkit-transform:translate(100px, 100px) rotate(45deg) translate(-100px, -100px) rotate(-45deg);
}
25% {
-webkit-transform:translate(100px, 100px) rotate(90deg) translate(-100px, -100px) rotate(-90deg);
}
38% {
-webkit-transform:translate(100px, 100px) rotate(135deg) translate(-100px, -100px) rotate(0deg);
}
50% {
-webkit-transform:translate(100px, 100px) rotate(180deg) translate(-100px, -100px) rotate(-180deg);
}
63% {
-webkit-transform:translate(100px, 100px) rotate(225deg) translate(-100px, -100px) rotate(225deg);
}
75% {
-webkit-transform:translate(100px, 100px) rotate(270deg) translate(-100px, -100px) rotate(-270deg);
}
88% {
-webkit-transform:translate(100px, 100px) rotate(315deg) translate(-100px, -100px) rotate(315deg);
}
100% {
-webkit-transform:translate(100px, 100px) rotate(360deg) translate(-100px, -100px) rotate(-360deg);
}
}
#circle {
height: 50px;
width: 50px;
border-radius:25px;
background-color: teal;
-webkit-animation-duration: 4s;
-webkit-animation-timing-function: linear;
-webkit-animation-name:"rotate";
-webkit-animation-iteration-count: infinite;
position:absolute;
left:30%;
top:20%;
}
#button {
width:130px;
background:teal;
}
&#13;
<div id="circle"></div>
<div id='button'>ChangeAnimation</div>
<div id='result'></div>
&#13;
答案 0 :(得分:3)
首先,transform
属性的值是<transform-function>
的列表。如果提供了<transform-function>
的列表,则净效果就好像每个转换函数已按提供的顺序单独指定。例如:
<div style="transform: translate(100px, 100px) rotate(45deg) translate(-100px, -100px) rotate(45deg)">
</div>
在功能上等同于:
<div style="transform: translate(100px, 100px)">
<div style="transform: rotate(45deg)">
<div style="transform: translate(-100px, -100px)">
<div style="transform: rotate(45deg)">
</div>
</div>
</div>
</div>
对于一个转换属性的两个转换和旋转的实现,它是为了获得一个圆形动画。
简单地说,第一个translate
定义圆形路径的中心,第一个rotate
定义X轴的角度,第二个translate
定义半径,第二个rotate
定义半径error-channel
是让图形在其轴上旋转。
请查看the article以更详细地了解一个简单示例。