1 |
|
2 |
|
3 | "use strict"
|
4 |
|
5 |
|
6 |
|
7 | var color = require("./color"),
|
8 | frame = require("./frame")
|
9 |
|
10 | var cancelFrame = frame.cancel,
|
11 | requestFrame = frame.request
|
12 |
|
13 | var prime = require("prime/prime"),
|
14 | array = require("prime/es5/array"),
|
15 | string = require("prime/types/string")
|
16 |
|
17 | var camelize = string.camelize,
|
18 | clean = string.clean,
|
19 | capitalize = string.capitalize
|
20 |
|
21 | var map = array.map,
|
22 | forEach = array.forEach,
|
23 | indexOf = array.indexOf
|
24 |
|
25 | var elements = require("elements/lib/elements")
|
26 |
|
27 | var fx = require("./fx")
|
28 |
|
29 |
|
30 |
|
31 | var hyphenated = {}
|
32 | var hyphenate = function(self){
|
33 | return hyphenated[self] || (hyphenated[self] = string.hyphenate(self))
|
34 | }
|
35 |
|
36 | var round = function(n){
|
37 | return Math.round(n * 1e3) / 1e3
|
38 | }
|
39 |
|
40 |
|
41 |
|
42 | var compute = global.getComputedStyle ? function(node){
|
43 | var cts = getComputedStyle(node)
|
44 | return function(property){
|
45 | return cts ? cts.getPropertyValue(hyphenate(property)) : ""
|
46 | }
|
47 | } : function(node){
|
48 | var cts = node.currentStyle
|
49 | return function(property){
|
50 | return cts ? cts[camelize(property)] : ""
|
51 | }
|
52 | }
|
53 |
|
54 |
|
55 |
|
56 | var test = document.createElement("div")
|
57 |
|
58 | var cssText = "border:none;margin:none;padding:none;visibility:hidden;position:absolute;height:0;";
|
59 |
|
60 |
|
61 |
|
62 | var pixelRatio = function(element, u){
|
63 | var parent = element.parentNode, ratio = 1
|
64 | if (parent){
|
65 | test.style.cssText = cssText + ("width:100" + u + ";")
|
66 | parent.appendChild(test)
|
67 | ratio = test.offsetWidth / 100
|
68 | parent.removeChild(test)
|
69 | }
|
70 | return ratio
|
71 | }
|
72 |
|
73 |
|
74 |
|
75 | var mirror4 = function(values){
|
76 | var length = values.length
|
77 | if (length === 1) values.push(values[0], values[0], values[0])
|
78 | else if (length === 2) values.push(values[0], values[1])
|
79 | else if (length === 3) values.push(values[1])
|
80 | return values
|
81 | }
|
82 |
|
83 |
|
84 |
|
85 | var sLength = "([-.\\d]+)(%|cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vm)",
|
86 | sLengthNum = sLength + "?",
|
87 | sBorderStyle = "none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset|inherit"
|
88 |
|
89 |
|
90 |
|
91 | var rgLength = RegExp(sLength, "g"),
|
92 | rLengthNum = RegExp(sLengthNum),
|
93 | rgLengthNum = RegExp(sLengthNum, "g"),
|
94 | rBorderStyle = RegExp(sBorderStyle)
|
95 |
|
96 |
|
97 |
|
98 | var parseString = function(value){
|
99 | return (value == null) ? "" : value + ""
|
100 | }
|
101 |
|
102 | var parseOpacity = function(value, normalize){
|
103 | if (value == null || value === "") return normalize ? "1" : ""
|
104 | return (isFinite((value = +value))) ? (value < 0 ? "0" : value + "") : "1"
|
105 | }
|
106 |
|
107 | try {test.style.color = "rgba(0,0,0,0.5)"} catch(e){}
|
108 | var rgba = /^rgba/.test(test.style.color)
|
109 |
|
110 | var parseColor = function(value, normalize){
|
111 | var black = "rgba(0,0,0,1)", c
|
112 | if (!value || !(c = color(value, true))) return normalize ? black : ""
|
113 | if (normalize) return "rgba(" + c + ")"
|
114 |
|
115 | var alpha = c[3]
|
116 | if (alpha === 0) return "transparent"
|
117 | return (!rgba || alpha === 1) ? "rgb(" + c.slice(0, 3) + ")" : "rgba(" + c + ")"
|
118 | }
|
119 |
|
120 | var parseLength = function(value, normalize){
|
121 | if (value == null || value === "") return normalize ? "0px" : ""
|
122 | var match = string.match(value, rLengthNum)
|
123 | return match ? match[1] + (match[2] || "px") : value
|
124 | }
|
125 |
|
126 | var parseBorderStyle = function(value, normalize){
|
127 | if (value == null || value === "") return normalize ? "none" : ""
|
128 | var match = value.match(rBorderStyle)
|
129 | return match ? value : normalize ? "none" : ""
|
130 | }
|
131 |
|
132 | var parseBorder = function(value, normalize){
|
133 | var normalized = "0px none rgba(0,0,0,1)"
|
134 | if (value == null || value === "") return normalize ? normalized : ""
|
135 | if (value === 0 || value === "none") return normalize ? normalized : value + ""
|
136 |
|
137 | var c
|
138 | value = value.replace(color.x, function(match){
|
139 | c = match
|
140 | return ""
|
141 | })
|
142 |
|
143 | var s = value.match(rBorderStyle),
|
144 | l = value.match(rgLengthNum)
|
145 |
|
146 | return clean([
|
147 | parseLength(l ? l[0] : "", normalize),
|
148 | parseBorderStyle(s ? s[0] : "", normalize),
|
149 | parseColor(c, normalize)
|
150 | ].join(" "))
|
151 | }
|
152 |
|
153 | var parseShort4 = function(value, normalize){
|
154 | if (value == null || value === "") return normalize ? "0px 0px 0px 0px" : ""
|
155 | return clean(mirror4(map(clean(value).split(" "), function(v){
|
156 | return parseLength(v, normalize)
|
157 | })).join(" "))
|
158 | }
|
159 |
|
160 | var parseShadow = function(value, normalize, len){
|
161 | var transparent = "rgba(0,0,0,0)",
|
162 | normalized = (len === 3) ? transparent + " 0px 0px 0px" : transparent + " 0px 0px 0px 0px"
|
163 |
|
164 | if (value == null || value === "") return normalize ? normalized : ""
|
165 | if (value === "none") return normalize ? normalized : value
|
166 |
|
167 | var colors = [], value = clean(value).replace(color.x, function(match){
|
168 | colors.push(match)
|
169 | return ""
|
170 | })
|
171 |
|
172 | return map(value.split(","), function(shadow, i){
|
173 |
|
174 | var c = parseColor(colors[i], normalize),
|
175 | inset = /inset/.test(shadow),
|
176 | lengths = shadow.match(rgLengthNum) || ["0px"]
|
177 |
|
178 | lengths = map(lengths, function(m){
|
179 | return parseLength(m, normalize)
|
180 | })
|
181 |
|
182 | while (lengths.length < len) lengths.push("0px")
|
183 |
|
184 | var ret = inset ? ["inset", c] : [c]
|
185 |
|
186 | return ret.concat(lengths).join(" ")
|
187 |
|
188 | }).join(", ")
|
189 | }
|
190 |
|
191 | var parse = function(value, normalize){
|
192 | if (value == null || value === "") return ""
|
193 | return value.replace(color.x, function(match){
|
194 | return parseColor(match, normalize)
|
195 | }).replace(rgLength, function(match){
|
196 | return parseLength(match, normalize)
|
197 | })
|
198 | }
|
199 |
|
200 |
|
201 |
|
202 | var getters = {}, setters = {}, parsers = {}, aliases = {}
|
203 |
|
204 | var getter = function(key){
|
205 | return getters[key] || (getters[key] = (function(){
|
206 | var alias = aliases[key] || key,
|
207 | parser = parsers[key] || parse
|
208 |
|
209 | return function(){
|
210 | return parser(compute(this)(alias), true)
|
211 | }
|
212 |
|
213 | }()))
|
214 | }
|
215 |
|
216 | var setter = function(key){
|
217 | return setters[key] || (setters[key] = (function(){
|
218 |
|
219 | var alias = aliases[key] || key,
|
220 | parser = parsers[key] || parse
|
221 |
|
222 | return function(value){
|
223 | this.style[alias] = parser(value, false)
|
224 | }
|
225 |
|
226 | }()))
|
227 | }
|
228 |
|
229 |
|
230 |
|
231 | var trbl = ["Top", "Right", "Bottom", "Left"], tlbl = ["TopLeft", "TopRight", "BottomRight", "BottomLeft"]
|
232 |
|
233 | forEach(trbl, function(d){
|
234 | var bd = "border" + d
|
235 | forEach([ "margin" + d, "padding" + d, bd + "Width", d.toLowerCase()], function(n){
|
236 | parsers[n] = parseLength
|
237 | })
|
238 | parsers[bd + "Color"] = parseColor
|
239 | parsers[bd + "Style"] = parseBorderStyle
|
240 |
|
241 |
|
242 | parsers[bd] = parseBorder
|
243 | getters[bd] = function(){
|
244 | return [
|
245 | getter(bd + "Width").call(this),
|
246 | getter(bd + "Style").call(this),
|
247 | getter(bd + "Color").call(this)
|
248 | ].join(" ")
|
249 | }
|
250 | })
|
251 |
|
252 | forEach(tlbl, function(d){
|
253 | parsers["border" + d + "Radius"] = parseLength
|
254 | })
|
255 |
|
256 | parsers.color = parsers.backgroundColor = parseColor
|
257 | parsers.width = parsers.height = parsers.fontSize = parsers.backgroundSize = parseLength
|
258 |
|
259 |
|
260 |
|
261 | forEach(["margin", "padding"], function(name){
|
262 | parsers[name] = parseShort4
|
263 | getters[name] = function(){
|
264 | return map(trbl, function(d){
|
265 | return getter(name + d).call(this)
|
266 | }, this).join(" ")
|
267 | }
|
268 | })
|
269 |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 | parsers.borderWidth = parseShort4
|
275 |
|
276 | parsers.borderStyle = function(value, normalize){
|
277 | if (value == null || value === "") return normalize ? mirror4(["none"]).join(" ") : ""
|
278 | value = clean(value).split(" ")
|
279 | return clean(mirror4(map(value, function(v){
|
280 | parseBorderStyle(v, normalize)
|
281 | })).join(" "))
|
282 | }
|
283 |
|
284 | parsers.borderColor = function(value, normalize){
|
285 | if (!value || !(value = string.match(value, color.x))) return normalize ? mirror4(["rgba(0,0,0,1)"]).join(" ") : ""
|
286 | return clean(mirror4(map(value, function(v){
|
287 | return parseColor(v, normalize)
|
288 | })).join(" "))
|
289 | }
|
290 |
|
291 | forEach(["Width", "Style", "Color"], function(name){
|
292 | getters["border" + name] = function(){
|
293 | return map(trbl, function(d){
|
294 | return getter("border" + d + name).call(this)
|
295 | }, this).join(" ")
|
296 | }
|
297 | })
|
298 |
|
299 |
|
300 |
|
301 | parsers.borderRadius = parseShort4
|
302 |
|
303 | getters.borderRadius = function(){
|
304 | return map(tlbl, function(d){
|
305 | return getter("border" + d + "Radius").call(this)
|
306 | }, this).join(" ")
|
307 | }
|
308 |
|
309 |
|
310 |
|
311 | parsers.border = parseBorder
|
312 |
|
313 | getters.border = function(){
|
314 | var pvalue
|
315 | for (var i = 0; i < trbl.length; i++){
|
316 | var value = getter("border" + trbl[i]).call(this)
|
317 | if (pvalue && value !== pvalue) return null
|
318 | pvalue = value
|
319 | }
|
320 | return pvalue
|
321 | }
|
322 |
|
323 |
|
324 |
|
325 | parsers.zIndex = parseString
|
326 |
|
327 |
|
328 |
|
329 | parsers.opacity = parseOpacity
|
330 |
|
331 |
|
332 |
|
333 | var filterName = (test.style.MsFilter != null && "MsFilter") || (test.style.filter != null && "filter")
|
334 |
|
335 | if (filterName && test.style.opacity == null){
|
336 |
|
337 | var matchOp = /alpha\(opacity=([\d.]+)\)/i
|
338 |
|
339 | setters.opacity = function(value){
|
340 | value = ((value = parseOpacity(value)) === "1") ? "" : "alpha(opacity=" + Math.round(value * 100) + ")"
|
341 | var filter = compute(this)(filterName)
|
342 | return this.style[filterName] = matchOp.test(filter) ? filter.replace(matchOp, value) : filter + " " + value
|
343 | }
|
344 |
|
345 | getters.opacity = function(){
|
346 | var match = compute(this)(filterName).match(matchOp)
|
347 | return (!match ? 1 : match[1] / 100) + ""
|
348 | }
|
349 |
|
350 | }
|
351 |
|
352 | var parseBoxShadow = parsers.boxShadow = function(value, normalize){
|
353 | return parseShadow(value, normalize, 4)
|
354 | }
|
355 |
|
356 | var parseTextShadow = parsers.textShadow = function(value, normalize){
|
357 | return parseShadow(value, normalize, 3)
|
358 | }
|
359 |
|
360 |
|
361 |
|
362 | forEach(['Webkit', "Moz", "ms", "O", null], function(prefix){
|
363 | forEach([
|
364 | "transition", "transform", "transformOrigin", "transformStyle", "perspective", "perspectiveOrigin", "backfaceVisibility"
|
365 | ], function(style){
|
366 | var cc = prefix ? prefix + capitalize(style) : style
|
367 | if (prefix === "ms") hyphenated[cc] = "-ms-" + hyphenate(style)
|
368 | if (test.style[cc] != null) aliases[style] = cc
|
369 | })
|
370 | })
|
371 |
|
372 | var transitionName = aliases.transition,
|
373 | transformName = aliases.transform
|
374 |
|
375 |
|
376 |
|
377 | if (transitionName === "OTransition") transitionName = null
|
378 |
|
379 |
|
380 |
|
381 |
|
382 |
|
383 | var parseTransform2d, Transform2d
|
384 |
|
385 |
|
386 |
|
387 | if (!transitionName && transformName) (function(){
|
388 |
|
389 | var unmatrix = require("./unmatrix2d")
|
390 |
|
391 | var v = "\\s*([-\\d\\w.]+)\\s*"
|
392 |
|
393 | var rMatrix = RegExp("matrix\\(" + [v, v, v, v, v, v] + "\\)")
|
394 |
|
395 | var decomposeMatrix = function(matrix){
|
396 |
|
397 | var d = unmatrix.apply(null, matrix.match(rMatrix).slice(1)) || [[0, 0], 0, 0, [0, 0]]
|
398 |
|
399 | return [
|
400 |
|
401 | "translate(" + map(d[0], function(v){return round(v) + "px"}) + ")",
|
402 | "rotate(" + round(d[1] * 180 / Math.PI) + "deg)",
|
403 | "skewX(" + round(d[2] * 180 / Math.PI) + "deg)",
|
404 | "scale(" + map(d[3], round) + ")"
|
405 |
|
406 | ].join(" ")
|
407 |
|
408 | }
|
409 |
|
410 | var def0px = function(value){return value || "0px"},
|
411 | def1 = function(value){return value || "1"},
|
412 | def0deg = function(value){return value || "0deg"}
|
413 |
|
414 | var transforms = {
|
415 |
|
416 | translate: function(value){
|
417 | if (!value) value = "0px,0px"
|
418 | var values = value.split(",")
|
419 | if (!values[1]) values[1] = "0px"
|
420 | return map(values, clean) + ""
|
421 | },
|
422 | translateX: def0px,
|
423 | translateY: def0px,
|
424 | scale: function(value){
|
425 | if (!value) value = "1,1"
|
426 | var values = value.split(",")
|
427 | if (!values[1]) values[1] = values[0]
|
428 | return map(values, clean) + ""
|
429 | },
|
430 | scaleX: def1,
|
431 | scaleY: def1,
|
432 | rotate: def0deg,
|
433 | skewX: def0deg,
|
434 | skewY: def0deg
|
435 |
|
436 | }
|
437 |
|
438 | Transform2d = prime({
|
439 |
|
440 | constructor: function(transform){
|
441 |
|
442 | var names = this.names = []
|
443 | var values = this.values = []
|
444 |
|
445 | transform.replace(/(\w+)\(([-.\d\s\w,]+)\)/g, function(match, name, value){
|
446 | names.push(name)
|
447 | values.push(value)
|
448 | })
|
449 |
|
450 | },
|
451 |
|
452 | identity: function(){
|
453 | var functions = []
|
454 | forEach(this.names, function(name){
|
455 | var fn = transforms[name]
|
456 | if (fn) functions.push(name + "(" + fn() + ")")
|
457 | })
|
458 | return functions.join(" ")
|
459 | },
|
460 |
|
461 | sameType: function(transformObject){
|
462 | return this.names.toString() === transformObject.names.toString()
|
463 | },
|
464 |
|
465 |
|
466 |
|
467 |
|
468 | decompose: function(){
|
469 | var transform = this.toString()
|
470 |
|
471 | test.style.cssText = cssText + hyphenate(transformName) + ":" + transform + ";"
|
472 | document.body.appendChild(test)
|
473 | var m = compute(test)(transformName)
|
474 | if (!m || m === "none") m = "matrix(1, 0, 0, 1, 0, 0)"
|
475 | document.body.removeChild(test)
|
476 | return decomposeMatrix(m)
|
477 | }
|
478 |
|
479 | })
|
480 |
|
481 | Transform2d.prototype.toString = function(clean){
|
482 | var values = this.values, functions = []
|
483 | forEach(this.names, function(name, i){
|
484 | var fn = transforms[name]
|
485 | if (!fn) return
|
486 | var value = fn(values[i])
|
487 | if (!clean || value !== fn()) functions.push(name + "(" + value + ")")
|
488 | })
|
489 | return functions.length ? functions.join(" ") : "none"
|
490 | }
|
491 |
|
492 | Transform2d.union = function(from, to){
|
493 |
|
494 | if (from === to) return
|
495 |
|
496 | var fromMap, toMap
|
497 |
|
498 | if (from === "none"){
|
499 |
|
500 | toMap = new Transform2d(to)
|
501 | to = toMap.toString()
|
502 | from = toMap.identity()
|
503 | fromMap = new Transform2d(from)
|
504 |
|
505 | } else if (to === "none"){
|
506 |
|
507 | fromMap = new Transform2d(from)
|
508 | from = fromMap.toString()
|
509 | to = fromMap.identity()
|
510 | toMap = new Transform2d(to)
|
511 |
|
512 | } else {
|
513 |
|
514 | fromMap = new Transform2d(from)
|
515 | from = fromMap.toString()
|
516 | toMap = new Transform2d(to)
|
517 | to = toMap.toString()
|
518 |
|
519 | }
|
520 |
|
521 | if (from === to) return
|
522 |
|
523 | if (!fromMap.sameType(toMap)){
|
524 |
|
525 | from = fromMap.decompose()
|
526 | to = toMap.decompose()
|
527 |
|
528 | }
|
529 |
|
530 | if (from === to) return
|
531 |
|
532 | return [from, to]
|
533 |
|
534 | }
|
535 |
|
536 |
|
537 |
|
538 | parseTransform2d = parsers.transform = function(transform){
|
539 | if (!transform || transform === "none") return "none"
|
540 | return new Transform2d(rMatrix.test(transform) ? decomposeMatrix(transform) : transform).toString(true)
|
541 | }
|
542 |
|
543 |
|
544 |
|
545 |
|
546 |
|
547 | getters.transform = function(){
|
548 | var s = this.style
|
549 | return s[transformName] || (s[transformName] = parseTransform2d(compute(this)(transformName)))
|
550 | }
|
551 |
|
552 |
|
553 | })()
|
554 |
|
555 |
|
556 |
|
557 | var prepare = function(node, property, to){
|
558 |
|
559 | var parser = parsers[property] || parse,
|
560 | from = getter(property).call(node),
|
561 | to = parser(to, true)
|
562 |
|
563 | if (from === to) return
|
564 |
|
565 | if (parser === parseLength || parser === parseBorder || parser === parseShort4){
|
566 |
|
567 | var toAll = to.match(rgLength), i = 0
|
568 |
|
569 | if (toAll) from = from.replace(rgLength, function(fromFull, fromValue, fromUnit){
|
570 |
|
571 | var toFull = toAll[i++],
|
572 | toMatched = toFull.match(rLengthNum),
|
573 | toUnit = toMatched[2]
|
574 |
|
575 | if (fromUnit !== toUnit){
|
576 | var fromPixels = (fromUnit === "px") ? fromValue : pixelRatio(node, fromUnit) * fromValue
|
577 | return round(fromPixels / pixelRatio(node, toUnit)) + toUnit
|
578 | }
|
579 |
|
580 | return fromFull
|
581 |
|
582 | })
|
583 |
|
584 | if (i > 0) setter(property).call(node, from)
|
585 |
|
586 | }else if (parser === parseTransform2d){
|
587 |
|
588 | return Transform2d.union(from, to)
|
589 |
|
590 | }
|
591 |
|
592 | return (from !== to) ? [from, to] : null
|
593 |
|
594 | }
|
595 |
|
596 |
|
597 |
|
598 | var BrowserAnimation = prime({
|
599 |
|
600 | inherits: fx,
|
601 |
|
602 | constructor: function BrowserAnimation(node, property){
|
603 |
|
604 | var _getter = getter(property),
|
605 | _setter = setter(property)
|
606 |
|
607 | this.get = function(){
|
608 | return _getter.call(node)
|
609 | }
|
610 |
|
611 | this.set = function(value){
|
612 | return _setter.call(node, value)
|
613 | }
|
614 |
|
615 | BrowserAnimation.parent.constructor.call(this, this.set)
|
616 |
|
617 | this.node = node
|
618 | this.property = property
|
619 |
|
620 | }
|
621 |
|
622 | })
|
623 |
|
624 | var JSAnimation
|
625 |
|
626 |
|
627 |
|
628 | JSAnimation = prime({
|
629 |
|
630 | inherits: BrowserAnimation,
|
631 |
|
632 | constructor: function JSAnimation(){
|
633 | return JSAnimation.parent.constructor.apply(this, arguments)
|
634 | },
|
635 |
|
636 | start: function(to){
|
637 |
|
638 | this.stop()
|
639 |
|
640 | if (this.duration === 0){
|
641 | this.cancel(to)
|
642 | return this
|
643 | }
|
644 |
|
645 | var fromTo = prepare(this.node, this.property, to)
|
646 |
|
647 | if (!fromTo){
|
648 | this.cancel(to)
|
649 | return this
|
650 | }
|
651 |
|
652 | JSAnimation.parent.start.apply(this, fromTo)
|
653 |
|
654 | if (!this.cancelStep) return this
|
655 |
|
656 |
|
657 |
|
658 | var parser = parsers[this.property] || parse
|
659 |
|
660 |
|
661 |
|
662 |
|
663 |
|
664 |
|
665 | if ((parser === parseBoxShadow || parser === parseTextShadow || parser === parse) &&
|
666 | (this.templateFrom !== this.templateTo)){
|
667 | this.cancelStep()
|
668 | delete this.cancelStep
|
669 | this.cancel(to)
|
670 | }
|
671 |
|
672 | return this
|
673 | },
|
674 |
|
675 | parseEquation: function(equation){
|
676 | if (typeof equation === "string") return JSAnimation.parent.parseEquation.call(this, equation)
|
677 | }
|
678 |
|
679 |
|
680 | })
|
681 |
|
682 |
|
683 |
|
684 | var remove3 = function(value, a, b, c){
|
685 | var index = indexOf(a, value)
|
686 | if (index !== -1){
|
687 | a.splice(index, 1)
|
688 | b.splice(index, 1)
|
689 | c.splice(index, 1)
|
690 | }
|
691 | }
|
692 |
|
693 | var CSSAnimation = prime({
|
694 |
|
695 | inherits: BrowserAnimation,
|
696 |
|
697 | constructor: function CSSAnimation(node, property){
|
698 | CSSAnimation.parent.constructor.call(this, node, property)
|
699 |
|
700 | this.hproperty = hyphenate(aliases[property] || property)
|
701 |
|
702 | var self = this
|
703 |
|
704 | this.bSetTransitionCSS = function(time){
|
705 | self.setTransitionCSS(time)
|
706 | }
|
707 |
|
708 | this.bSetStyleCSS = function(time){
|
709 | self.setStyleCSS(time)
|
710 | }
|
711 |
|
712 | this.bComplete = function(){
|
713 | self.complete()
|
714 | }
|
715 | },
|
716 |
|
717 | start: function(to){
|
718 |
|
719 | this.stop()
|
720 |
|
721 | if (this.duration === 0){
|
722 | this.cancel(to)
|
723 | return this
|
724 | }
|
725 |
|
726 | var fromTo = prepare(this.node, this.property, to)
|
727 |
|
728 | if (!fromTo){
|
729 | this.cancel(to)
|
730 | return this
|
731 | }
|
732 |
|
733 | this.to = fromTo[1]
|
734 |
|
735 |
|
736 | this.cancelSetTransitionCSS = requestFrame(this.bSetTransitionCSS)
|
737 |
|
738 | return this
|
739 | },
|
740 |
|
741 | setTransitionCSS: function(time){
|
742 | delete this.cancelSetTransitionCSS
|
743 | this.resetCSS(true)
|
744 |
|
745 |
|
746 | this.cancelSetStyleCSS = requestFrame(this.bSetStyleCSS)
|
747 | },
|
748 |
|
749 | setStyleCSS: function(time){
|
750 | delete this.cancelSetStyleCSS
|
751 | var duration = this.duration
|
752 |
|
753 |
|
754 | this.cancelComplete = setTimeout(this.bComplete, duration)
|
755 | this.endTime = time + duration
|
756 | this.set(this.to)
|
757 | },
|
758 |
|
759 | complete: function(){
|
760 | delete this.cancelComplete
|
761 | this.resetCSS()
|
762 | this.callback(this.endTime)
|
763 | },
|
764 |
|
765 | stop: function(hard){
|
766 | if (this.cancelExit){
|
767 | this.cancelExit()
|
768 | delete this.cancelExit
|
769 | } else if (this.cancelSetTransitionCSS){
|
770 |
|
771 | this.cancelSetTransitionCSS()
|
772 | delete this.cancelSetTransitionCSS
|
773 | } else if (this.cancelSetStyleCSS){
|
774 |
|
775 | this.cancelSetStyleCSS()
|
776 | delete this.cancelSetStyleCSS
|
777 |
|
778 |
|
779 | if (hard) this.resetCSS()
|
780 | } else if (this.cancelComplete){
|
781 |
|
782 | clearTimeout(this.cancelComplete)
|
783 | delete this.cancelComplete
|
784 |
|
785 |
|
786 | if (hard){
|
787 | this.resetCSS()
|
788 | this.set(this.get())
|
789 | }
|
790 | }
|
791 | return this
|
792 | },
|
793 |
|
794 | resetCSS: function(inclusive){
|
795 | var rules = compute(this.node),
|
796 | properties = rules(transitionName + "Property").replace(/\s+/g, "").split(","),
|
797 | durations = rules(transitionName + "Duration").replace(/\s+/g, "").split(","),
|
798 | equations = rules(transitionName + "TimingFunction").replace(/\s+/g, "").match(/cubic-bezier\([\d-.,]+\)/g)
|
799 |
|
800 | remove3("all", properties, durations, equations)
|
801 | remove3(this.hproperty, properties, durations, equations)
|
802 |
|
803 | if (inclusive){
|
804 | properties.push(this.hproperty)
|
805 | durations.push(this.duration + "ms")
|
806 | equations.push("cubic-bezier(" + this.equation + ")")
|
807 | }
|
808 |
|
809 | var nodeStyle = this.node.style
|
810 |
|
811 | nodeStyle[transitionName + "Property"] = properties
|
812 | nodeStyle[transitionName + "Duration"] = durations
|
813 | nodeStyle[transitionName + "TimingFunction"] = equations
|
814 | },
|
815 |
|
816 | parseEquation: function(equation){
|
817 | if (typeof equation === "string") return CSSAnimation.parent.parseEquation.call(this, equation, true)
|
818 | }
|
819 |
|
820 | })
|
821 |
|
822 |
|
823 |
|
824 | var BaseAnimation = transitionName ? CSSAnimation : JSAnimation
|
825 |
|
826 | var moofx = function(x, y){
|
827 | return (typeof x === "function") ? fx(x) : elements(x, y)
|
828 | }
|
829 |
|
830 | elements.implement({
|
831 |
|
832 |
|
833 |
|
834 | animate: function(A, B, C){
|
835 |
|
836 | var styles = A, options = B
|
837 |
|
838 | if (typeof A === "string"){
|
839 | styles = {}
|
840 | styles[A] = B
|
841 | options = C
|
842 | }
|
843 |
|
844 | if (options == null) options = {}
|
845 |
|
846 | var type = typeof options
|
847 |
|
848 | options = type === "function" ? {
|
849 | callback: options
|
850 | } : (type === "string" || type === "number") ? {
|
851 | duration: options
|
852 | } : options
|
853 |
|
854 | var callback = options.callback || function(){},
|
855 | completed = 0,
|
856 | length = 0
|
857 |
|
858 | options.callback = function(t){
|
859 | if (++completed === length) callback(t)
|
860 | }
|
861 |
|
862 | for (var property in styles){
|
863 |
|
864 | var value = styles[property],
|
865 | property = camelize(property)
|
866 |
|
867 | this.forEach(function(node){
|
868 | length++
|
869 | var self = elements(node), anims = self._animations || (self._animations = {})
|
870 | var anim = anims[property] || (anims[property] = new BaseAnimation(node, property))
|
871 | anim.setOptions(options).start(value)
|
872 | })
|
873 | }
|
874 |
|
875 | return this
|
876 |
|
877 | },
|
878 |
|
879 |
|
880 |
|
881 | style: function(A, B){
|
882 |
|
883 | var styles = A
|
884 |
|
885 | if (typeof A === "string"){
|
886 | styles = {}
|
887 | styles[A] = B
|
888 | }
|
889 |
|
890 | for (var property in styles){
|
891 | var value = styles[property],
|
892 | set = setter(property = camelize(property))
|
893 |
|
894 | this.forEach(function(node){
|
895 | var self = elements(node), anims = self._animations, anim
|
896 | if (anims && (anim = anims[property])) anim.stop(true)
|
897 | set.call(node, value)
|
898 | })
|
899 | }
|
900 |
|
901 | return this
|
902 |
|
903 | },
|
904 |
|
905 | compute: function(property){
|
906 |
|
907 | property = camelize(property)
|
908 | var node = this[0]
|
909 |
|
910 |
|
911 |
|
912 | if (property === "transform" && parseTransform2d) return compute(node)(transformName)
|
913 |
|
914 | var value = getter(property).call(node)
|
915 |
|
916 |
|
917 |
|
918 | return (value != null) ? value.replace(rgLength, function(match, value, unit){
|
919 | return (unit === "px") ? match : pixelRatio(node, unit) * value + "px"
|
920 | }) : ''
|
921 |
|
922 | }
|
923 |
|
924 | })
|
925 |
|
926 | moofx.parse = function(property, value, normalize){
|
927 | return (parsers[camelize(property)] || parse)(value, normalize)
|
928 | }
|
929 |
|
930 | module.exports = moofx
|