timelines: [],\r
\r
/*開始フレーム数の候補。アニメーションの開始条件となる\r
- * 単位はフレーム数であって、秒数ではない*/\r
- begin: 0,\r
+ * 単位はフレーム数であって、秒数ではない\r
+ * なお、初期値については、開始フレームが負の値を考慮しているため*/\r
+ begin: -Number.MAX_VALUE,\r
\r
/*活動継続時間 (Active Duration)のフレーム数。アニメーションの継続条件となる\r
* 単位はフレーム数であって、秒数ではない*/\r
\r
/*アニメーションを開始させるメソッド*/\r
startAnimation: function() {\r
- /*__step関数は最後に書く*/\r
- __step();\r
+ /*$getDocument.step関数は最後に書く*/\r
+ base("$getDocument").step();\r
},\r
\r
/*アニメーションが停止した状態かどうか、停止しているならばtrue*/\r
pauseAnimation: function() {\r
this.isPaused = true;\r
},\r
+ \r
+ /*後述のinitializeメソッドで使うオブジェクトリスト*/\r
+ objList: [],\r
+ \r
+ /*オブジェクトの初期化処理*/\r
+ initialize: function() {\r
+ var list = this.objList;\r
+ for (var i=0;i<list.length;++i) {\r
+ list[i].initialize();\r
+ }\r
+ },\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
} ).mix( function($frame) {\r
$frame.up("$list").mix( {\r
- /*開始時刻リスト (後述のupdateStateメソッドで使う)*/\r
+ /*終了時刻(単位フレーム数)のキャッシュとして使う*/\r
+ end: 0,\r
+ \r
+ /*開始時刻から終了時刻までのフレーム数\r
+ * これがactiveTimeより短ければ、活動継続時間とみなす*/\r
+ beginEnd: Number.MAX_VALUE,\r
+ \r
+ /*開始時刻(単位フレーム数)リスト (後述のupdateStateメソッドで使う)*/\r
beginList: { \r
next: null,\r
value: Number.MAX_VALUE\r
},\r
\r
- /*終了時刻リスト (後述のupdateStateメソッドで使う)*/\r
+ /*終了時刻(単位フレーム数)リスト (後述のupdateStateメソッドで使う)*/\r
endList: {\r
next: null,\r
value: Number.MAX_VALUE\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
/*終了処理をした後の待機状態を示す定数*/\r
POSTWAITING: 4,\r
\r
+ /*初期化用メソッド*/\r
+ init: function() {\r
+ this.state = this.WAITING;\r
+ this.begin = 0;\r
+ return this;\r
+ },\r
+ \r
/*引数で指定されたフレーム数に応じて、stateプロパティを更新するメソッド*/\r
updateState: function( /*number*/ f) {\r
if (f === void 0) {\r
post = /*this.POSTWAITING*/ 4;\r
/*beginListプロパティと、endListプロパティの中で、\r
* 現在フレーム数 f より大きい数値は、更新できる条件と無関係なので、除外しておく\r
- * ã\81¾ã\81\9f、f以下の値の中から、最大値を探して、\r
+ * ã\81 ã\81\8bã\82\89、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 ( (state === wait) || (state === post) ) {\r
+ if ( !startTime && isWait) {\r
+ /*開始時刻が0ならば、アニメーションを開始\r
+ * ただし、アニメが終了した後のPOSTWAITING状態の時には作動させない*/\r
+ this.begin = 0;\r
+ this.state = begin;\r
+ } else if ( isWait || (state === post) ) {\r
if (startTime > cacheBegin) {\r
this.state = begin;\r
/*beginプロパティに開始時刻をキャッシュ用に保存*/\r
this.begin = startTime;\r
- } else if (!startTime) {\r
- /*開始時刻が0ならば、アニメーションを開始*/\r
- this.state = begin;\r
}\r
} else if (state === begin) {\r
if (endTime >= cacheBegin) {\r
/*終了時刻にもう到達したときは、直接BEGINNING状態からENDING状態へ移行*/\r
this.state = end;\r
+ /*endTimeを終了時刻とみなす*/\r
+ (endTime > 0) && (this.end = endTime);\r
+ /*activeTimeプロパティは、begin属性とend属性が反映されていないため、\r
+ * beginEndプロパティに別に設定しておく*/\r
+ this.beginEnd = 0;\r
} else {\r
this.state = play;\r
}\r
} else if (state === play) {\r
- if ( (endTime >= cacheBegin) || (startTime > cacheBegin) ) {\r
+ /*activeTimeプロパティを比較して、変数endTimeを書き換える*/\r
+ var act = cacheBegin + this.activeTime;\r
+ endTime = (endTime > act) ? act\r
+ : endTime;\r
+ if ( (f >= act) || (endTime >= cacheBegin) || (startTime > cacheBegin) ) {\r
/*終了時刻に到達したか、再び開始イベントが発火されたとき*/\r
this.state = end;\r
+ if (endTime > 0) {\r
+ /*endTimeを終了時刻とみなす*/\r
+ this.end = endTime;\r
+ /*activeTimeプロパティは、begin属性とend属性が反映されていないため、\r
+ * beginEndプロパティに別に設定しておく*/\r
+ this.beginEnd = endTime - cacheBegin;\r
+ }\r
}\r
} else if (state === end) {\r
- if (endTime >= cacheBegin) {\r
- this.state = post;\r
- } else {\r
+ if (startTime > cacheBegin) {\r
/*再生中に開始イベントが発火されて、終了状態となったとき*/\r
this.state = begin;\r
this.begin = startTime;\r
+ } else {\r
+ this.state = post;\r
}\r
} else {\r
this.state = begin;\r
}\r
- cacheBegin = startTime = endTime = void 0;\r
+ cacheBegin = startTime = endTime = isWait = state = void 0;\r
return this;\r
},\r
\r
for (var i=0;i<list.length;++i) {\r
list[i](this);\r
}\r
- /*開始時刻と終了時刻が一致した場合はstateはENDING状態*/\r
+ /*開始時刻と終了時刻が一致した場合はstateはENDING状態\r
+ * それ以外はPLAYING状態*/\r
state = this.updateState(f).state;\r
}\r
if (state === /*this.ENDING*/ 3) {\r
ele,\r
/*endListのvalueプロパティには、活動継続フレーム数と開始フレーム数を足したものが入る*/\r
endList = this.$list.addEndList(Number.MAX_VALUE);\r
- if (this.$end) {\r
- /*$endオブジェクトを継承していた場合、\r
- *活動継続フレーム数関連のリストは無効とする*/\r
- endList = { value: 0};\r
- }\r
if (str === "indefinite") {\r
this.begin = Number.MAX_VALUE;\r
} else if (plusminus > 0) {\r
objList = this.$list.addList(Number.MAX_VALUE),\r
/*イベントのリスナーとして使う*/\r
listener = function(evt) {\r
- objList.value = this.begin = eventOffset + this.$frame.currentFrame;\r
- endList.value = this.$list.begin + this.activeTime;\r
+ objList.value = this.begin = eventOffset + base("$frame").currentFrame;\r
this.isResolved = true;\r
};\r
this.eventOffset = eventOffset;\r
} else {\r
/*開始リストに登録しておく($endの場合は終了リストに登録)*/\r
this.$list.addList(this.begin);\r
- /*活動継続時間から算出される終了フレーム数は、終了リストに入れておく*/\r
- endList.value = this.begin + this.activeTime;\r
}\r
s = event = str = plusminus = ele = void 0;\r
},\r
var s = ( this.$activate = this.$activate.up() );\r
/*$endオブジェクトに付属している$listプロパティを更新したものと一致させておく*/\r
s.end && (s.end.$list = this.$list);\r
- this.activeTime = s.call() || Number.MAX_VALUE;\r
+ this.activeTime = this.$list.activeTime = s.call() || Number.MAX_VALUE;\r
this.simpleDuration = s.simpleDur;\r
return this;\r
}\r
}\r
return s;\r
},\r
+ \r
+ /*repeatイベントの発火時刻リスト\r
+ * setSmilEventメソッドを見よ*/\r
+ _repeatList: [],\r
+ \r
+ /*リピート回数を示すプロパティ\r
+ * setSmilEventメソッドを見よ*/\r
+ _repeatCount: 0,\r
+ \r
+ /*SMILイベント関連を発火させるためのメソッド\r
+ * もっぱら、$attributeオブジェクトのpush メソッドで使われる*/\r
+ setSmilEvent: function($list) {\r
+ $list.addEvent("begin", function($list) {\r
+ var target = this._ele,\r
+ detail = 0;\r
+ /*IE11のために、MouseEventsでSMILEventsの代用をする*/\r
+ var evt = target.ownerDocument.createEvent("MouseEvents");\r
+ evt.initMouseEvent("beginEvent" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
+ target.dispatchEvent(evt);\r
+ /*repeatイベントのために、_repeatListプロパティを初期化する*/\r
+ var list = this._repeatList = [],\r
+ active = $list.activeTime,\r
+ begin = $list.begin,\r
+ simpleDuration = this.timeline.simpleDuration;\r
+ if (simpleDuration && (simpleDuration !== active)\r
+ && (active !== Number.MAX_VALUE) ) {\r
+ /*活動継続時間と単純持続時間が異なるとき、repeatイベントを設定*/\r
+ for (var m= simpleDuration, n=1;m < active ; m+=simpleDuration) {\r
+ list.push( {\r
+ frame: begin + m,\r
+ /*リピートの回数 (n >= 1)*/\r
+ count: n\r
+ } );\r
+ ++n;\r
+ }\r
+ }\r
+ }.bind(this) );\r
+ \r
+ $list.addEvent("play", function($list) {\r
+ var target = this._ele,\r
+ detail = 0,\r
+ frame = $list.currentFrame,\r
+ list = this._repeatList;\r
+ if (!list.length) {\r
+ return;\r
+ }\r
+ for (var i=0;i<list.length;++i) {\r
+ if ( (this._repaetCount >= i+1)\r
+ || (list[i].frame >= frame) ) {\r
+ this._repeatCount = detail;\r
+ break;\r
+ } \r
+ detail = list[i].count;\r
+ var evt = target.ownerDocument.createEvent("MouseEvents");\r
+ evt.initMouseEvent("repeatEvent" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
+ target.dispatchEvent(evt);\r
+ }\r
+ }.bind(this) );\r
+ \r
+ $list.addEvent("end", function() {\r
+ var target = this._ele,\r
+ detail = 0;\r
+ var evt = target.ownerDocument.createEvent("MouseEvents");\r
+ evt.initMouseEvent("endEvent" ,true, true, window, detail, 0, 0, 0, 0, false, false, false, false, 0, target);\r
+ target.dispatchEvent(evt);\r
+ }.bind(this) );\r
+ },\r
\r
/*引数で指定した要素 ele の属性を解析して、フレームに追加する*/\r
push: function(/*Element Node*/ ele) {\r
max: this.getAttr("max", "indefinite")\r
} )\r
} ).updateList().parse();\r
- $frame.addLine(frame.$list);\r
+ $frame.addLine(frame.$list.init());\r
+ \r
/*beginElementメソッドを追加*/\r
- function eleMethod (obj, eventName) {\r
- return (obj.string !== "indefinite") ? function(){}\r
+ var objList = frame.$list.addList(Number.MAX_VALUE),\r
+ /*endListのvalueプロパティには、活動継続フレーム数と開始フレーム数を足したものが入る*/\r
+ endList = frame.$list.addEndList(Number.MAX_VALUE);\r
+ ele.beginElement = (frame.string !== "indefinite") ? function(){}\r
: function() {\r
+ objList.value = frame.begin = base("$frame").currentFrame;\r
+ frame.isResolved = true;\r
var evt = this.ownerDocument.createEvent("MouseEvents");\r
- evt.initMouseEvent(eventName + "Event" ,true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, this);\r
+ evt.initMouseEvent("beginEvent" ,true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, this);\r
this.dispatchEvent(evt);\r
};\r
- };\r
- ele.beginElement = eleMethod(frame, "begin");\r
/*endElementメソッドを追加*/\r
- ele.endElement = eleMethod(frame.$activate.end || {}, "end");\r
+ var endFrame = frame.$activate.end || {};\r
+ ele.endElement = (endFrame.string !== "indefinite") ? function(){}\r
+ : function() {\r
+ if (frame.isResolved) {\r
+ endFrame.isResolved = true;\r
+ endList.value = base("$frame").currentFrame;\r
+ var evt = this.ownerDocument.createEvent("MouseEvents");\r
+ evt.initMouseEvent("endEvent" ,true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, this);\r
+ this.dispatchEvent(evt);\r
+ }\r
+ };\r
/*setFrameメソッドを使ったときの、再帰スタックの使いすぎを防ぐため*/\r
frame.timelines = [];\r
+ this.setSmilEvent(frame.$list);\r
begin = ele = void 0;\r
return frame;\r
},\r
/*to属性の値、文字列*/\r
to: "",\r
\r
+ \r
+ /*後述のinitializeメソッドで使う要素リスト\r
+ * getElementsByTagNameNSメソッドの返り値をArray化したことを想定*/\r
+ elementList: [],\r
+ \r
+ /*何番目からelementListを処理しているかの数値*/\r
+ numberOfElemList: 0,\r
+ \r
+ /*initialize メソッド\r
+ * 要素リストを初期化させる\r
+ * 初期化処理を分散させるために使う*/\r
+ initialize: function() {\r
+ var eles = this.elementList;\r
+ if (!eles || !eles.length) {\r
+ return;\r
+ }\r
+ var length = this.numberOfElemList+50;\r
+ for (var i=length-50; i<length; ++i) {\r
+ if (eles.length <= i) {\r
+ this.elementList = null;\r
+ return;\r
+ }\r
+ this.up().init(eles[i]);\r
+ }\r
+ this.numberOfElemList += 50;\r
+ eles = length = void 0;\r
+ },\r
+ \r
/*initメソッドで使われるアニメーション関数*/\r
_setFrame: function ($list) {\r
this.setAttribute(this.to);\r
},\r
\r
_setFrame: function($list) {\r
- var currentTime = $list.currentFrame;\r
+ var currentFrame = $list.currentFrame;\r
/*durationは単純継続時間\r
*advanceは継続時間内での、進捗率\r
* 仕様を参照 http://www.w3.org/TR/smil-animation/#AnimFuncValues\r
/*単純継続時間が不定の場合、補間はせずに初期値が採用されるため、advanceは0となる\r
* 仕様を参照 SMIL Animation 3.2.2. Animation function values のInterpolation and indefinite simple durations\r
* http://www.w3.org/TR/2001/REC-smil-animation-20010904/#AnimFuncValues*/\r
- advance = duration ? ( (currentTime - $list.begin) % duration ) / duration\r
+ advance = duration ? ( (currentFrame - $list.begin) % duration ) / duration\r
: 0;\r
this.setAttribute(this.tocall(advance));\r
line = duration = advance = void 0;\r
},\r
\r
- /*_setEndFrameメソッドは、終了処理と凍結作業をするときに、falseを返す*/\r
+ /*凍結処理をするために、進捗率を最後まで進めて調整するメソッド\r
+ * 返り値は調整された進捗率\r
+ * もっぱら、_setEndFrameメソッドで使われる*/\r
+ getAdvanceEnd: function($list) {\r
+ var line = this.timeline,\r
+ duration = line.simpleDuration;\r
+ if (duration) {\r
+ var time = (line.activeTime > $list.beginEnd) ? $list.beginEnd\r
+ : line.activeTime;\r
+ var advance = ( time % duration ) / duration;\r
+ /*例外が発生するため、進捗率が1を超えないように処理*/\r
+ advance = (advance > 1) ? 1 : advance;\r
+ /*活動継続時間と単純継続時間が一致すると、余りは0となるため以下の処理*/\r
+ advance = advance || 1;\r
+ } else {\r
+ advance = 0;\r
+ }\r
+ return advance;\r
+ },\r
+ \r
+ /*_setEndFrameメソッドは、終了処理と凍結作業をする*/\r
_setEndFrame: function($list) {\r
- var frame = $list.currentFrame;\r
/*上書きされたメソッドを呼び出してアニメーションの凍結作業をする*/\r
if (this.fill === "freeze") {\r
- var line = this.timeline,\r
- duration = line.simpleDuration;\r
- if (duration) {\r
- var advance = ( line.activeTime % duration ) / duration;\r
- /*例外が発生するため、進捗率が1を超えないように処理*/\r
- advance = (advance > 1) ? 1 : advance;\r
- /*活動継続時間と単純継続時間が一致すると、余りは0となるため以下の処理*/\r
- advance = advance || 1;\r
- } else {\r
- advance = 0;\r
- }\r
- this.setAttribute(this.tocall(advance));\r
+ this.setAttribute(this.tocall( this.getAdvanceEnd($list) ));\r
line = duration = advance = void 0;\r
} else {\r
this.removeAttribute();\r
/*後の_setFrameメソッドで使うダミー*/\r
__setAttribute: function(){},\r
\r
- _setFrame: function(currentFrame) {\r
+ _setFrame: function($list) {\r
+ var currentFrame = $list.currentFrame;\r
/*__transformListの中で、自分より後の項目に再生中のものがあれば、\r
*アニメーションを再生させないで、後に続く項目に任せる*/\r
var list = this.element.__transformList,\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(currentFrame) {\r
+ _setEndFrame: function($list) {\r
var list = this.element.__transformList;\r
- if ((this.fill !== "remove") || !list) {\r
+ if (!list) {\r
return;\r
}\r
- if (!this.isSum) {\r
- /*凍結処理をしないで、かつ、元の状態に戻して、効果が出ないようにする*/\r
- list[this.numberOfList]\r
- && (list[this.numberOfList].isPlaying = false);\r
- for (var i = 0;i<list.length;++i) {\r
- var listi = list[i];\r
- if (listi.isPlaying || !listi.isRemove) {\r
- /*他のanimateTransform要素が活性化しているか、凍結処理が必要ならば、\r
- * 属性の初期化はしない*/\r
- return;\r
- }\r
- }\r
- this.removeAttribute();\r
+ var item = list[this.numberOfList];\r
+ if (this.fill === "remove") {\r
+ if (!item) {\r
+ return;\r
+ } else if (!this.isSum) {\r
+ /*凍結処理をしないで、かつ、元の状態に戻して、効果が出ないようにする*/\r
+ item.isPlaying = false;\r
+ } else {\r
+ /*凍結処理をしないで、かつ、効果を出すが、変形させないようにする*/\r
+ item.value = "translate(0)";\r
+ }\r
} else {\r
- /*凍結処理をしないで、かつ、効果を出すが、変形させないようにする*/\r
- list[this.numberOfList]\r
- && (list[this.numberOfList].value = "translate(0)");\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
- /*$animateElement.tocallメソッドを置き換えるためのメソッド\r
+ /*this.$animateElement.tocallメソッドを置き換えるためのメソッド\r
* mpath要素が指定されたときか、path属性のときにのみ使われる*/\r
_tocallForPath: function(advance) {\r
var path = this.path,\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
+base("$getDocument").mix ( function() {\r
\r
-function getDocument() \r
-{\r
- var svg = document.getElementsByTagName("object"),\r
- svgns = "http://www.w3.org/2000/svg";\r
- if (svg) {\r
- for (var i=0;i<svg.length;++i) {\r
- getElement( svg[i].getSVGDocument() );\r
+ function getDocument() \r
+ {\r
+ var svg = document.getElementsByTagName("object"),\r
+ svgns = "http://www.w3.org/2000/svg";\r
+ if (svg) {\r
+ for (var i=0;i<svg.length;++i) {\r
+ getElement( svg[i].getSVGDocument() );\r
+ }\r
}\r
+ /*SVG文書から呼び出されたときも処理する*/\r
+ getElement(document);\r
+ /*idはアニメの中止ハンドル*/\r
+ var id = __step(),\r
+ idstop = function() {\r
+ /*アニメーションを中止する関数*/\r
+ window.cancelAnimationFrame && cancelAnimationFrame(id);\r
+ };\r
+ base("$frame").on("pauseAnimation", idstop);\r
+ window.addEventListener("unload", idstop);\r
+ \r
+ /*文書からアニメーション関連要素を取り出して、オブジェクトを初期化*/\r
+ function getElement (svgDoc) {\r
+ var $set = base("$calcMode").$attribute.$setElement,\r
+ $animate = $set.$animateElement,\r
+ frame = base("$frame");\r
+ init($set, "set");\r
+ init($animate, "animate");\r
+ init($animate.up(), "animateColor");\r
+ init($animate.$animateTransformElement, "animateTransform");\r
+ init($animate.$animateTransformElement.$motionElement, "animateMotion");\r
+ /*リンクのハッシュ読み取りで、ハイパーリンクのイベント処理\r
+ * たとえば、a要素のxlink:href="#hoge"で、<animate id="hoge"のとき、\r
+ * animate要素がハイパーリンク作動と同時に動くようになる\r
+ * \r
+ * ただし、SMIL アニメーションの仕様では、\r
+ * animate要素の開始時刻まで、時を進める操作をするだけ*/\r
+ svgDoc.defaultView.addEventListener("hashchange", function() {\r
+ var hash = svgDoc.defaultView.location.hash.slice(1);\r
+ svgDoc.getElementById(hash).beginElement();\r
+ });\r
+ function init (obj, name) {\r
+ /*あとでframe.initializeメソッドで呼び出すために準備しておく*/\r
+ var elist = svgDoc.getElementsByTagNameNS(svgns, name);\r
+ obj.numberOfElemList = 0;\r
+ if (elist.length > 0) {\r
+ obj.elementList = elist;\r
+ frame.objList.push(obj);\r
+ }\r
+ elist = obj = void 0;\r
+ };\r
+ };\r
}\r
- /*SVG文書から呼び出されたときも処理する*/\r
- getElement(document);\r
- /*idはアニメの中止ハンドル*/\r
- var id = __step(),\r
- idstop = function() {\r
- /*アニメーションを中止する関数*/\r
- window.cancelAnimationRequest && cancelAnimationRequest(id);\r
- };\r
- base("$frame").on("pauseAnimation", idstop);\r
- window.addEventListener("unload", idstop);\r
\r
- /*文書からアニメーション関連要素を取り出して、オブジェクトを初期化*/\r
- function getElement (svgDoc) {\r
- var $set = base("$calcMode").$attribute.$setElement,\r
- $animate = $set.$animateElement;\r
- init($set, "set");\r
- init($animate, "animate");\r
- init($animate, "animateColor");\r
- init($animate.$animateTransformElement, "animateTransform");\r
- init($animate.$animateTransformElement.$motionElement, "animateMotion");\r
- /*リンクのハッシュ読み取りで、ハイパーリンクのイベント処理\r
- * たとえば、a要素のxlink:href="#hoge"で、<animate id="hoge"のとき、\r
- * animate要素がハイパーリンク作動と同時に動くようになる\r
- * \r
- * ただし、SMIL アニメーションの仕様では、\r
- * animate要素の開始時刻まで、時を進める操作をするだけ*/\r
- svgDoc.defaultView.addEventListener("hashchange", function() {\r
- var hash = svgDoc.defaultView.location.hash.slice(1);\r
- svgDoc.getElementById(hash).beginElement();\r
- });\r
-\r
- function init (obj, name) {\r
- var eles = svgDoc.getElementsByTagNameNS(svgns, name)\r
- for (var i=0;i<eles.length;++i) {\r
- obj.up().init(eles.item(i));\r
- }\r
- eles = obj = void 0;\r
- };\r
- };\r
-}\r
+ window.addEventListener && window.addEventListener("load", getDocument);\r
\r
-window.addEventListener && window.addEventListener("load", getDocument);\r
-\r
-function __step() {\r
-/*EdgeはhasFeatureメソッドでtrueを返す*/\r
-if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Animation", "1.1")\r
- || window.navigator.userAgent.toLowerCase().indexOf("edge")) {\r
- if (window.requestAnimationFrame && requestAnimationFrame) {\r
- /*IE11などSMILアニメーションに対応していないブラウザ用*/\r
- /*cancelはアニメーションの中止ハンドル*/\r
- var cancel = {\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
- frame++;\r
- try {\r
- $f.setFrame(frame);\r
- } catch(e) {\r
- }\r
+ this.step = __step;\r
+ function __step() {\r
+ /*EdgeはhasFeatureメソッドでtrueを返す*/\r
+ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Animation", "1.1")\r
+ || (window.navigator.userAgent.toLowerCase().indexOf("edge") > 0)) {\r
+ if (window.requestAnimationFrame && requestAnimationFrame) {\r
+ /*IE11やEdgeなどSMILアニメーションに対応していないブラウザ用*/\r
+ /*cancelはアニメーションの中止ハンドル*/\r
+ var cancel = {\r
+ handle: null\r
+ };\r
+ (function(frame) {\r
+ var _cancel = cancel; /*cancelのエイリアス*/\r
+ var step = function () {\r
+ if (!this.isPaused) {\r
+ frame++;\r
+ try {\r
+ this.initialize();\r
+ this.setFrame(frame);\r
+ } catch(e) {\r
+ }\r
+ _cancel.handle = requestAnimationFrame(step);\r
+ }\r
+ }.bind(base("$frame"));\r
_cancel.handle = requestAnimationFrame(step);\r
- }\r
- };\r
- })(-1);\r
- return cancel;\r
- } else {\r
- setInterval( (function(frame) {\r
- var $f = base("$frame").$svgEvent;\r
- return function () {\r
- frame++;\r
- $f.setFrame(frame);\r
- };\r
- })(-1), 1 );\r
+ })(-1);\r
+ return cancel;\r
+ } else {\r
+ setInterval( (function(frame) {\r
+ var $f = base("$frame");\r
+ return function () {\r
+ frame++;\r
+ $f.initialize();\r
+ $f.setFrame(frame);\r
+ };\r
+ })(-1), 1 );\r
+ }\r
+ }\r
}\r
-}\r
-}\r
+} );\r
//#endif // _SMIL_IDL_\r