JavaScript ã¢ãã¡ã¼ã·ã§ã³ã¯ CSS ã§ã¯ã§ããªããã¨ãæ±ããã¨ãã§ãã¾ãã
ä¾ãã°ããã¸ã§æ²ç·ã¨ã¯ç°ãªãã¿ã¤ãã³ã°é¢æ°ãç¨ãã¦è¤éãªçµè·¯ã«æ²¿ã£ã¦ç§»åããããcanvas ä¸ã§ã®ã¢ãã¡ã¼ã·ã§ã³ãªã©ã§ãã
setInterval
HTML/CSS ã®è¦³ç¹ããã¯ãã¢ãã¡ã¼ã·ã§ã³ã¯ã¹ã¿ã¤ã«ããããã£ã®æ®µéçãªå¤æ´ã§ããä¾ãã°ãstyle.left ã 0px ãã 100px ã«å¤æ´ããã¨ãè¦ç´ ãç§»åãã¾ãã
ããã¦ãããããã setInterval ã®ä¸ã§å¢å ãããã¨ããæ¯ç§ 50 åã®å°ããªå¤æ´ãå ãããã¨ã«ãã£ã¦ããã®å¤åã¯ãªãããã«è¦ãã¾ããããã¯æ ç»é¤¨ã¨åãåçã§ãã: æ¯ç§ 24 以ä¸ã®ãã¬ã¼ã ãããã°ååã«æ»ããã«è¦ãã¾ãã
çä¼¼ã³ã¼ãã¯æ¬¡ã®ããã«ãªãã¾ã:
let delay = 1000 / 50; // 1 ç§ã§ 50 ãã¬ã¼ã
let timer = setInterval(function() {
if (animation complete) clearInterval(timer);
else increase style.left
}, delay)
ããè¤éãªã¢ãã¡ã¼ã·ã§ã³ã®ä¾:
let start = Date.now(); // éå§æéãè¦ãã
let timer = setInterval(function() {
// éå§ããã®çµéæéã¯ï¼
let timePassed = Date.now() - start;
if (timePassed >= 2000) {
clearInterval(timer); // 2ç§å¾ã«ã¢ãã¡ã¼ã·ã§ã³ãçµäº
return;
}
// timePassed æç¹ã®ã¢ãã¡ã¼ã·ã§ã³ãæç»
draw(timePassed);
}, 20);
// timePassed 㯠0 ãã 2000 ã¾ã§é²ã
// ãªã®ã§ãleft 㯠0px ãã 400px ã«ãªãã¾ã
function draw(timePassed) {
train.style.left = timePassed / 5 + 'px';
}
ãã¢ã§ããé»è»ãã¯ãªãã¯ãã¦ã¿ã¦ãã ãã:
<!DOCTYPE HTML>
<html>
<head>
<style>
#train {
position: relative;
cursor: pointer;
}
</style>
</head>
<body>
<img id="train" src="https://js.cx/clipart/train.gif">
<script>
train.onclick = function() {
let start = Date.now();
let timer = setInterval(function() {
let timePassed = Date.now() - start;
train.style.left = timePassed / 5 + 'px';
if (timePassed > 2000) clearInterval(timer);
}, 20);
}
</script>
</body>
</html>requestAnimationFrame
è¤æ°ã®ã¢ãã¡ã¼ã·ã§ã³ãåæã«å®è¡ããã¦ããã¨ãã¾ãããã
ããããããå¥ã
ã«å®è¡ãããããããåå¥ã« setInterval(..., 20) ãæã£ã¦ããã¨ããã©ã¦ã¶ã¯ 20ms ééãããã£ã¨é »ç¹ã«åæç»ãããå¿
è¦ãããã¾ãã
å setInterval 㯠20ms æ¯ã«ä¸åããªã¬ãã¾ãããç¬ç«ãã¦ããã®ã§ 20ms ã®ä¸ã«è¤æ°ã®ç¬ç«ããå®è¡ããããã¨ã«ãªãã¾ãã
ãããã®è¤æ°ã®ç¬ç«ããåæç»ã¯ããã©ã¦ã¶ã®åæç»ãç°¡åã«ããCPUã®è² è·ãæ¸ããã¦ãããªãããã«è¦ããããã«ã°ã«ã¼ãåãã¹ãã§ãã
è¨ãæããã¨ã次ã®ã³ã¼ã:
setInterval(function() {
animate1();
animate2();
animate3();
}, 20)
â¦ã¯ä»¥ä¸ã®ã³ã¼ãããã軽éã§ã:
setInterval(animate1, 20);
setInterval(animate2, 20);
setInterval(animate3, 20);
å¿ã«çãã¦ããã¹ããã¨ãããä¸ã¤ããã¾ããCPUãéè² è·ã«ãªã£ã¦ããå ´åãããã®ä»åæç»ããã¾ãããªãã¦è¯ãå ´åãããã¾ã(ãã©ã¦ã¶ã¿ããé表示ã«ãªã£ã¦ãããããªã¨ãï¼ããã®ãããæ¬å½ã¯20msæ¯ã«å®è¡ãã¹ãã§ã¯ããã¾ããã
ããããããã JavaScript ã§ã¯ã©ããã£ã¦ããã®ã§ãããï¼ é¢æ° requestAnimationFrame ãæä¾ããæ¨æºã® ã¢ãã¡ã¼ã·ã§ã³ã¿ã¤ãã³ã° ãããã¾ãããã®é¢æ°ã¯ãããããã¹ã¦ã®åé¡åã³ããã®ä»å¤ãã®ãã¨ã«å¯¾å¿ãã¦ãã¾ãã
æ§æ:
let requestId = requestAnimationFrame(callback)
ããã¯ããã©ã¦ã¶ãã¢ãã¡ã¼ã·ã§ã³ããããæãè¿ãæéã« callback 颿°ãå®è¡ããããã¹ã±ã¸ã¥ã¼ãªã³ã°ãã¾ãã
ãã callback ã®ä¸ã§è¦ç´ ã夿´ããã¨ãä»ã® requestAnimationFrame ã³ã¼ã«ããã¯ã CSS ã¢ãã¡ã¼ã·ã§ã³ã¨ä¸ç·ã«ã°ã«ã¼ãåããã¾ããããã«ãããé
ç½®ã®åè¨ç®ã¨åæç»ãããããã§ã¯ãªã1åã§ã¾ã¨ãã¦è¡ããã¾ãã
è¿å´å¤ requestId ã¯å¼ã³åºãããã£ã³ã»ã«ããã®ã«ä½¿ããã¨ãã§ãã¾ã:
// ã¹ã±ã¸ã¥ã¼ãªã³ã°ãããã³ã¼ã«ããã¯ã®å®è¡ããã£ã³ã»ã«ãã
cancelAnimationFrame(requestId);
callback ã¯1ã¤ã®å¼æ°ãåãã¾ã â ãã¼ã¸ãã¼ãã®éå§ããã®çµéæéã®ãã¤ã¯ãç§ã§ãã
ãã®æé㯠performance.now() ãå¼ã³åºããã¨ã§ãå¾ããã¨ãã§ãã¾ãã
é常 callback 㯠CPU ãéè² è·ç¶æ
ã«ãªã£ããããã¼ãPCã®ããããªã¼ãã»ã¨ãã©ãªãã£ããããã®ä»å¥ã®çç±ãããå ´åãé¤ãããã«å®è¡ããã¾ãã
ä¸ã®ã³ã¼ã㯠requestAnimationFrame ã§ã®æåã®10åã®å®è¡æéã表示ãã¾ããé常㯠10-20ms ã§ãã
<script>
let prev = performance.now();
let times = 0;
requestAnimationFrame(function measure(time) {
document.body.insertAdjacentHTML("beforeEnd", Math.floor(time - prev) + " ");
prev = time;
if (times++ < 10) requestAnimationFrame(measure);
})
</script>
Structured animation
ããã§ãrequestAnimationFrame ã«åºã¥ãããæ§ã
ãªç¶æ³ã«å¯¾å¿ãããã¨ã®ã§ããã¢ãã¡ã¼ã·ã§ã³é¢æ°ã使ãããã¨ãã§ãã¾ãã
function animate({timing, draw, duration}) {
let start = performance.now();
requestAnimationFrame(function animate(time) {
// timeFraction 㯠0 ãã 1 ã«ãªãã¾ã
let timeFraction = (time - start) / duration;
if (timeFraction > 1) timeFraction = 1;
// ç¾å¨ã®ã¢ãã¡ã¼ã·ã§ã³ã®ç¶æ
ãè¨ç®ãã¾ã
let progress = timing(timeFraction)
draw(progress); // æç»ãã¾ã
if (timeFraction < 1) {
requestAnimationFrame(animate);
}
});
}
颿° animate ã¯ã¢ãã¡ã¼ã·ã§ã³ãè¨è¿°ããããã®3ã¤ã®ãã©ã¡ã¼ã¿ãåãä»ãã¾ãã:
duration-
ã¢ãã¡ã¼ã·ã§ã³ã®ãã¼ã¿ã«ã®æéãä¾:
1000ã timing(timeFraction)-
çµéæé(éå§æ:
0, çµäºæ:1)ãåºã«ãã¢ãã¡ã¼ã·ã§ã³ã®å®äº(ãã¸ã§æ²ç·ã®yã®ãããª) ãè¿ããCSS ããããã£transition-timing-functionã®ãããªã¿ã¤ãã³ã°é¢æ°ã§ããä¾ãã°ãç·å½¢é¢æ°ã¯ã¢ãã¡ã¼ã·ã§ã³ãåãã¹ãã¼ãã§åä¸ã«é²ããã¨ãæå³ãã¾ãã:
function linear(timeFraction) { return timeFraction; }ã°ã©ãã¯ãã®ããã«ãªãã¾ã:
ããã¯
transition-timing-function: linearã®ãããªãã®ã§ããä¸ã«ãããããªããè峿·±ãã±ã¼ã¹ãããã¾ãã draw(progress)-
ã¢ãã¡ã¼ã·ã§ã³ã®å®äºç¶æ ãåããæç»ãè¡ã颿°ã§ããå¤
progress=0ã¯ã¢ãã¡ã¼ã·ã§ã³ã®éå§ç¶æ ã示ããprogress=1ã¯çµäºç¶æ ã示ãã¾ããããã¯å®éã«ã¢ãã¡ã¼ã·ã§ã³ãæç»ãã颿°ã§ãã
è¦ç´ ãç§»åãã¾ã:
function draw(progress) { train.style.left = progress + 'px'; }â¦ã¾ãã¯ãä»ã®ãã¨ãè¡ããã¨ã§ãã©ããªæ¹æ³ã§ãä½ã§ãã¢ãã¡ã¼ã·ã§ã³ããããã¨ãã§ãã¾ãã
ãã®é¢æ°ã使ã£ã¦ãè¦ç´ ã® width ã 0 ãã 100% ã¾ã§ã¢ãã¡ã¼ã·ã§ã³ããã¦ã¿ã¾ãããã
ãã¢å ã®è¦ç´ ãã¯ãªãã¯ãã¦ãã ãã:
function animate({duration, draw, timing}) {
let start = performance.now();
requestAnimationFrame(function animate(time) {
let timeFraction = (time - start) / duration;
if (timeFraction > 1) timeFraction = 1;
let progress = timing(timeFraction)
draw(progress);
if (timeFraction < 1) {
requestAnimationFrame(animate);
}
});
}<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
progress {
width: 5%;
}
</style>
<script src="animate.js"></script>
</head>
<body>
<progress id="elem"></progress>
<script>
elem.onclick = function() {
animate({
duration: 1000,
timing: function(timeFraction) {
return timeFraction;
},
draw: function(progress) {
elem.style.width = progress * 100 + '%';
}
});
};
</script>
</body>
</html>ã³ã¼ãã¯æ¬¡ã®éãã§ã:
animate({
duration: 1000,
timing(timeFraction) {
return timeFraction;
},
draw(progress) {
elem.style.width = progress * 100 + '%';
}
});
CSS ã¢ãã¡ã¼ã·ã§ã³ã¨ã¯ç°ãªããä»»æã®ã¿ã¤ãã³ã°é¢æ°ãæç»é¢æ°ãä½ããã¨ãã§ãã¾ããã¿ã¤ãã³ã°é¢æ°ã¯ãã¸ã§æ²ç·ã«ã¯å¶éããã¾ããããã㦠draw ã¯ããããã£ãè¶
ãã¦ãè±ç«ã®ã¢ãã¡ã¼ã·ã§ã³ã¨ãã£ãæ°ããè¦ç´ ã使ãããã¨ãã§ãã¾ãã
ã¿ã¤ãã³ã°é¢æ°
ä¸è¨ã§æãã·ã³ãã«ãªç·å½¢ã®ã¿ã¤ãã³ã°é¢æ°ãè¦ã¾ããã
ä»ã®ãã®ãè¦ã¦ã¿ã¾ããããæ§ã ãªã¿ã¤ãã³ã°é¢æ°ã§ã®ã¢ãã¡ã¼ã·ã§ã³ã試ãã¦ãã©ã®ããã«åãã®ãã確èªãã¦ã¿ã¾ãã
Power of n(n ã®ã¹ãä¹)
ã¢ãã¡ã¼ã·ã§ã³ãã¹ãã¼ãã¢ããããããå ´åã«ã¯ãn ã®ã¹ãä¹ã§ progress ã使ãã¾ãã
ä¾ãã°ãæ¾ç©æ²ç·:
function quad(timeFraction) {
return Math.pow(timeFraction, 2)
}
ã°ã©ã:
åä½ãè¦ãï¼ã¯ãªãã¯ãã¦æå¹åï¼:
â¦ã¾ãã¯ã3次æ²ç·ã®ãã㪠n ããã大ããå ´åãn ãå¢ãããã¨ã§ããé度ãä¸ããã¾ãã
ããã¯ãã¹ãä¹ 5 ã§ã® progress ã®ã°ã©ãã§ãã:
åä½ãè¦ã:
åå¼§
颿°:
function circ(timeFraction) {
return 1 - Math.sin(Math.acos(timeFraction));
}
ã°ã©ã:
æ»ã: å¼
ãã®é¢æ°ã¯ âå¼ã®å°æâ ãè¡ãã¾ããæåã« â弦ãå¼ãâãæ¬¡ã« âæã¡ã¾ãâã
åã®é¢æ°ã¨ã¯ç°ãªãã追å ã®ãã©ã¡ã¼ã¿ x, âå¼¾æ§ä¿æ°â ã«ä¾åãã¾ããâ弦ãå¼ãâ è·é¢ã¯ããã«ããå®ç¾©ããã¾ãã
ã³ã¼ã:
function back(x, timeFraction) {
return Math.pow(timeFraction, 2) * ((x + 1) * timeFraction - x)
}
x = 1.5 ã®å ´åã®ã°ã©ã:
ã¢ãã¡ã¼ã·ã§ã³ã®å ´åãç¹å®ã® x ã®å¤ã§ä½¿ç¨ãã¾ãããã㯠x = 1.5 ã®ä¾ã§ã:
ãã¦ã³ã
ãã¼ã«ãè½ã¨ããã¨æ³åãã¦ãã ãããããã¯è½ã¡ã¦å¾ä½åº¦ãè·³ãè¿ã£ã¦ãã忢ãã¾ãã
bounce 颿°ã¯ããã¨åããã¨ããã¾ãããå§ã¾ãé åºã¯éã§ãããªãããã®ããã«å¿
è¦ãªç¹å¥ãªä¿æ°ã¯ã»ã¨ãã©ããã¾ããã:
function bounce(timeFraction) {
for (let a = 0, b = 1, result; 1; a += b, b /= 2) {
if (timeFraction >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2)
}
}
}
åä½ãè¦ã:
å¼¾æ§ã®ããã¢ãã¡ã¼ã·ã§ã³
âåæç¯å²â ç¨ã®è¿½å ãã©ã¡ã¼ã¿ x ãåãåãããä¸ã¤ã® âå¼¾ãâ 颿°ã§ãã
function elastic(x, timeFraction) {
return Math.pow(2, 10 * (timeFraction - 1)) * Math.cos(20 * Math.PI * x / 3 * timeFraction)
}
x=1.5 ã®ã°ã©ãã§ã:
x=1.5 ã®å ´åã®åä½:
Reversal: ease*
ããã¾ã§ã§æ§ã ãªã¿ã¤ãã³ã°é¢æ°ãããã¾ããããã㯠âeaseInâ ã¨å¼ã°ãã¾ãã
ã¢ãã¡ã¼ã·ã§ã³ãéã®é åºã§è¡¨ç¤ºããå¿ è¦ããããã¨ãããã¾ããããã¯ãâeaseOutâ 夿ã§è¡ãã¾ãã
easeOut
âeaseOutâ ã¢ã¼ãã§ã¯ãtiming 颿°ã¯ã©ããã¼ timingEaseOut ã®ä¸ã«é
ç½®ããã¾ãã
timingEaseOut(timeFraction) = 1 - timing(1 - timeFraction)
ã¤ã¾ããâé常ã®â ã¿ã¤ãã³ã°é¢æ°ãåããâãã®ã©ããã¼ãè¿ãâ â夿â 颿° makeEaseOut ã使ç¨ãã¾ãã:
// ã¿ã¤ãã³ã°é¢æ°ã弿°ã¨ãã夿ãããã®ãè¿ã
function makeEaseOut(timing) {
return function(timeFraction) {
return 1 - timing(1 - timeFraction);
}
}
ä¾ãã°ãä¸è¿°ã® bounce 颿°ã«å¯¾ãã¦é©ç¨ãã¦ã¿ã¾ã:
let bounceEaseOut = makeEaseOut(bounce);
ããã¨ãæåã§ã¯ãªãã¢ãã¡ã¼ã·ã§ã³ã®æå¾ã«ãã¦ã³ãããããã«ãªãã¾ããããèªç¶ã«ã¿ãã¾ãã:
#brick {
width: 40px;
height: 20px;
background: #EE6B47;
position: relative;
cursor: pointer;
}
#path {
outline: 1px solid #E8C48E;
width: 540px;
height: 20px;
}<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
<script src="https://js.cx/libs/animate.js"></script>
</head>
<body>
<div id="path">
<div id="brick"></div>
</div>
<script>
function makeEaseOut(timing) {
return function(timeFraction) {
return 1 - timing(1 - timeFraction);
}
}
function bounce(timeFraction) {
for (let a = 0, b = 1, result; 1; a += b, b /= 2) {
if (timeFraction >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2)
}
}
}
let bounceEaseOut = makeEaseOut(bounce);
brick.onclick = function() {
animate({
duration: 3000,
timing: bounceEaseOut,
draw: function(progress) {
brick.style.left = progress * 500 + 'px';
}
});
};
</script>
</body>
</html>ããã§ã¯ã夿颿°ãã©ã®ããã«å ã®é¢æ°ã®æåãå¤åãããã®ãã確èªã§ãã¾ã:
è·³ãè¿ããããªãã¢ãã¡ã¼ã·ã§ã³ãæåã«ããå ´åã«ã¯ãããã¯æå¾ä¼¼è¡¨ç¤ºããã¾ãã
ä¸ã®ã°ã©ãã§ã¯ é常ã®ãã¦ã³ã ã¯èµ¤è²ãeaseOut ã®ãã¦ã³ã ã¯éè²ã§ãã
- é常ã®ãã¦ã³ã: ç©ä½ã¯ä¸ã®æ¹ã§è·³ããæå¾ã«æ¥æ¿ã«è·³ãä¸ããã¾ãã
easeOut: æåã«ä¸ã«å¤§ããè·³ãã¦ãããã¦ã³ããã¾ã
easeInOut
ã¢ãã¡ã¼ã·ã§ã³ã®æåã¨æå¾ä¸¡æ¹ã§ãã®å¹æãè¦ãããã¨ãã§ãã¾ãããã®ãã©ã³ã¸ã·ã§ã³ã¯ âeaseInOutâ ã¨å¼ã°ãã¾ãã
ã¿ã¤ãã³ã°é¢æ°ãä¸ããããã¨ã次ã®ããã«ã¢ãã¡ã¼ã·ã§ã³ã®ç¶æ ãç®åºãã¾ã:
if (timeFraction <= 0.5) { // ã¢ãã¡ã¼ã·ã§ã³ã®åå
return timing(2 * timeFraction) / 2;
} else { // ã¢ãã¡ã¼ã·ã§ã³ã®å¾å
return (2 - timing(2 * (1 - timeFraction))) / 2;
}
ãã®ã©ããã¼ã³ã¼ãã§ã:
function makeEaseInOut(timing) {
return function(timeFraction) {
if (timeFraction < .5)
return timing(2 * timeFraction) / 2;
else
return (2 - timing(2 * (1 - timeFraction))) / 2;
}
}
bounceEaseInOut = makeEaseInOut(bounce);
bounceEaseInOut ã®åä½ãè¦ã:
#brick {
width: 40px;
height: 20px;
background: #EE6B47;
position: relative;
cursor: pointer;
}
#path {
outline: 1px solid #E8C48E;
width: 540px;
height: 20px;
}<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
<script src="https://js.cx/libs/animate.js"></script>
</head>
<body>
<div id="path">
<div id="brick"></div>
</div>
<script>
function makeEaseInOut(timing) {
return function(timeFraction) {
if (timeFraction < .5)
return timing(2 * timeFraction) / 2;
else
return (2 - timing(2 * (1 - timeFraction))) / 2;
}
}
function bounce(timeFraction) {
for (let a = 0, b = 1, result; 1; a += b, b /= 2) {
if (timeFraction >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2)
}
}
}
let bounceEaseInOut = makeEaseInOut(bounce);
brick.onclick = function() {
animate({
duration: 3000,
timing: bounceEaseInOut,
draw: function(progress) {
brick.style.left = progress * 500 + 'px';
}
});
};
</script>
</body>
</html>âeaseInOutâ 夿ã¯2ã¤ã®ã°ã©ãã1ã¤ã«ãã¾ã: ã¢ãã¡ã¼ã·ã§ã³ã®ååç¨ã® easeIn ã¨ãå¾åç¨ã® easeOut (easeIn ã®å転)ã§ãã
åå¼§ circ ã¿ã¤ãã³ã°é¢æ°ãä¾ã«ãã¦ããã® easeIn, easeOut 㨠easeInOut ã®ã°ã©ããæ¯ã¹ãã¨ããã®å¹æããã¯ã£ããã¨åããã¾ãã:
- 赤 é常ã®
circ(easeIn). - ç· â
easeOut. - é â
easeInOut.
ã覧ã®éããã¢ãã¡ã¼ã·ã§ã³ã®ååã®ã°ã©ãã¯ç¸®å°ããã easeIn ã§ãããå¾åã¯ç¸®å°ããã easeOut ã®ã°ã©ãã§ããçµæãã¢ãã¡ã¼ã·ã§ã³ã¯ããããã®å¹æã§ã¯ãã¾ããããã¦çµããã¾ãã
ããè峿·±ã âdrawâ
è¦ç´ ãç§»åããã代ããã«ãä»ã®ãã¨ããããã¨ãã§ãã¾ããå¿
è¦ãªãã¨ã¯é©å㪠draw ãè¨è¿°ãããã¨ã§ãã
ãã㯠âãã¦ã³ãâ ããããã¹ãå ¥åã®ã¢ãã¡ã¼ã·ã§ã³ä¾ã§ã:
textarea {
display: block;
border: 1px solid #BBB;
color: #444;
font-size: 110%;
}
button {
margin-top: 10px;
}<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="style.css">
<script src="https://js.cx/libs/animate.js"></script>
</head>
<body>
<textarea id="textExample" rows="5" cols="60">He took his vorpal sword in hand:
Long time the manxome foe he soughtâ
So rested he by the Tumtum tree,
And stood awhile in thought.
</textarea>
<button onclick="animateText(textExample)">Run the animated typing!</button>
<script>
function animateText(textArea) {
let text = textArea.value;
let to = text.length,
from = 0;
animate({
duration: 5000,
timing: bounce,
draw: function(progress) {
let result = (to - from) * progress + from;
textArea.value = text.substr(0, Math.ceil(result))
}
});
}
function bounce(timeFraction) {
for (let a = 0, b = 1, result; 1; a += b, b /= 2) {
if (timeFraction >= (7 - 4 * a) / 11) {
return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2)
}
}
}
</script>
</body>
</html>ãµããª
CSS ã§ã¯ä¸æãæ±ããªãã£ãããå³å¯ãªå¶å¾¡ãå¿
è¦ãªã¢ãã¡ã¼ã·ã§ã³ã®å ´åãJavaScript ãå½¹ç«ã¡ã¾ããJavaScript ã¢ãã¡ã¼ã·ã§ã³ã¯ requestAnimationFrame çµç±ã§å®è£
ãã¾ãããã®çµã¿è¾¼ã¿ã®ã¡ã½ããã«ããããã©ã¦ã¶ãåæç»ãæºåããã¨ãã«å®è¡ãããã³ã¼ã«ããã¯é¢æ°ãã»ããã¢ãããããã¨ãã§ãã¾ããé常ãããã¯ããã§ãããæ£ç¢ºãªæéã¯ãã©ã¦ã¶ã«ä¾åãã¾ãã
ã¾ããããã¯ãã¼ã¸ãããã¯ã°ã©ã¦ã³ãã®ã¨ãã¯åæç»ã¯ã¾ã£ããè¡ãã¾ãããã³ã¼ã«ããã¯ãå®è¡ãããªãããã§ããã¢ãã¡ã¼ã·ã§ã³ã¯ä¸æåæ¢ãããªã½ã¼ã¹ãæ¶è²»ããã¾ãããããã¯ç´ æ´ããããã¨ã§ãã
ããã¯ãã»ã¨ãã©ã®ã¢ãã¡ã¼ã·ã§ã³ã®ã»ããã¢ããã«ä½¿ãããã«ãã¼é¢æ° animate ã§ã:
function animate({timing, draw, duration}) {
let start = performance.now();
requestAnimationFrame(function animate(time) {
// timeFraction 㯠0 tãã 1
let timeFraction = (time - start) / duration;
if (timeFraction > 1) timeFraction = 1;
// ç¾å¨ã®ã¢ãã¡ã¼ã·ã§ã³ã®ç¶æ
ãè¨ç®
let progress = timing(timeFraction);
draw(progress); // æç»
if (timeFraction < 1) {
requestAnimationFrame(animate);
}
});
}
ãªãã·ã§ã³:
durationâ ã¢ãã¡ã¼ã·ã§ã³ã®åè¨æé(ms)ãtimingâ ã¢ãã¡ã¼ã·ã§ã³ã®é²è¡ç¶æ³ãè¨ç®ãã颿°ã0 ã 1 ã¾ã§å¤ã弿°ã«åããé常㯠0 ã 1 ã§ã¢ãã¡ã¼ã·ã§ã³ã®é²è¡ç¶æ³ãè¿ãã¾ããdrawâ ã¢ãã¡ã¼ã·ã§ã³ãæç»ãã颿°ã§ãã
ãã¡ããããããæ¹åãã¦æ§ã ãªãªãã·ã§ã³ã追å ãããã¨ãã§ãã¾ãããJavaScript ã¢ãã¡ã¼ã·ã§ã³ã¯æ¥å¸¸çã«ä½¿ç¨ããããã®ã§ã¯ããã¾ããããããã¯ãªã«ãè峿·±ããã¨ãããå ´åã鿍æºçãªãã¨ãããéã«å©ç¨ããã¾ãããã®ãããå¿ è¦ãªã¨ãã«å¿ è¦ãªæ©è½ã追å ããã®ãããã§ãããã
JavaScript ã¢ãã¡ã¼ã·ã§ã³ã¯ãä»»æã®ã¿ã¤ãã³ã°é¢æ°ãæ±ããã¨ãã§ãã¾ããããã§ã¯å¤ãã®ä¾ãåãä¸ãã¾ãããCSS ã¨ã¯ç°ãªããJavaScript ã¢ãã¡ã¼ã·ã§ã³ã¯ãã¸ã§æ²ç·ã«å¶éããã¾ããã
draw ã«ã¤ãã¦ãåæ§ã§ããCSS ããããã£ã ãã§ãªããä½ã§ãã¢ãã¡ã¼ã·ã§ã³ã«ãããã¨ãã§ãã¾ãã
ã³ã¡ã³ã
<code>ã¿ã°ã使ã£ã¦ãã ãããè¤æ°è¡ã®å ´åã¯<pre>ãã10è¡ãè¶ ããå ´åã«ã¯ãµã³ãããã¯ã¹ã使ã£ã¦ãã ãã(plnkr, JSBin, codepenâ¦)ã