| <!DOCTYPE html> |
| <meta charset="UTF-8"> |
| <body> |
| <script src="../interpolation/resources/interpolation-test.js"></script> |
| <script> |
| // Basic additive composition; the lists should be concatenated. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| addFrom: 'blur(40px)', |
| addTo: 'blur(90px)', |
| }, [ |
| {at: -0.5, is: 'blur(10px) blur(15px)'}, |
| {at: 0, is: 'blur(10px) blur(40px)'}, |
| {at: 0.25, is: 'blur(10px) blur(52.5px)'}, |
| {at: 0.5, is: 'blur(10px) blur(65px)'}, |
| {at: 0.75, is: 'blur(10px) blur(77.5px)'}, |
| {at: 1, is: 'blur(10px) blur(90px)'}, |
| {at: 1.5, is: 'blur(10px) blur(115px)'}, |
| ]); |
| |
| // Here we have add-from and replace-to, so the list will be have mismatched |
| // lengths and the replace-to list will have to be extended to interpolate as |
| // per https://drafts.fxtf.org/filter-effects-1/#interpolation-of-filters |
| // |
| // That is, this becomes an interpolation of the form: |
| // sepia(0.5) sepia(0.5) --> sepia(1) sepia(0) |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'sepia(0.5)', |
| addFrom: 'sepia(0.5)', |
| replaceTo: 'sepia(1)', |
| }, [ |
| {at: -0.5, is: 'sepia(0.25) sepia(0.75)'}, |
| {at: 0, is: 'sepia(0.5) sepia(0.5)'}, |
| {at: 0.25, is: 'sepia(0.625) sepia(0.375)'}, |
| {at: 0.5, is: 'sepia(0.75) sepia(0.25)'}, |
| {at: 0.75, is: 'sepia(0.875) sepia(0.125)'}, |
| {at: 1, is: 'sepia(1) sepia(0)'}, |
| {at: 1.5, is: 'sepia(1) sepia(0)'}, |
| ]); |
| |
| // In this case we have replace-from and add-to, so similar extending behavior |
| // takes place. Note that brightness has an initial value of 1. |
| // |
| // That is, this becomes an interpolation of the form: |
| // brightness(0.5) brightness(1) --> brightness(0) brightness(1.5) |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'brightness(0)', |
| replaceFrom: 'brightness(0.5)', |
| addTo: 'brightness(1.5)', |
| }, [ |
| {at: -0.5, is: 'brightness(0.75) brightness(0.75)'}, |
| {at: 0, is: 'brightness(0.5) brightness(1)'}, |
| {at: 0.25, is: 'brightness(0.375) brightness(1.125)'}, |
| {at: 0.5, is: 'brightness(0.25) brightness(1.25)'}, |
| {at: 0.75, is: 'brightness(0.125) brightness(1.375)'}, |
| {at: 1, is: 'brightness(0) brightness(1.5)'}, |
| {at: 1.5, is: 'brightness(0) brightness(1.75)'}, |
| ]); |
| |
| // Test mixing properties. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'invert(0.5)', |
| addFrom: 'saturate(2)', |
| addTo: 'saturate(3)', |
| }, [ |
| {at: -0.5, is: 'invert(0.5) saturate(1.5)'}, |
| {at: 0, is: 'invert(0.5) saturate(2)'}, |
| {at: 0.25, is: 'invert(0.5) saturate(2.25)'}, |
| {at: 0.5, is: 'invert(0.5) saturate(2.5)'}, |
| {at: 0.75, is: 'invert(0.5) saturate(2.75)'}, |
| {at: 1, is: 'invert(0.5) saturate(3)'}, |
| {at: 1.5, is: 'invert(0.5) saturate(3.5)'}, |
| ]); |
| |
| // Test the 'none' behavior; composition happens before interpolation, so this |
| // is actually an interpolation of: |
| // invert(0.5) saturate(1) --> invert(1) saturate(3) |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'invert(0.5)', |
| addFrom: 'none', |
| replaceTo: 'invert(1) saturate(3)', |
| }, [ |
| {at: -0.5, is: 'invert(0.25) saturate(0)'}, |
| {at: 0, is: 'invert(0.5) saturate(1)'}, |
| {at: 0.25, is: 'invert(0.625) saturate(1.5)'}, |
| {at: 0.5, is: 'invert(0.75) saturate(2)'}, |
| {at: 0.75, is: 'invert(0.875) saturate(2.5)'}, |
| {at: 1, is: 'invert(1) saturate(3)'}, |
| {at: 1.5, is: 'invert(1.25) saturate(4)'}, |
| ]); |
| |
| // Test having multiple underlying values |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'grayscale(25%) blur(10px)', |
| addFrom: 'brightness(0)', |
| addTo: 'brightness(1)', |
| }, [ |
| {at: -0.5, is: 'grayscale(25%) blur(10px) brightness(0)'}, |
| {at: 0, is: 'grayscale(25%) blur(10px) brightness(0)'}, |
| {at: 0.25, is: 'grayscale(25%) blur(10px) brightness(0.25)'}, |
| {at: 0.5, is: 'grayscale(25%) blur(10px) brightness(0.5)'}, |
| {at: 0.75, is: 'grayscale(25%) blur(10px) brightness(0.75)'}, |
| {at: 1, is: 'grayscale(25%) blur(10px) brightness(1)'}, |
| {at: 1.5, is: 'grayscale(25%) blur(10px) brightness(1.5)'}, |
| ]); |
| |
| // Make sure that a matching underlying value is still prefixed. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| addFrom: 'grayscale(50%) blur(10px)', |
| addTo: 'grayscale(25%) blur(10px)', |
| }, [ |
| {at: -0.5, is: 'blur(10px) grayscale(0.625) blur(10px)'}, |
| {at: 0, is: 'blur(10px) grayscale(0.5) blur(10px)'}, |
| {at: 0.25, is: 'blur(10px) grayscale(0.4375) blur(10px)'}, |
| {at: 0.5, is: 'blur(10px) grayscale(0.375) blur(10px)'}, |
| {at: 0.75, is: 'blur(10px) grayscale(0.3125) blur(10px)'}, |
| {at: 1, is: 'blur(10px) grayscale(0.25) blur(10px)'}, |
| {at: 1.5, is: 'blur(10px) grayscale(0.125) blur(10px)'}, |
| ]); |
| |
| // Check the case where composition causes a url() to be included; the animation |
| // should change to discrete. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'url(#a)', |
| addFrom: 'grayscale(50%) blur(30px)', |
| addTo: 'grayscale(25%) blur(40px)', |
| }, [ |
| {at: -0.5, is: 'url("#a") grayscale(0.5) blur(30px)'}, |
| {at: 0, is: 'url("#a") grayscale(0.5) blur(30px)'}, |
| {at: 0.25, is: 'url("#a") grayscale(0.5) blur(30px)'}, |
| {at: 0.5, is: 'url("#a") grayscale(0.25) blur(40px)'}, |
| {at: 0.75, is: 'url("#a") grayscale(0.25) blur(40px)'}, |
| {at: 1, is: 'url("#a") grayscale(0.25) blur(40px)'}, |
| {at: 1.5, is: 'url("#a") grayscale(0.25) blur(40px)'}, |
| ]); |
| |
| // And check the inverse; nothing fancy here but it should be a discrete |
| // animation with blur prepended. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| addFrom: 'url(#a) brightness(1)', |
| addTo: 'url(#b) brightness(0)', |
| }, [ |
| {at: -0.5, is: 'blur(10px) url(#a) brightness(1)'}, |
| {at: 0, is: 'blur(10px) url(#a) brightness(1)'}, |
| {at: 0.25, is: 'blur(10px) url(#a) brightness(1)'}, |
| {at: 0.5, is: 'blur(10px) url(#b) brightness(0)'}, |
| {at: 0.75, is: 'blur(10px) url(#b) brightness(0)'}, |
| {at: 1, is: 'blur(10px) url(#b) brightness(0)'}, |
| {at: 1.5, is: 'blur(10px) url(#b) brightness(0)'}, |
| ]); |
| |
| // --------------- Accumulation tests. --------------------- |
| |
| // blur; simple addition. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| accumulateFrom: 'blur(40px)', |
| accumulateTo: 'blur(90px)', |
| }, [ |
| {at: -0.5, is: 'blur(25px)'}, |
| {at: 0, is: 'blur(50px)'}, |
| {at: 0.25, is: 'blur(62.5px)'}, |
| {at: 0.5, is: 'blur(75px)'}, |
| {at: 0.75, is: 'blur(87.5px)'}, |
| {at: 1, is: 'blur(100px)'}, |
| {at: 1.5, is: 'blur(125px)'}, |
| ]); |
| |
| // brightness; 1-based addition. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'brightness(0.25)', |
| accumulateFrom: 'brightness(0.5)', |
| accumulateTo: 'brightness(1.5)', |
| }, [ |
| {at: -0.5, is: 'brightness(0)'}, |
| {at: 0, is: 'brightness(0)'}, |
| {at: 0.25, is: 'brightness(0)'}, |
| {at: 0.5, is: 'brightness(0.25)'}, |
| {at: 0.75, is: 'brightness(0.5)'}, |
| {at: 1, is: 'brightness(0.75)'}, |
| {at: 1.5, is: 'brightness(1.25)'}, |
| ]); |
| |
| // contrast; 1-based addition. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'contrast(0.25)', |
| accumulateFrom: 'contrast(0.5)', |
| accumulateTo: 'contrast(1.5)', |
| }, [ |
| {at: -0.5, is: 'contrast(0)'}, |
| {at: 0, is: 'contrast(0)'}, |
| {at: 0.25, is: 'contrast(0)'}, |
| {at: 0.5, is: 'contrast(0.25)'}, |
| {at: 0.75, is: 'contrast(0.5)'}, |
| {at: 1, is: 'contrast(0.75)'}, |
| {at: 1.5, is: 'contrast(1.25)'}, |
| ]); |
| |
| // drop-shadow; addition of lengths plus color addition |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'drop-shadow(10px 5px 0px rgb(255, 0, 0))', |
| accumulateFrom: 'drop-shadow(0px 10px 10px rgb(0, 255, 0))', |
| accumulateTo: 'drop-shadow(50px 30px 10px rgb(0, 0, 255))', |
| }, [ |
| {at: -0.5, is: 'drop-shadow(-15px 5px 10px rgb(255, 255, 0))'}, |
| {at: 0, is: 'drop-shadow(10px 15px 10px rgb(255, 255, 0))'}, |
| {at: 0.25, is: 'drop-shadow(22.5px 20px 10px rgb(255, 191, 64))'}, |
| {at: 0.5, is: 'drop-shadow(35px 25px 10px rgb(255, 128, 128))'}, |
| {at: 0.75, is: 'drop-shadow(47.5px 30px 10px rgb(255, 64, 191))'}, |
| {at: 1, is: 'drop-shadow(60px 35px 10px rgb(255, 0, 255))'}, |
| {at: 1.5, is: 'drop-shadow(85px 45px 10px rgb(255, 0, 255))'}, |
| ]); |
| |
| // grayscale; 1-based addition. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'grayscale(0.25)', |
| accumulateFrom: 'grayscale(0.5)', |
| accumulateTo: 'grayscale(1.5)', // clamped to 1 |
| }, [ |
| {at: -0.5, is: 'grayscale(0)'}, |
| {at: 0, is: 'grayscale(0)'}, |
| {at: 0.25, is: 'grayscale(0)'}, |
| {at: 0.5, is: 'grayscale(0)'}, |
| {at: 0.75, is: 'grayscale(0.125)'}, |
| {at: 1, is: 'grayscale(0.25)'}, |
| {at: 1.5, is: 'grayscale(0.5)'}, |
| ]); |
| |
| // hue-rotate; simple addition |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'hue-rotate(45deg)', |
| accumulateFrom: 'hue-rotate(140deg)', |
| accumulateTo: 'hue-rotate(400deg)', |
| }, [ |
| {at: -0.5, is: 'hue-rotate(55deg)'}, |
| {at: 0, is: 'hue-rotate(185deg)'}, |
| {at: 0.25, is: 'hue-rotate(250deg)'}, |
| {at: 0.5, is: 'hue-rotate(315deg)'}, |
| {at: 0.75, is: 'hue-rotate(380deg)'}, |
| {at: 1, is: 'hue-rotate(445deg)'}, |
| {at: 1.5, is: 'hue-rotate(575deg)'}, |
| ]); |
| |
| // invert; 1-based addition. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'invert(0.25)', |
| accumulateFrom: 'invert(0.5)', |
| accumulateTo: 'invert(1.5)', // clamped to 1 |
| }, [ |
| {at: -0.5, is: 'invert(0)'}, |
| {at: 0, is: 'invert(0)'}, |
| {at: 0.25, is: 'invert(0)'}, |
| {at: 0.5, is: 'invert(0)'}, |
| {at: 0.75, is: 'invert(0.125)'}, |
| {at: 1, is: 'invert(0.25)'}, |
| {at: 1.5, is: 'invert(0.5)'}, |
| ]); |
| |
| // opacity; 1-based addition |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'opacity(0.25)', |
| accumulateFrom: 'opacity(0.5)', |
| accumulateTo: 'opacity(1.5)', // clamped to 1 |
| }, [ |
| {at: -0.5, is: 'opacity(0)'}, |
| {at: 0, is: 'opacity(0)'}, |
| {at: 0.25, is: 'opacity(0)'}, |
| {at: 0.5, is: 'opacity(0)'}, |
| {at: 0.75, is: 'opacity(0.125)'}, |
| {at: 1, is: 'opacity(0.25)'}, |
| {at: 1.5, is: 'opacity(0.5)'}, |
| ]); |
| |
| // saturate; 1-based addition |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'saturate(0.25)', |
| accumulateFrom: 'saturate(0.5)', |
| accumulateTo: 'saturate(1.5)', |
| }, [ |
| {at: -0.5, is: 'saturate(0)'}, |
| {at: 0, is: 'saturate(0)'}, |
| {at: 0.25, is: 'saturate(0)'}, |
| {at: 0.5, is: 'saturate(0.25)'}, |
| {at: 0.75, is: 'saturate(0.5)'}, |
| {at: 1, is: 'saturate(0.75)'}, |
| {at: 1.5, is: 'saturate(1.25)'}, |
| ]); |
| |
| // sepia; 1-based addition |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'sepia(0.25)', |
| accumulateFrom: 'sepia(0.5)', |
| accumulateTo: 'sepia(1.5)', // clamped to 1 |
| }, [ |
| {at: -0.5, is: 'sepia(0)'}, |
| {at: 0, is: 'sepia(0)'}, |
| {at: 0.25, is: 'sepia(0)'}, |
| {at: 0.5, is: 'sepia(0)'}, |
| {at: 0.75, is: 'sepia(0.125)'}, |
| {at: 1, is: 'sepia(0.25)'}, |
| {at: 1.5, is: 'sepia(0.5)'}, |
| ]); |
| |
| // url; cannot be accumulated |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'url(#a)', |
| accumulateFrom: 'url(#b)', |
| accumulateTo: 'url(#c)', |
| }, [ |
| {at: -0.5, is: 'url(#b)'}, |
| {at: 0, is: 'url(#b)'}, |
| {at: 0.25, is: 'url(#b)'}, |
| {at: 0.5, is: 'url(#c)'}, |
| {at: 0.75, is: 'url(#c)'}, |
| {at: 1, is: 'url(#c)'}, |
| {at: 1.5, is: 'url(#c)'}, |
| ]); |
| |
| // Test auto-extension of the underlying list. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| accumulateFrom: 'blur(40px) saturate(1)', |
| accumulateTo: 'blur(90px) saturate(0)', |
| }, [ |
| {at: -0.5, is: 'blur(25px) saturate(1.5)'}, |
| {at: 0, is: 'blur(50px) saturate(1)'}, |
| {at: 0.25, is: 'blur(62.5px) saturate(0.75)'}, |
| {at: 0.5, is: 'blur(75px) saturate(0.5)'}, |
| {at: 0.75, is: 'blur(87.5px) saturate(0.25)'}, |
| {at: 1, is: 'blur(100px) saturate(0)'}, |
| {at: 1.5, is: 'blur(125px) saturate(0)'}, |
| ]); |
| |
| // Test auto-extension of the composited-onto list. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px) saturate(0.75)', |
| accumulateFrom: 'blur(40px)', |
| accumulateTo: 'blur(90px)', |
| }, [ |
| {at: -0.5, is: 'blur(25px) saturate(0.75)'}, |
| {at: 0, is: 'blur(50px) saturate(0.75)'}, |
| {at: 0.25, is: 'blur(62.5px) saturate(0.75)'}, |
| {at: 0.5, is: 'blur(75px) saturate(0.75)'}, |
| {at: 0.75, is: 'blur(87.5px) saturate(0.75)'}, |
| {at: 1, is: 'blur(100px) saturate(0.75)'}, |
| {at: 1.5, is: 'blur(125px) saturate(0.75)'}, |
| ]); |
| |
| // Mismatching type for underlying; it just gets replaced. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'contrast(0.75)', |
| accumulateFrom: 'blur(40px)', |
| accumulateTo: 'blur(80px)', |
| }, [ |
| {at: -0.5, is: 'blur(20px)'}, |
| {at: 0, is: 'blur(40px)'}, |
| {at: 0.25, is: 'blur(50px)'}, |
| {at: 0.5, is: 'blur(60px)'}, |
| {at: 0.75, is: 'blur(70px)'}, |
| {at: 1, is: 'blur(80px)'}, |
| {at: 1.5, is: 'blur(100px)'}, |
| ]); |
| |
| // Underlying only type-matches one side of the interpolation; it should be |
| // accumulated onto that side, but the entire animation will be discrete due to |
| // the mis-matching types. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| accumulateFrom: 'blur(40px)', |
| accumulateTo: 'saturate(1)', |
| }, [ |
| {at: -0.5, is: 'blur(50px)'}, |
| {at: 0, is: 'blur(50px)'}, |
| {at: 0.25, is: 'blur(50px)'}, |
| {at: 0.5, is: 'saturate(1)'}, |
| {at: 0.75, is: 'saturate(1)'}, |
| {at: 1, is: 'saturate(1)'}, |
| {at: 1.5, is: 'saturate(1)'}, |
| ]); |
| |
| // Test a case where only one side is accumulative and the other is replace. |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| accumulateFrom: 'blur(30px)', |
| replaceTo: 'blur(100px)', |
| }, [ |
| {at: -0.5, is: 'blur(10px)'}, |
| {at: 0, is: 'blur(40px)'}, |
| {at: 0.25, is: 'blur(55px)'}, |
| {at: 0.5, is: 'blur(70px)'}, |
| {at: 0.75, is: 'blur(85px)'}, |
| {at: 1, is: 'blur(100px)'}, |
| {at: 1.5, is: 'blur(130px)'}, |
| ]); |
| |
| // Test a case where only one side is accumulative and the other is add. |
| // This basically looks like: |
| // accumulateSide = blur(Apx) neutral-blur |
| // addSide = blur(10px) blur(Bpx) |
| assertComposition({ |
| property: 'backdrop-filter', |
| underlying: 'blur(10px)', |
| accumulateFrom: 'blur(40px)', |
| addTo: 'blur(100px)', |
| }, [ |
| {at: -0.5, is: 'blur(70px) blur(0px)'}, |
| {at: 0, is: 'blur(50px) blur(0px)'}, |
| {at: 0.25, is: 'blur(40px) blur(25px)'}, |
| {at: 0.5, is: 'blur(30px) blur(50px)'}, |
| {at: 0.75, is: 'blur(20px) blur(75px)'}, |
| {at: 1, is: 'blur(10px) blur(100px)'}, |
| {at: 1.5, is: 'blur(0px) blur(150px)'}, |
| ]); |
| </script> |
| </body> |