• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5//     You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//     See the License for the specific language governing permissions and
13// limitations under the License.
14
15(function(shared, scope, testing) {
16
17  scope.convertEffectInput = function(effectInput) {
18    var keyframes = shared.normalizeKeyframes(effectInput);
19    var propertySpecificKeyframeGroups = makePropertySpecificKeyframeGroups(keyframes);
20    var interpolations = makeInterpolations(propertySpecificKeyframeGroups);
21    return function(target, fraction) {
22      if (fraction != null) {
23        interpolations.filter(function(interpolation) {
24          return fraction >= interpolation.applyFrom && fraction < interpolation.applyTo;
25        }).forEach(function(interpolation) {
26          var offsetFraction = fraction - interpolation.startOffset;
27          var localDuration = interpolation.endOffset - interpolation.startOffset;
28          var scaledLocalTime = localDuration == 0 ? 0 : interpolation.easingFunction(offsetFraction / localDuration);
29          scope.apply(target, interpolation.property, interpolation.interpolation(scaledLocalTime));
30        });
31      } else {
32        for (var property in propertySpecificKeyframeGroups)
33          if (property != 'offset' && property != 'easing' && property != 'composite')
34            scope.clear(target, property);
35      }
36    };
37  };
38
39
40  function makePropertySpecificKeyframeGroups(keyframes) {
41    var propertySpecificKeyframeGroups = {};
42
43    for (var i = 0; i < keyframes.length; i++) {
44      for (var member in keyframes[i]) {
45        if (member != 'offset' && member != 'easing' && member != 'composite') {
46          var propertySpecificKeyframe = {
47            offset: keyframes[i].offset,
48            easing: keyframes[i].easing,
49            value: keyframes[i][member]
50          };
51          propertySpecificKeyframeGroups[member] = propertySpecificKeyframeGroups[member] || [];
52          propertySpecificKeyframeGroups[member].push(propertySpecificKeyframe);
53        }
54      }
55    }
56
57    for (var groupName in propertySpecificKeyframeGroups) {
58      var group = propertySpecificKeyframeGroups[groupName];
59      if (group[0].offset != 0 || group[group.length - 1].offset != 1) {
60        throw {
61          type: DOMException.NOT_SUPPORTED_ERR,
62          name: 'NotSupportedError',
63          message: 'Partial keyframes are not supported'
64        };
65      }
66    }
67    return propertySpecificKeyframeGroups;
68  }
69
70
71  function makeInterpolations(propertySpecificKeyframeGroups) {
72    var interpolations = [];
73    for (var groupName in propertySpecificKeyframeGroups) {
74      var keyframes = propertySpecificKeyframeGroups[groupName];
75      for (var i = 0; i < keyframes.length - 1; i++) {
76        var startIndex = i;
77        var endIndex = i + 1;
78        var startOffset = keyframes[startIndex].offset;
79        var endOffset = keyframes[endIndex].offset;
80        var applyFrom = startOffset;
81        var applyTo = endOffset;
82
83        if (i == 0) {
84          applyFrom = -Infinity;
85          WEB_ANIMATIONS_TESTING && console.assert(startOffset == 0);
86          if (endOffset == 0) {
87            endIndex = startIndex;
88          }
89        }
90        if (i == keyframes.length - 2) {
91          applyTo = Infinity;
92          WEB_ANIMATIONS_TESTING && console.assert(endOffset == 1);
93          if (startOffset == 1) {
94            startIndex = endIndex;
95          }
96        }
97
98        interpolations.push({
99          applyFrom: applyFrom,
100          applyTo: applyTo,
101          startOffset: keyframes[startIndex].offset,
102          endOffset: keyframes[endIndex].offset,
103          easingFunction: shared.parseEasingFunction(keyframes[startIndex].easing),
104          property: groupName,
105          interpolation: scope.propertyInterpolation(groupName,
106              keyframes[startIndex].value,
107              keyframes[endIndex].value)
108        });
109      }
110    }
111    interpolations.sort(function(leftInterpolation, rightInterpolation) {
112      return leftInterpolation.startOffset - rightInterpolation.startOffset;
113    });
114    return interpolations;
115  }
116
117
118  if (WEB_ANIMATIONS_TESTING) {
119    testing.makePropertySpecificKeyframeGroups = makePropertySpecificKeyframeGroups;
120    testing.makeInterpolations = makeInterpolations;
121  }
122
123})(webAnimationsShared, webAnimations1, webAnimationsTesting);
124