5-4 Keyframes/Keyframe Rule

from/to 는 keyframe animation selector 이라는 것이다. 이것을 어떻게 객체화 시킬까?

@keyframes size {
from {width: 0}
to {width: 500px}
}
const sheet = new Sheet(document.styleSheets[1]);
sheet.add('@keyframes size').set(/* ... */);
const Sheet = class {
constructor(sheet) { /* ... */}
add(selector) {
const index = this._sheet.cssRules.length;
this._sheet.insertRule(`${selector}{}`, index);
const cssRule = this._sheet.cssRules[index];
// 여기서부터 문제.. style rule 로 가정한 부분... 의존성 주입! 여기서는 분기문으로 작성
const rule = new Rule(cssRule);
this._rules.set(selector, rule);
return rule;
}
}
const Sheet = class {
constructor(sheet) { /* ... */}
add(selector) {
const index = this._sheet.cssRules.length;
this._sheet.insertRule(`${selector}{}`, index);
const cssRule = this._sheet.cssRules[index];
let rule;
if (selector.startWith('@keyframes')) {
// 키프레임 애니매이션 처리
rule = new KeyFramesRule(cssRule); // delegation
} else {
rule = new Rule(cssRule);
}
this._rules.set(selector, rule);
return rule;
}
}

keyframeRule 객체는 sheet 객체와 거의 똑같다.
size 가 하나의 rule 이긴 하지만 from, to 안쪽이 style_sheet 처럼 생겼다.
insertRule 대신 appendRule 을 쓴다.

const KeyFramesRule = class {
constructor(rule) {
this._keyframe = rule;
this._rules = new Map;
}
add(selector) {
const index = this._keyframe.cssRules.length;
this._keyframe.appendRule(`${selector}{}`, index);
const cssRule = this._keyframe.cssRules[index];
const rule = new Rule(cssRule);
this._rules.set(selector, rule);
return rule;
}
remove(selector) {
if (!this._rules.contains(selector)) return;
const rule = this._rules.get(selector)._rule;
Array.from(this._keyframe.cssRules).some((cssRule, index) => {
if (cssRule === rule._rule) {
this._keyframe.deleteRule(index);
return true;
}
})
}
get(selector) {
return this._rules.get(selector);
}
}
const KeyFramesRule = class {
constructor(rule) { /* ... */}
add(selector) { /* ... */}
remove(selector) { /* ... */}
}
const sheet = new Sheet(document.styleSheets[0]);
const size = sheet.add('@keyframes size');
size.add("from").set("width", "0");
size.add("to").set("width", "500px");
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.test {
background: #f00;
animation: size 1s infinite alternate;
}
</style>
</head>
<body>
<div class="test">test</div>
</body>
</html>
tip

특수한 애니메이션을 동적으로 정의해서 사용할 수 있게 되었다.
키프레임 실렉터를 정의해서 동적정의 / 재활용 가능하다.

Last updated on