}\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
};\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
+ $frame.setFrame(frame);\r
} catch(e) {\r
}\r
_cancel.handle = requestAnimationFrame(step);\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
f(23, "#106.0C", "fi"); \r
} );\r
} );\r
- describe("$frame.$svgEvent object", function() {\r
- var frame = base("$frame").$svgEvent,\r
- p, ele;\r
- base("$frame").pauseAnimation();\r
- beforeEach( function() {\r
- base("$frame").pauseAnimation();\r
- frame = frame.up().mix( {isResolved: true} );\r
- frame.first = null;\r
- /*firstプロパティとtimelinesプロパティは$frameオブジェクトのフレーム進行に\r
- * 影響を受けるため、新たに初期化しておく*/\r
- base("$frame").timelines = frame.timelines = [];\r
- frame.lastTimeLine = null;\r
- p = document.createElementNS("http://www.w3.org/2000/svg", "g");\r
- ele = document.createElementNS("http://www.w3.org/2000/svg", "animate");\r
- p.appendChild(ele);\r
- } );\r
- /*境界条件を調べておく (limit value analysis)*/\r
- it("should be this for the value (limit value analysis)", function() {\r
- base("$frame").pauseAnimation();\r
- frame.lastTimeLine = null;\r
- expect(frame.lastTimeLine).toBeNull();\r
- expect(frame.first).toBeNull();\r
- frame.setTimeTable();\r
- expect(frame.first).toBeNull();\r
- frame.addLine( base("$frame").$begin.up().mix({\r
- isResolved: true,\r
- timelines: [],\r
- begin: 0,\r
- activeTime: 0,\r
- target: ele\r
- }) );\r
- frame.setTimeTable();\r
- expect(frame.first).toEqual(\r
- { frame: 0,\r
- eventType: "begin",\r
- target: ele,\r
- \r
- next: { frame: 0,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- }\r
- }\r
- );\r
- } );\r
- /*同値分割をして、有効同値クラスを調べておく (Equivalence partitioning, the following is the valid partion)*/\r
- it("should be this for the value (the valid partion )", function() {\r
- base("$frame").pauseAnimation();\r
- frame.addLine( base("$frame").$begin.up().mix({\r
- isResolved: true,\r
- timelines: [],\r
- begin: 0,\r
- activeTime: 0,\r
- target: ele\r
- }) );\r
- frame.setTimeTable();\r
- frame.setTimeTable();\r
- expect(frame.first).toEqual(\r
- { frame: 0,\r
- eventType: "begin",\r
- target: ele,\r
- \r
- next: { frame: 0,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- }\r
- }\r
- );\r
- frame.setTimeTable();\r
- frame.setTimeTable();\r
- expect(frame.first).toEqual(\r
- { frame: 0,\r
- eventType: "begin",\r
- target: ele,\r
- \r
- next: { frame: 0,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- }\r
- }\r
- );\r
- \r
- var isFiredBeginEvent = false;\r
- ele.addEventListener("beginEvent", function(evt) {\r
- isFiredBeginEvent = true;\r
- expect(evt.target).toBe(ele);\r
- } );\r
- ele.addEventListener("endEvent", function(evt) {\r
- expect(evt.target).toBe(ele);\r
- expect(isFiredBeginEvent).toBeTruthy();\r
- } );\r
- frame.setFrame(0);\r
- expect(frame.first).toBeNull();\r
- frame.setFrame(0);\r
- expect(frame.first).toBeNull();\r
- \r
- frame.timelines = [];\r
- frame.addLine( base("$frame").$begin.up().mix({\r
- isResolved: true,\r
- timelines: [],\r
- begin: 0,\r
- activeTime: 10,\r
- target: ele\r
- }) );\r
- frame.setTimeTable();\r
- var a = { frame: 0,\r
- eventType: "begin",\r
- target: ele,\r
- \r
- next: { frame: 10,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- }\r
- };\r
- expect(frame.first).toEqual(a);\r
- \r
- frame.addLine( base("$frame").$begin.up().mix({\r
- isResolved: true,\r
- timelines: [],\r
- begin: 1,\r
- simpleDuration: 9,\r
- activeTime: 11,\r
- target: ele\r
- }) );\r
- frame.setTimeTable();\r
- a.next.next = { frame: 1,\r
- eventType: "begin",\r
- target: ele,\r
- \r
- next: {\r
- frame: 10,\r
- eventType: "repeat",\r
- count: 1,\r
- target: ele,\r
- \r
- next: { frame: 12,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- }\r
- }\r
- };\r
- expect(frame.first).toEqual(a);\r
- frame.setFrame(11);\r
- expect(frame.first).toEqual( {frame: 12,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- } );\r
- \r
- frame.timelines = [];\r
- frame.first = null;\r
- frame.addLine( base("$frame").$begin.up().mix({\r
- isResolved: true,\r
- timelines: [],\r
- begin: 1,\r
- simpleDuration: 4,\r
- activeTime: 10,\r
- target: ele\r
- }) );\r
- frame.setTimeTable();\r
- a = { frame: 1,\r
- eventType: "begin",\r
- target: ele,\r
- \r
- next: {\r
- frame: 5,\r
- eventType: "repeat",\r
- count: 1,\r
- target: ele,\r
- \r
- next: {\r
- frame: 9,\r
- eventType: "repeat",\r
- count: 2,\r
- target: ele,\r
- \r
- next: { frame: 11,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- }\r
- }\r
- }\r
- };\r
- expect(frame.first).toEqual(a);\r
- frame.setFrame(0);\r
- expect(frame.first).toEqual(a);\r
- frame.setFrame(1);\r
- a = a.next;\r
- expect(frame.first).toEqual(a);\r
- frame.setFrame(5);\r
- expect(frame.first).toEqual(a.next);\r
-\r
- ele.addEventListener("repeatEvent", function(evt) {\r
- expect(evt.target).toBe(ele);\r
- } );\r
- frame.timelines = [];\r
- frame.first = null;\r
- frame.addLine( base("$frame").$begin.up().mix({\r
- isResolved: true,\r
- timelines: [],\r
- begin: 1,\r
- simpleDuration: 4,\r
- activeTime: 15,\r
- target: ele\r
- }) );\r
- frame.setFrame(9);\r
- expect(frame.first).toEqual({\r
- frame: 13,\r
- eventType: "repeat",\r
- count: 3,\r
- target: ele,\r
- \r
- next: { frame: 16,\r
- eventType: "end",\r
- target: ele,\r
- next: null\r
- }\r
- } );\r
- } );\r
- afterEach( function() {\r
- base("$frame").startAnimation();\r
- } );\r
- } );\r
describe("A $animateTransformElement object", function() {\r
describe("An init method", function() {\r
var $animate, ele, frame, p;\r