OSDN Git Service

Lighten the unload event
[sie/sie.git] / org / w3c / dom / smil.js
index 1bd0077..4185ec8 100644 (file)
@@ -34,8 +34,9 @@ base("$frame").mix ( {
   timelines: [],\r
 \r
   /*開始フレーム数の候補。アニメーションの開始条件となる\r
-   * 単位はフレーム数であって、秒数ではない*/\r
-  begin: 0,\r
+   * 単位はフレーム数であって、秒数ではない\r
+   * なお、初期値については、開始フレームが負の値を考慮しているため*/\r
+  begin: -Number.MAX_VALUE,\r
 \r
   /*活動継続時間 (Active Duration)のフレーム数。アニメーションの継続条件となる\r
    * 単位はフレーム数であって、秒数ではない*/\r
@@ -61,9 +62,6 @@ base("$frame").mix ( {
   /*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
@@ -139,12 +137,12 @@ base("$frame").mix ( {
     },\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
@@ -195,12 +193,17 @@ base("$frame").mix ( {
        * 現在フレーム数 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
@@ -1475,8 +1478,9 @@ base("$calcMode").up("$attribute").mix( {
   },\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
@@ -1490,14 +1494,14 @@ base("$calcMode").up("$attribute").mix( {
     } 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
@@ -1859,7 +1863,7 @@ base("$calcMode").up("$attribute").mix( {
      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
@@ -1867,20 +1871,26 @@ base("$calcMode").up("$attribute").mix( {
      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
@@ -1909,15 +1919,16 @@ base("$calcMode").up("$attribute").mix( {
      /*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
@@ -2030,124 +2041,6 @@ base("$calcMode").up("$attribute").mix( {
     }\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
@@ -2163,7 +2056,7 @@ function getDocument()
   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
@@ -2211,25 +2104,23 @@ if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Anim
        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