-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanimateOnLoad.js
122 lines (103 loc) · 3.54 KB
/
animateOnLoad.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
'use strict';
/*
The Motion Path Polyfill implements Web Animations for:
- Motion Path properties
https://drafts.fxtf.org/motion-1/
- Individual Transform Properties
https://drafts.csswg.org/css-transforms-2/#individual-transforms
The polyfill doesn't consider stylesheets or inline styles,
hence this file.
If we have stylesheets or inline styles that use the polyfilled properties,
we can identify the relevant elements and create fill: forwards animations.
FIXME: We currently don't detect any DOM or stylesheet changes that occur
after load, and we don't honour the selector specificity rules.
*/
window.onload = function() {
function camelCase(property) {
var hyphen = property.indexOf('-');
if (hyphen === -1) {
return property;
}
return (
property.substring(0, hyphen) +
property.substring(hyphen + 1, hyphen + 2).toUpperCase() +
property.substring(hyphen + 2));
}
var polyfilledProperties = {};
[
'offset-anchor',
'offset-distance',
'offset-path',
'offset-position',
'offset-rotate',
'rotate',
'scale',
'translate'
].forEach(function(property) {
polyfilledProperties[property] = camelCase(property);
});
function motionPathKeyframe(declarations) {
var declarations = declarations.split(';');
var keyframe = {};
declarations.forEach(function(declaration) {
declaration = declaration.split(':');
var property = declaration[0].trim();
if (property in polyfilledProperties)
keyframe[polyfilledProperties[property]] = declaration[1].trim();
});
return keyframe;
}
var timing = {duration: 0, fill: 'forwards'};
function processRuleset(ruleset) {
ruleset = ruleset.split('{');
if (ruleset.length !== 2)
return;
var selectors = ruleset[0];
var elementList = document.querySelectorAll(selectors);
if (elementList.length === 0)
return;
var keyframe = motionPathKeyframe(ruleset[1]);
if (Object.keys(keyframe).length === 0)
return;
var keyframes = [keyframe, keyframe];
elementList.forEach(function(element) {
element.animate(keyframes, timing);
});
}
function applyStyleSheets() {
var styleElements = document.getElementsByTagName('style');
for (var i = 0; i < styleElements.length; ++i) {
var styleElement = styleElements[i];
// Replace comments with whitepace.
var textContent = styleElement.textContent.replace(/\/\*.*?\*\//g, ' ');
// For now, we assume the stylesheet contains rulesets only.
var rulesets = textContent.split('}');
rulesets.pop(); // Ignore everything after the final }
rulesets.forEach(processRuleset);
}
}
var pending = [];
function readInlineStyles() {
var inlineStyledElements = document.querySelectorAll('[style]');
for (var i = 0; i < inlineStyledElements.length; ++i) {
var inlineStyledElement = inlineStyledElements[i];
// Replace comments with whitepace.
var declarations = inlineStyledElement.getAttribute('style').replace(/\/\*.*?\*\//g, ' ');
var keyframe = motionPathKeyframe(declarations);
if (Object.keys(keyframe).length === 0)
continue;
pending.push([inlineStyledElement, keyframe]);
}
}
function applyInlineStyles() {
for (var i = 0; i < pending.length; ++i) {
var inlineStyledElement = pending[i][0];
var keyframe = pending[i][1];
var keyframes = [keyframe, keyframe];
inlineStyledElement.animate(keyframes, timing);
}
}
readInlineStyles();
applyStyleSheets();
applyInlineStyles();
};