timelines: [],\r
\r
/*開始フレーム数の候補。アニメーションの開始条件となる\r
- * 単位はフレーム数であって、秒数ではない*/\r
- begin: 0,\r
+ * 単位はフレーム数であって、秒数ではない\r
+ * なお、初期値については、開始フレームが負の値を考慮しているため*/\r
+ begin: -Number.MAX_VALUE,\r
\r
/*活動継続時間 (Active Duration)のフレーム数。アニメーションの継続条件となる\r
* 単位はフレーム数であって、秒数ではない*/\r
/*setFrame メソッド\r
* フレーム数を数値num まで進めるか、戻す*/\r
setFrame: function( /*number*/ num) {\r
- if((num < this.begin) || (num >= (this.begin+this.activeTime))) {\r
- return;\r
- }\r
this.currentFrame = num;\r
var timelines = this.timelines;\r
for (var i=0;i<timelines.length;++i) {\r
},\r
\r
/*引数に渡された時刻リストの中から、現在フレームf以下の、最大値を求めるメソッド\r
- * -1を返したときはリストの中にf以下の値がないことを示す*/\r
+ * Number.MIN_VALUEの値を返したときはリストの中にf以下の値がないことを示す*/\r
getMaxList: function (f, list) {\r
- var maxTime = -1; /*時刻の最大値*/\r
+ var maxTime = -Number.MAX_VALUE; /*時刻の最大値*/\r
while( list ) {\r
var v = list.value;\r
- /*f以下の開始リスト値のうち、最大値をstartTimeに代入*/\r
+ /*f以下の開始リスト値のうち、最大値をmaxTimeに代入*/\r
if ( (v <= f)\r
&& (maxTime <= v) ) {\r
maxTime = v;\r
* 現在フレーム数 f より大きい数値は、更新できる条件と無関係なので、除外しておく\r
* だから、f以下の値の中から、最大値を探して、\r
* それをbeginプロパティの値cacheBeginと比較する*/\r
- var startTime = this.getMaxList(f, this.beginList),\r
- endTime = this.getMaxList(f, this.endList),\r
+ var startTime = this.getMaxList(f, this.beginList);\r
+ if (startTime === -Number.MAX_VALUE) {\r
+ (state > post) && (this.state = begin);\r
+ return this;\r
+ }\r
+ var endTime = this.getMaxList(f, this.endList),\r
isWait = (state === wait),\r
cacheBegin = this.begin;\r
if ( !startTime && isWait) {\r
- /*開始時刻が0ならば、アニメーションを開始*/\r
+ /*開始時刻が0ならば、アニメーションを開始\r
+ * ただし、アニメが終了した後のPOSTWAITING状態の時には作動させない*/\r
this.begin = 0;\r
this.state = begin;\r
} else if ( isWait || (state === post) ) {\r
},\r
\r
/*凍結処理をするために、進捗率を最後まで進めて調整するメソッド\r
+ * 返り値は調整された進捗率\r
* もっぱら、_setEndFrameメソッドで使われる*/\r
- freeze: function($list) {\r
+ getAdvanceEnd: function($list) {\r
var line = this.timeline,\r
duration = line.simpleDuration;\r
if (duration) {\r
} else {\r
advance = 0;\r
}\r
- return this.tocall(advance);\r
+ return advance;\r
},\r
\r
/*_setEndFrameメソッドは、終了処理と凍結作業をする*/\r
_setEndFrame: function($list) {\r
/*上書きされたメソッドを呼び出してアニメーションの凍結作業をする*/\r
if (this.fill === "freeze") {\r
- this.setAttribute(this.freeze($list));\r
+ this.setAttribute(this.tocall( this.getAdvanceEnd($list) ));\r
line = duration = advance = void 0;\r
} else {\r
this.removeAttribute();\r
this.setAttribute = isPostActive ? this.__setAttribute\r
: this.$animateElement.setAttribute;\r
/*上書きされたメソッドを呼び出す*/\r
- this.$animateElement._setFrame.call(this, currentFrame);\r
+ this.$animateElement._setFrame.call(this, $list);\r
},\r
\r
_setEndFrame: function($list) {\r
if (!list) {\r
return;\r
}\r
+ var item = list[this.numberOfList];\r
if (this.fill === "remove") {\r
- if (!list[this.numberOfList]) {\r
+ if (!item) {\r
return;\r
} else if (!this.isSum) {\r
/*凍結処理をしないで、かつ、元の状態に戻して、効果が出ないようにする*/\r
- list[this.numberOfList].isPlaying = false;\r
+ item.isPlaying = false;\r
} else {\r
/*凍結処理をしないで、かつ、効果を出すが、変形させないようにする*/\r
- list[this.numberOfList].value = "translate(0)";\r
+ item.value = "translate(0)";\r
}\r
} else {\r
- /*凍結処理をする*/\r
- list[this.numberOfList].value = this.freeze($list);\r
+ /*凍結処理をする\r
+ * 自前のtocallメソッドはvalueプロパティを書きかえてしまうため、\r
+ * 上書きメソッドを呼び出す*/\r
+ item.value = this.type+ "(" \r
+ +this.$animateElement.tocall.call( this, this.getAdvanceEnd($list) )+ ")";\r
}\r
+ this.setAttribute( this.joinList(this.defaultValue || "") );\r
+ item = void 0;\r
},\r
\r
/*setAddメソッドのオーバライド\r
/*isPlayingプロパティはアニメーション再生終了後でもtrueとなるので注意*/\r
parent.__transformList.push( {isPlaying: false,\r
value: "translate(0)",\r
- isSum: this.isSum,\r
- isRemove: (this.fill === "remove")\r
+ isSum: this.isSum\r
} );\r
}\r
} )\r
.up("$motionElement")\r
.mix( function() {\r
- /*setRFrameメソッドを再定義*/\r
+ /*$animateTransformElementオブジェクトのでは、うまくいかないため、\r
+ * setRFrameとsetEndFrameメソッドを再定義*/\r
this._setFrame = this.$animateElement._setFrame;\r
+ this._setEndFrame = this.$animateElement._setEndFrame;\r
})\r
.mix( {\r
numberOfList: -1,\r
}\r
} );\r
\r
-/*$svgEventオブジェクトは、SVGEvent発火を監視するためのオブジェクト*/\r
-base("$frame").up("$svgEvent").mix( {\r
- /*イベントのスケジュール記録*/\r
- first: null,\r
- \r
- /*タイムラインの最後のキャッシュ*/\r
- lastTimeLine: null,\r
- \r
- /*setTimeTable メソッドはスケジュールの記録をつけるためのメソッド*/\r
- setTimeTable: function () {\r
- var timelines = this.timelines;\r
- for (var i=0, obj = null;i<timelines.length;++i) {\r
- if (!timelines[i].target || !timelines[i].isResolved) {\r
- /*一度スケジュールを作成して実行したり、未解決だったタイムラインは、処理しない*/\r
- continue;\r
- }\r
- /*タイムラインから、beginEventとendEventを発火するスケジュールを作成*/\r
- var timeline = timelines[i],\r
- begin = timeline.begin,\r
- target = timeline.target,\r
- simpleDur = timeline.simpleDuration,\r
- activeTime = timeline.activeTime;\r
- var first = {\r
- frame: begin,\r
- eventType: "begin",\r
- target: target,\r
- next: {\r
- frame: begin+activeTime,\r
- eventType: "end",\r
- target: target,\r
- next: null\r
- }\r
- };\r
- if (obj) {\r
- obj.next.next = first;\r
- } else if (!this.first) {\r
- /*firstプロパティがすでにある場合、書き換えない*/\r
- this.first = first;\r
- } else {\r
- /*firstプロパティがある場合、そのリストのリンクをたどっていって、\r
- * 最後の尾を変数firstとつなげる*/\r
- var fst = this.first;\r
- while(fst.next) {\r
- fst = fst.next;\r
- }\r
- fst.next = first;\r
- }\r
- obj = first;\r
- if (simpleDur && (activeTime !== simpleDur)) {\r
- /*活動継続時間と単純持続時間が異なるとき、repeatイベントを設定\r
- * ただし、repeatイベントはendイベントが発生する前に起きるものと仮定*/\r
- for (var a = first, m= begin + simpleDur, n=1;m < begin + activeTime; m+=simpleDur, ++n) {\r
- a.next = {\r
- frame: m,\r
- eventType: "repeat",\r
- target: target,\r
- /*リピートの回数 (n >= 1)*/\r
- count: n,\r
- next: a.next\r
- };\r
- a = a.next;\r
- }\r
- }\r
- /*一度、スケジュールを作っておいたタイムラインは次回から処理しないようにする*/\r
- timeline.target = null;\r
- }\r
- timelines = obj = first = begin = target = simpleDur = activeTime = void 0;\r
- },\r
- \r
- $frame: base("$frame"),\r
- \r
- setFrame: function (num) {\r
- var timelines = this.timelines,\r
- lastTimeLine = timelines[timelines.length-1],\r
- s = this.$frame.setFrame(num);\r
- /*キャッシュのlastTimeLineプロパティを使って、再びスケジュールの計算をさせないようにする*/\r
- if (this.lastTimeLine !== lastTimeLine) {\r
- this.lastTimeLine = lastTimeLine;\r
- this.setTimeTable();\r
- }\r
- /*スケジュールに記録しておいたものを実行して、イベントを発火\r
- * また、発火した場合は記録から取り除いて、次回から再び発火しないようにする*/\r
- var obj = this.first,\r
- cobj = obj,\r
- floor = Math.floor;\r
- while(obj) {\r
- var frame = obj.frame,\r
- target = obj.target,\r
- detail = 0;\r
- if (frame <= num) {\r
- /*IE11ではSVGEventsやDOMEventsを使うと問題が起きるため、MouseEventsで代用する*/\r
- if (obj.eventType === "repeat") {\r
- /*detailは何回リピートしたか*/\r
- detail = obj.count;\r
- }\r
- /*ポインタの連結を変更することで、リストからobj を除去\r
- * 一度除去したものはイベントを発生させない*/\r
- cobj.next = obj.next;\r
- if (this.first === obj) {\r
- cobj = obj.next;\r
- this.first = cobj;\r
- } else {\r
- cobj = obj;\r
- }\r
- var evt = target.ownerDocument.createEvent("MouseEvents");\r
- evt.initMouseEvent(obj.eventType+"Event" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
- target.dispatchEvent(evt);\r
- } else {\r
- /*next プロパティを書き換えるためのobj オブジェクトのキャッシュ*/\r
- cobj = obj;\r
- }\r
- obj = obj.next;\r
- }\r
- obj = num = first = frame = target = cobj = detail = void 0;\r
- return s;\r
- }\r
-} );\r
-\r
function getDocument() \r
{\r
var svg = document.getElementsByTagName("object"),\r
var id = __step(),\r
idstop = function() {\r
/*アニメーションを中止する関数*/\r
- window.cancelAnimationRequest && cancelAnimationRequest(id);\r
+ window.cancelAnimationFrame && cancelAnimationFrame(id);\r
};\r
base("$frame").on("pauseAnimation", idstop);\r
window.addEventListener("unload", idstop);\r
handle: null\r
};\r
(function(frame) {\r
- var $frame = base("$frame"),\r
- $f = $frame.$svgEvent,\r
- _cancel = cancel; /*cancelのエイリアス*/\r
- _cancel.handle = requestAnimationFrame(step);\r
- function step() {\r
- if (!$frame.isPaused) {\r
+ var _cancel = cancel; /*cancelのエイリアス*/\r
+ var step = function () {\r
+ if (!this.isPaused) {\r
frame++;\r
try {\r
- $f.setFrame(frame);\r
+ this.setFrame(frame);\r
} catch(e) {\r
}\r
_cancel.handle = requestAnimationFrame(step);\r
}\r
- };\r
+ }.bind(base("$frame"));\r
+ _cancel.handle = requestAnimationFrame(step);\r
})(-1);\r
return cancel;\r
} else {\r
setInterval( (function(frame) {\r
- var $f = base("$frame").$svgEvent;\r
+ var $f = base("$frame");\r
return function () {\r
frame++;\r
$f.setFrame(frame);\r