<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- TODO(kevers): Insert link once resolutions present in spec -->
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/web-animations/testcommon.js"></script>
<script src="/web-animations/resources/keyframe-utils.js"></script>
<script src="support/testcommon.js"></script>
<title>Reported keyframes containing timeline offset</title>
</head>
<style type="text/css">
#scroller {
border: 10px solid lightgray;
overflow-y: scroll;
overflow-x: hidden;
width: 300px;
height: 200px;
}
#target {
margin: 800px 10px;
width: 100px;
height: 100px;
z-index: -1;
background-color: green;
}
</style>
<body>
<div id=scroller>
<div id=target></div>
</div>
</body>
<script type="text/javascript">
async function runTest() {
function createAnimation(t, keyframes, use_view_timeline = true) {
const options = {
rangeStart: { rangeName: 'contain', offset: CSS.percent(0) },
rangeEnd: { rangeName: 'contain', offset: CSS.percent(100) },
duration: 'auto',
fill: 'both'
};
if (use_view_timeline) {
options.timeline = new ViewTimeline( { subject: target });
}
const anim = target.animate(keyframes, options);
t.add_cleanup(() => {
anim.cancel();
});
return anim;
}
promise_test(async t => {
let anim = createAnimation(t, [
{ offset: "contain 25%", marginLeft: "0px", opacity: "0" },
{ offset: "contain 75%", marginRight: "0px", opacity: "1" }
]);
let frames = anim.effect.getKeyframes();
let expected = [
{ offset: { rangeName: 'contain', offset: CSS.percent(25) },
computedOffset: 0.25, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'contain', offset: CSS.percent(75) },
computedOffset: 0.75, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
}, 'Report specified timeline offsets');
promise_test(async t => {
let anim = createAnimation(t, [
{ offset: "cover 0%", marginLeft: "0px", opacity: "0" },
{ offset: "cover 100%", marginRight: "0px", opacity: "1" }
]);
let frames = anim.effect.getKeyframes();
let expected = [
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: -1, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: 2, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
}, 'Computed offsets can be outside [0,1] for keyframes with timeline ' +
'offsets');
promise_test(async t => {
let anim = createAnimation(t, [
{ offset: "contain 75%", marginLeft: "0px", opacity: "0" },
{ offset: "contain 25%", marginRight: "0px", opacity: "1" }
]);
let frames = anim.effect.getKeyframes();
let expected = [
{ offset: { rangeName: 'contain', offset: CSS.percent(75) },
computedOffset: 0.75, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'contain', offset: CSS.percent(25) },
computedOffset: 0.25, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
}, 'Retain specified ordering of keyframes with timeline offsets');
promise_test(async t => {
let anim = createAnimation(t, [
{ offset: "cover 0%", marginLeft: "0px", opacity: "0" },
{ offset: "cover 100%", marginRight: "0px", opacity: "1" }
], /* use_view_timeline */ false);
let frames = anim.effect.getKeyframes();
let expected = [
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: null, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: null, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
}, 'Include unreachable keyframes');
promise_test(async t => {
let anim = createAnimation(t, [
{ offset: "cover 0%", marginLeft: "0px", opacity: 0 },
{ offset: "cover 100%", marginRight: "0px", opacity: 1 },
{ opacity: 0 },
{ opacity: 0.5 },
{ opacity: 1.0 }
]);
let frames = anim.effect.getKeyframes();
let expected = [
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: -1, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: 2, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" },
{ offset: null, computedOffset: 0, easing: "linear", composite: "auto",
opacity: "0" },
{ offset: null, computedOffset: 0.5, easing: "linear",
composite: "auto", opacity: "0.5" },
{ offset: null, computedOffset: 1.0, easing: "linear",
composite: "auto", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
anim = createAnimation(t, [
{ opacity: 0 },
{ offset: "cover 0%", marginLeft: "0px", opacity: 0 },
{ opacity: 0.5 },
{ offset: "cover 100%", marginRight: "0px", opacity: 1 },
{ opacity: 1.0 }
]);
frames = anim.effect.getKeyframes();
expected = [
{ offset: null, computedOffset: 0, easing: "linear", composite: "auto",
opacity: "0" },
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: -1, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: null, computedOffset: 0.5, easing: "linear",
composite: "auto", opacity: "0.5" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: 2, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" },
{ offset: null, computedOffset: 1.0, easing: "linear",
composite: "auto", opacity: "1" }
];
assert_frame_lists_equal(frames, expected);
anim = createAnimation(t, [
{ opacity: 0.2, offset: 0.2 },
{ offset: "cover 0%", marginLeft: "0px", opacity: 0 },
{ opacity: 0.4 },
{ opacity: 0.6 },
{ offset: "cover 100%", marginRight: "0px", opacity: 1 },
{ opacity: 0.8, offset: 0.8 }
]);
frames = anim.effect.getKeyframes();
expected = [
{ offset: 0.2, computedOffset: 0.2, easing: "linear", composite: "auto",
opacity: "0.2" },
{ offset: { rangeName: 'cover', offset: CSS.percent(0) },
computedOffset: -1, easing: "linear", composite: "auto",
marginLeft: "0px", opacity: "0" },
{ offset: null, computedOffset: 0.4, easing: "linear",
composite: "auto", opacity: "0.4" },
{ offset: null, computedOffset: 0.6, easing: "linear",
composite: "auto", opacity: "0.6" },
{ offset: { rangeName: 'cover', offset: CSS.percent(100) },
computedOffset: 2, easing: "linear", composite: "auto",
marginRight: "0px", opacity: "1" },
{ offset: 0.8, computedOffset: 0.8, easing: "linear", composite: "auto",
opacity: "0.8" }
];
assert_frame_lists_equal(frames, expected);
}, 'Mix of computed and timeline offsets.');
}
window.onload = runTest;
</script>
</html>