*/
function ElementTimeControl(ele) {
this._tar = ele;
- /*_beginと_endプロパティはミリ秒数を収納する。リピート時に書き換えられることがある。
- *_beginはアニメ開始時の秒数。_endはアニメ終了時の秒数。
+ /*_startと_endプロパティはミリ秒数を収納する。
+ *_startはアニメ開始時の秒数のリスト。_finishはアニメ終了時の秒数のリスト。
*なお、文書読み込み終了時(アニメ開始時刻)の秒数を0とする。
*/
- this._begin = 0;
- this._end = null;
+ this._start = [];
+ this._finish = null;
return this;
};
ElementTimeControl.prototype = {
this.dispatchEvent(evt);
},
/*void*/ beginElementAt : function(/*float*/ offset) {
- var ntc = this.ownerDocument.documentElement.getCurrentTime();
- this._begin = offset + ntc;
+ var ntc = this.ownerDocument.documentElement.getCurrentTime(),
+ start = this._start || [];
+ for (var i=0,sli=start.length;i<sli;++i) {
+ if (start[i] === (offset+ntc)) {
+ ntc = start = offset = void 0;
+ return;
+ }
+ }
+ start.push(offset + ntc);
+ this._start = start;
},
/*void*/ endElementAt : function(/*float*/ offset) {
- var ntc = this.ownerDocument.documentElement.getCurrentTime();
- this._end = offset + ntc;
+ var ntc = this.ownerDocument.documentElement.getCurrentTime(),
+ fin = this._finish || [];
+ for (var i=0,fli=fin.length;i<fli;++i) {
+ if (fin[i] === (offset+ntc)) {
+ ntc = fin = offset = void 0;
+ return;
+ }
+ }
+ fin.push(offset + ntc);
+ this._finish = fin;
}
};
NAIBU._buff = setInterval(function(){
var n = NAIBU._buff_num,
dbuf = DOMImplementation._buffer_,
- dbufli = dbuf.length,
+ dbufli = dbuf ? dbuf.length : 0, //極端な負荷がかかると、dbufはnullになる可能性あり
s, evt;
if (dbufli === 0) {
clearInterval(NAIBU._buff);
t.prototype._list = null; //文字の位置を格納しておくリストのキャッシュ
t.prototype._length = 0; //全文字数
t.prototype._stx = t.prototype._sty = 0; //初めの文字の位置
- t.prototype._chars = 0; //tspan要素が全体の何文字目から始まっているか
+ t.prototype._chars = 0; //tspan (tref)要素が全体の何文字目から始まっているか
t.prototype._isYokogaki = true; //横書きかどうか
/*long*/ t.prototype.getNumberOfChars = function() {
return (this._length);
while (ti) {
if (ti.nodeType === /*Node.TEXT_NODE*/ 3) {
tt = ti._tars;
- /*tspan要素のx属性で指定された座標の個数よりも、文字数が多い場合は、祖先(親)のx属性を
+ /*tspan(tref)要素のx属性で指定された座標の個数よりも、文字数が多い場合は、祖先(親)のx属性を
*使う。また、属性が指定されていないときも同様に祖先や親を使う。
*もし、仮に祖先や親がx属性を指定されていなければ、現在のテキスト位置(変数xに格納している)を使う。
*この処理はdx属性やdy、y属性でも同様とする
ti = ti.parentNode;
}
ti = ti.nextSibling;
- } else if ((ti.localName === "tspan") && (ti.namespaceURI === "http://www.w3.org/2000/svg") && ti.firstChild) {
- /*現在のテキスト位置(x,y)の分だけ、tspan要素をずらしておく。
+ } else if (((ti.localName === "tspan") || (ti.localName === "tref"))
+ && (ti.namespaceURI === "http://www.w3.org/2000/svg") && ti.firstChild) {
+ /*現在のテキスト位置(x,y)の分だけ、tspan (tref)要素をずらしておく。
*さらに、現在のテキスト位置を更新する
*/
ti._stx = x;
/*readonly SVGAnimatedLengthList*/ this.y = new sl();
/*readonly SVGAnimatedLengthList*/ this.dx = new sl();
/*readonly SVGAnimatedLengthList*/ this.dy = new sl();
- _doc = sl = void 0;
+ sl = void 0;
/*readonly SVGAnimatedNumberList*/ this.rotate = new SVGAnimatedNumberList();
this.addEventListener("DOMAttrModified", function(evt){
var tar = evt.target,
evt = tar = void 0;
}
}, false);
- return this;
-};
-SVGTextPositioningElement.constructor = SVGTextContentElement;
-SVGTextPositioningElement.prototype = new SVGTextContentElement();
-
-function SVGTextElement(_doc) {
- SVGTextPositioningElement.apply(this, arguments);
- this._tar = _doc.createElement("v:group");
+ if (_doc) {
+ this._tar = _doc.createElement("v:group");
+ this._doc = _doc; //_docプロパティは_texto関数内で使われる
+ }
this.addEventListener("DOMNodeInserted", function(evt){
if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
return; //強制終了させる
tpart.appendChild(tar._tar);
}
tnext = tpart = isLast = void 0;
- tar.addEventListener("DOMNodeInsertedIntoDocument", function(evt) {
- var tar = evt.target,
- ti = tar.firstChild,
- ttp = tar._tar,
- style = tar.ownerDocument.defaultView.getComputedStyle(tar, null),
- n = parseFloat(style.getPropertyValue("font-size")) * Math.sqrt(Math.abs(tar.getScreenCTM()._determinant())),
- tod = tar.ownerDocument.documentElement,
- ttpc = ttp, //ttpcはttpのキャッシュ
- tlen = tar.getComputedTextLength(),
- anchor = style.getPropertyValue("text-anchor"),
- tedeco = style.getPropertyValue("text-decoration"), //text-decorationは継承しないので、個々に設定する
- ttps = ttp.style,
- ae = [];
- ttps.fontSize = n + "px";
- ttps.fontFamily = style.getPropertyValue("font-family");
- ttps.fontStyle = style.getPropertyValue("font-style");
- ttps.fontWeight = style.getPropertyValue("font-weight");
- /*ここでの変数jは前回ノードまでの総文字数*/
- for (var i=0, j=0, tli=tar.getNumberOfChars();i<tli;++i) {
- if (ti) {
- if (!!ti._tars && (ti._tars.length !== 0)) {
- var ij = (i > j) ? i - j : j - i
- var sty = ti._tars[ij].style,
- p = tar.getStartPositionOfChar(i);
- sty.position = "absolute";
- if (tar._isYokogaki) {
- if (anchor === "middle") {
- p.x -= tlen / 2;
- } else if (anchor === "end") {
- p.x -= tlen;
- }
- } else {
- if (anchor === "middle") {
- p.y -= tlen / 2;
- } else if (anchor === "end") {
- p.y -= tlen;
- }
- }
- sty.left = p.x + "px";
- sty.top = p.y + "px";
- sty.width = "0px";
- sty.height = "0px";
- sty.marginTop = tar._isYokogaki ? -n-5+ "px" : "-5px";
- sty.lineHeight = n+10+ "px";
- sty.textDecoration = tedeco;
- sty.display = "none"
- ttp.appendChild(ti._tars[ij]);
- sty = p = void 0;
+ tar.addEventListener("DOMNodeInsertedIntoDocument", tar._texto, false);
+ evt = tar = void 0;
+ },false);
+ return this;
+};
+SVGTextPositioningElement.constructor = SVGTextContentElement;
+SVGTextPositioningElement.prototype = new SVGTextContentElement();
+SVGTextPositioningElement.prototype._texto = function(evt) {
+ var tar = evt.target,
+ ti = tar.firstChild,
+ ttp = tar._tar,
+ style = tar.ownerDocument.defaultView.getComputedStyle(tar, null),
+ n = parseFloat(style.getPropertyValue("font-size")) * Math.sqrt(Math.abs(tar.getScreenCTM()._determinant())),
+ tod = tar.ownerDocument.documentElement,
+ ttpc = ttp, //ttpcはttpのキャッシュ
+ tlen = tar.getComputedTextLength(),
+ anchor = style.getPropertyValue("text-anchor"),
+ tedeco = style.getPropertyValue("text-decoration"), //text-decorationは継承しないので、個々に設定する
+ ttps = ttp.style,
+ ae = [];
+ ttps.fontSize = n + "px";
+ ttps.fontFamily = style.getPropertyValue("font-family");
+ ttps.fontStyle = style.getPropertyValue("font-style");
+ ttps.fontWeight = style.getPropertyValue("font-weight");
+ /*ここでの変数jは前回ノードまでの総文字数*/
+ for (var i=0, j=0, tli=tar.getNumberOfChars();i<tli;++i) {
+ if (ti) {
+ if (!!ti._tars && (ti._tars.length !== 0)) {
+ var ij = (i > j) ? i - j : j - i
+ var sty = ti._tars[ij].style,
+ p = tar.getStartPositionOfChar(i);
+ sty.position = "absolute";
+ if (tar._isYokogaki) {
+ if (anchor === "middle") {
+ p.x -= tlen / 2;
+ } else if (anchor === "end") {
+ p.x -= tlen;
}
- if (ti.nodeName === "#text") {
- if ((ti.data.length+j) <= i+1) { //テキストノード内の文字をすべて処理し終えれば
- j = j + ti.data.length;
- if (ti.parentNode.localName === "a") {
- ti = ti.parentNode;
- ttp = ttpc;
- }
- ti = ti.nextSibling;
- }
- } else if (!!ti.getNumberOfChars) {
- if ((ti.getNumberOfChars()+j) <= i+1) {
- j = j + ti.getNumberOfChars();
- ti = ti.nextSibling;
- }
- } else if ((ti.localName === "a") && (ti.namespaceURI === "http://www.w3.org/2000/svg") && ti.firstChild) {
- ttp = ti._tar;
- ti = ti.firstChild;
- ae[ae.length] = ti;
- i-=2;
+ } else {
+ if (anchor === "middle") {
+ p.y -= tlen / 2;
+ } else if (anchor === "end") {
+ p.y -= tlen;
}
}
- }
- var color = style.getPropertyValue("fill"),
- cursor = style.getPropertyCSSValue("cursor"),
- vis = style.getPropertyCSSValue("visibility"),
- disp = style.getPropertyCSSValue("display"),
- tts = tar._tar.style,
- tft = tar.firstChild._tars, //空白のテキストノードの場合、tftがundefinedになる恐れがある
- ttt = tft[0] ? tft[0].innerText.charAt(0) : [""], //あらかじめ初期化しておく
- tfti;
- if (color === "none"){
- tts.color = "transparent";
- } else if (color.indexOf("url") === -1) {
- tts.color = color;
- } else {
- tts.color = "black";
- }
- if (cursor && !cursor._isDefault) { //初期値でないならば
- var tc = cursor.cssText;
- tts.cursor = tc.split(":")[1];
- tc = void 0;
- }
- if ((tar.x.baseVal.numberOfItems === 1) && (tar.y.baseVal.numberOfItems === 1)
- && tar._isYokogaki && (tar.firstChild.nodeName === "#text")) {
- /*xとy属性が一つの値しか取らないとき、字詰めの処理をすべてブラウザに任せておく。
- *以下では、他のdiv要素のテキストをすべて、最初のdiv要素にまとめている
- */
- for (var i=1, tli=tft.length;i<tli;++i) {
- tfti = tft[i];
- ttt += tfti.innerText;
- tfti.parentNode.removeChild(tfti);
- }
- //以下でinnerTextやinnerHTMLを使うのは、IE6でエラーとなる可能性がある
- if (tft[0] && tft[0].replaceChild) {
- tft[0].replaceChild(_doc.createTextNode(ttt), tft[0].firstChild);
- }
- ttt = void 0;
- }
- var isRect = true,
- di = "block";
- if (ttp.lastChild) {
- if (ttp.lastChild.nodeName !== "rect") {
- isRect = false;
- }
- } else {
- isRect = false;
- }
- if (!isRect) {
- var backr = _doc.createElement("v:rect"),
- backrs = backr.style; //ずれを修正するためのもの
- backrs.width = backrs.height = "1px";
- backrs.left = backrs.top = "0px";
- backr.stroked = backr.filled = "false";
- ttp.appendChild(backr);
- }
- if (vis && !vis._isDefault) {
- tts.visibility = vis.cssText.split(":")[1];
- }
- /*dipslayプロパティだけはdiv要素の個々に設定しておく必要がある
- *なぜかといえば、div要素をdisplay:none;であらかじめ設定しているため。
- */
- if (disp && !disp._isDefault && (disp.cssText.indexOf("none") > -1)) {
- di = "none";
- } else if (disp && !disp._isDefault) {
- di = "block";
- }
- var jt = tar._tar.firstChild,
- j = 0;
- while (jt) {
- jt.style.display = di;
- jt = jt.nextSibling;
- }
- while (ae[j]) { //要素内部にあるa要素の処理
- for (var l=0, tli=ae[j]._tars.length;l<tli;++l) {
- ae[j]._tars[l].style.display = di;
+ sty.left = p.x + "px";
+ sty.top = p.y + "px";
+ sty.width = "0px";
+ sty.height = "0px";
+ sty.marginTop = tar._isYokogaki ? -n-5+ "px" : "-5px";
+ sty.lineHeight = n+10+ "px";
+ sty.textDecoration = tedeco;
+ sty.display = "none"
+ ttp.appendChild(ti._tars[ij]);
+ sty = p = void 0;
+ }
+ if (ti.nodeName === "#text") {
+ if ((ti.data.length+j) <= i+1) { //テキストノード内の文字をすべて処理し終えれば
+ j = j + ti.data.length;
+ if (ti.parentNode.localName === "a") {
+ ti = ti.parentNode;
+ ttp = ttpc;
+ }
+ ti = ti.nextSibling;
}
- l = void 0;
- ++j;
+ } else if (!!ti.getNumberOfChars) {
+ if ((ti.getNumberOfChars()+j) <= i+1) {
+ j = j + ti.getNumberOfChars();
+ ti = ti.nextSibling;
+ }
+ } else if ((ti.localName === "a") && (ti.namespaceURI === "http://www.w3.org/2000/svg") && ti.firstChild) {
+ ttp = ti._tar;
+ ti = ti.firstChild;
+ ae[ae.length] = ti;
+ i-=2;
}
- delete tar._cacheMatrix;
- ae = isRect = evt = tar = style = tedeco = tpp = ttpc = style = color = cursor = disp = vis = ttps = backr = backrs = di = tft = jt = void 0;
- }, false);
- evt = tar = void 0;
- },false);
+ }
+ }
+ var color = style.getPropertyValue("fill"),
+ cursor = style.getPropertyCSSValue("cursor"),
+ vis = style.getPropertyCSSValue("visibility"),
+ disp = style.getPropertyCSSValue("display"),
+ tts = tar._tar.style,
+ tft = tar.firstChild._tars, //空白のテキストノードの場合、tftがundefinedになる恐れがある
+ ttt = tft[0] ? tft[0].innerText.charAt(0) : [""], //あらかじめ初期化しておく
+ tfti;
+ if (color === "none"){
+ tts.color = "transparent";
+ } else if (color.indexOf("url") === -1) {
+ tts.color = color;
+ } else {
+ tts.color = "black";
+ }
+ if (cursor && !cursor._isDefault) { //初期値でないならば
+ var tc = cursor.cssText;
+ tts.cursor = tc.split(":")[1];
+ tc = void 0;
+ }
+ if ((tar.x.baseVal.numberOfItems === 1) && (tar.y.baseVal.numberOfItems === 1)
+ && tar._isYokogaki && (tar.firstChild.nodeName === "#text")) {
+ /*xとy属性が一つの値しか取らないとき、字詰めの処理をすべてブラウザに任せておく。
+ *以下では、他のdiv要素のテキストをすべて、最初のdiv要素にまとめている
+ */
+ for (var i=1, tli=tft.length;i<tli;++i) {
+ tfti = tft[i];
+ ttt += tfti.innerText;
+ tfti.parentNode.removeChild(tfti);
+ }
+ //以下でinnerTextやinnerHTMLを使うのは、IE6でエラーとなる可能性がある
+ if (tft[0] && tft[0].replaceChild) {
+ tft[0].replaceChild(tar._doc.createTextNode(ttt), tft[0].firstChild);
+ }
+ ttt = void 0;
+ }
+ var isRect = true,
+ di = "block";
+ if (ttp.lastChild) {
+ if (ttp.lastChild.nodeName !== "rect") {
+ isRect = false;
+ }
+ } else {
+ isRect = false;
+ }
+ if (!isRect) {
+ var backr = tar._doc.createElement("v:rect"),
+ backrs = backr.style; //ずれを修正するためのもの
+ backrs.width = backrs.height = "1px";
+ backrs.left = backrs.top = "0px";
+ backr.stroked = backr.filled = "false";
+ ttp.appendChild(backr);
+ }
+ if (vis && !vis._isDefault) {
+ tts.visibility = vis.cssText.split(":")[1];
+ }
+ /*dipslayプロパティだけはdiv要素の個々に設定しておく必要がある
+ *なぜかといえば、div要素をdisplay:none;であらかじめ設定しているため。
+ */
+ if (disp && !disp._isDefault && (disp.cssText.indexOf("none") > -1)) {
+ di = "none";
+ } else if (disp && !disp._isDefault) {
+ di = "block";
+ }
+ var jt = tar._tar.firstChild,
+ j = 0;
+ while (jt) {
+ jt.style.display = di;
+ jt = jt.nextSibling;
+ }
+ while (ae[j]) { //要素内部にあるa要素の処理
+ for (var l=0, tli=ae[j]._tars.length;l<tli;++l) {
+ ae[j]._tars[l].style.display = di;
+ }
+ l = void 0;
+ ++j;
+ }
+ delete tar._cacheMatrix;
+ ae = isRect = evt = tar = style = tedeco = tpp = ttpc = style = color = cursor = disp = vis = ttps = backr = backrs = di = tft = jt = void 0;
+};
+
+function SVGTextElement(_doc) {
+ SVGTextPositioningElement.apply(this, arguments);
return this;
};
SVGTextElement.constructor = SVGTextPositioningElement;
function SVGTRefElement(_doc) {
SVGTextPositioningElement.apply(this, arguments);
+ this.addEventListener("DOMNodeInserted", function(evt){
+ if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
+ return; //強制終了させる
+ }
+ evt.target.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:show", "embed");
+ }, false);
+ this.addEventListener("S_Load", function(evt){
+ var tar = evt.target,
+ tic = tar._instance.firstChild;
+ /*textノードのデータだけを処理*/
+ while (tic && (tic.nodeName !== "#text")) {
+ tic = tic.nextSibling;
+ }
+ tic && tar.parentNode.insertBefore(tar.ownerDocument.importNode(tic, false), tar);
+ evt.target = tar.parentNode;
+ tar.parentNode._texto(evt);
+ tar = tic = evtt = void 0;
+ }, false);
SVGURIReference.apply(this, arguments);
return this;
};
this.style.setProperty = function(){};
this._tar = null;
/*readonly SVGElement*/ this.targetElement;
- this._beginValue = "0ms";
- this._endValue = null;
+ /*それぞれのプロパティは、_を除いた属性に対応している*/
+ this._begin = this._end = this._repeatCount = this._repeatDur = null;
+ this._dur = "indefinite";
this._currentFrame = 0;
- this._currentCount = 0;
- /*_maxCountはrepeatCount属性で指定された数値
- *_maxDurはrepeatDur属性で指定された数値
- */
- this._maxCount = 0;
- this._maxDur = 0;
+ /*_isRepeatと_numRepeatは繰り返し再生のときに使う。なお、後者は現在のリピート回数*/
this._isRepeat = false;
- /*_simpleDurationプロパティは
- *dur属性の数値を収納しておく。属性がなければnullのまま
- */
- this._simpleDuration = null;
- /*_beginと_endプロパティはミリ秒数を収納する。リピート時に書き換えられることがある。
- *_beginはアニメ開始時の秒数。_endはアニメ終了時の秒数。
+ this._numRepeat = 0;
+ /*_startと_finishプロパティはミリ秒数のリストを収納する。
+ *_startはアニメ開始時の秒数リスト。_finishはアニメ終了時の秒数のリスト。
*なお、文書読み込み終了時(アニメ開始時刻)の秒数を0とする。
+ *_startingプロパティは現在アニメーションでの開始時刻。getSartTimeメソッドで使う
*/
- this._begin = null;
- this._end = null;
+ this._start = this._finish = this._starting = null;
+ /*_activeDurプロパティは現時点でのアニメーションの活動期間*/
+ this._activeDur = 0;
this._from = this._to = this._values = this._by = null;
this._keyTimes = null;
this.addEventListener("beginEvent", function(evt) {
- var tar = evt.target;
- if (!tar.isRepeat) {
- tar.endElementAt(tar.getSimpleDuration());
- } else {
- tar.beginElementAt(tar.getSimpleDuration());
- if (tar.getCurrentTime() !== 0) {
- var ttd = tar.ownerDocument, evt = ttd.createEvent("TimeEvents");
- tar._currentCount++;
- evt.initTimeEvent("repeatEvent", ttd.defaultView, tar._currentCount);
- tar.dispatchEvent(evt);
+ try {
+ var tar = evt.target,
+ begin = tar.getStartTime(),
+ dur = tar.getSimpleDuration(),
+ durv = tar._dur,
+ end = tar._finish,
+ endv= tar._end,
+ td = tar._repeatDur,
+ tc = tar._repeatCount,
+ ac = 0;
+ if (end) {
+ end.sort(function(a, b) {
+ return a - b;
+ });
+ for (var i=0, eli=end.length;i<eli;++i) {
+ /*endの配列をソートした後で、beginに最も近い数値を選ぶ*/
+ if (eli[i] >= begin) {
+ end = end[i];
+ }
+ break;
+ }
}
+ /*Activate Duration (活性持続時間と呼ぶことにする)を計算
+ *計算方法は以下を参照のこと
+ *http://www.w3.org/TR/smil-animation/#ComputingActiveDur
+ *3.3.4. Computing the active duration
+ */
+ if ((td === "indefinte") || (tc === "indefinte")) {
+ if (endv) {
+ ac = end - begin;
+ } else {
+ /*活性持続時間が不定(indefinte)なので、強制的にアニメを終了させる*/
+ ac = null;
+ }
+ } else if (durv === "indefinte") {
+ if (!tc && !endv) {
+ /*活性持続時間が不定(indefinte)なので、強制的にアニメを終了させる*/
+ ac = null;
+ } else if (tc && !endv) {
+ ac = tar._getOffset(td);
+ } else if (!tc && endv) {
+ ac = end - begin;
+ } else {
+ ac = (tar._getOffset(td) > (end - begin)) ? tar._getOffset(td) : (end - begin);
+ }
+ } else if (durv && !td && !tc && !endv) {
+ ac = dur;
+ } else if (durv && !td && tc && !endv) {
+ ac = dur * (+tc);
+ } else if (durv && td && !tc && !endv) {
+ ac = tar._getOffset(td);
+ } else if (durv && !td && !tc && endv) {
+ ac = (dur > (end - begin)) ? dur : (end - begin);
+ } else if (durv && td && tc && !endv) {
+ ac = (+tc*dur > tar._getOffset(td)) ? +tc*dur : tar._getOffset(td);
+ } else if (durv && td && tc && endv) {
+ ac = (+tc*dur > Math.min(+td, (end-begin))) ? +tc*dur : Math.min(tar._getOffset(td), (end - begin));
+ } else if (durv && td && !tc && endv) {
+ ac = (tar._getOffset(td) > (end - begin)) ? tar._getOffset(td) : (end - begin);
+ } else if (durv && !td && tc && endv) {
+ ac = (+tc*dur > (end - begin)) ? +tc*dur : (end - begin)
+ }
+ } catch (e) {
+ tar.endElementAt(1);
+ throw new DOMException(DOMException.INVALID_STATE_ERR);
}
+ if (isFinite(ac)) {
+ tar.endElementAt(ac);
+ tar._activeDur = ac;
+ }
+ tar = begin = dur = durv = end = endv= td = tc = ac = void 0;
}, false);
this.addEventListener("DOMAttrModified", function(evt){
if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
return;
}
- var tar = evt.target, name = evt.attrName;
+ var tar = evt.target,
+ name = evt.attrName,
+ evtv = evt.newValue;
if (name === "begin") {
- tar._beginValue = evt.newValue;
+ tar._begin = evtv.replace(/\s+/g, "").split(";"); //空白は取り除く
} else if (name === "end") {
- tar._endValue = evt.newValue;
+ tar._end = evtv.replace(/\s+/g, "").split(";");
} else if (name === "dur") {
- tar._simpleDuration = tar._getOffset(evt.newValue);
+ tar._dur = evtv;
} else if (name === "repeatCount") {
- tar._maxCount = parseFloat(evt.newValue);
+ tar._repeatCount = evtv;
tar._isRepeat = true;
} else if (name === "repeatDur") {
- tar._maxDur = parseFloat(evt.newValue);
+ tar._repeatCount = evtv;
tar._isRepeat = true;
} else if (name === "from") {
- tar._from = evt.newValue;
+ tar._from = evtv;
} else if (name === "to") {
- tar._to = evt.newValue;
+ tar._to = evtv;
} else if (name === "values") {
- tar._values = evt.newValue.split(";");
+ tar._values = evtv.split(";");
} else if (name === "by") {
- tar._by = evt.newValue;
+ tar._by = evtv;
} else if (name === "keyTimes") {
- var s = evt.newValue.split(";");
+ var s = evtv.split(";");
tar._keyTimes = []; //_keyTimesプロパティを初期化
for (var i=0;i<s.length;++i) {
tar._keyTimes[i] = parseFloat(s[i]);
}
s = void 0;
}
- evt = void 0;
+ evt = evtv = void 0;
}, false);
this.addEventListener("DOMNodeInserted", function(evt){
if (evt.eventPhase === /*Event.BUBBLING_PHASE*/ 3) {
*/
return this;
}
+ /*begin属性とend属性を処理する*/
+ var that = tar,
+ timing = function(val, name, offset) {
+ /*timing関数は時間のタイミングをidとeventと、clock-value(offset)に分割して処理していく
+ *まず、idを検出するためのsearcIdローカル関数を作る
+ */
+ var searchId = function () {
+ var n = val.indexOf(".");
+ if ((n > 0) && (/[a-z]/i).test(val.charAt(n+1))) { //. (dot)の後がアルファベットならば
+ return (val.slice(0, n));
+ }
+ n = nn = void 0;
+ return "";
+ },
+ id;
+ /*
+ *W3CのSMIl AnimationのTimingモデルは7パターンがあるので、場合分けする
+ */
+ if (isFinite(parseFloat(val))) { //1) offset-valueの場合
+ that[name](offset);
+ } else if (val.indexOf("repeat(") > -1) { //2) repeat-valueの場合
+ var inte = parseFloat(val.slice(7)),
+ ds = (function(that, name, offset) {
+ return function (evt) {
+ if (inte === evt.target._numRepeat) {
+ that[name](offset);
+ }
+ };
+ })(that, name, offset),
+ id = searchId();
+ if (id) {
+ that.ownerDocument.getElementById(id).addEventListener("repeatEvent", ds);
+ } else {
+ that.addEventListener("repeatEvent", ds);
+ }
+ } else if (/\.(begin|end)/.test(val)) { //3) syncbase-valueの場合
+ id = searchId();
+ if (id) {
+ var ds = (function(that, name, offset) {
+ return function (evt) {
+ that[name](offset);
+ };
+ })(that, name, offset),
+ ev = "";
+ /\.(begin|end)/.test(val); //RegExp.$1のために、もう一度する必要がある
+ if (RegExp.$1 === "begin") {
+ ev = "beginEvent";
+ } else if (RegExp.$1 === "end") {
+ ev = "endEvent";
+ }
+ that.ownerDocument.getElementById(id).addEventListener(ev, ds);
+ }
+ } else if (val.indexOf("wallclock(") === 0) { //4) wallclock-valueの場合
+
+ } else if (val === "indefinte") { //5) indefinteの場合
+ } else if (val.indexOf("accesskey(") > -1) { //6) accesskey-valueの場合
+
+ } else { //7) event-valueの場合
+ id = searchId();
+ var ds = (function(that, name, offset) {
+ return function (evt) {
+ that[name](offset);
+ };
+ })(that, name, offset);
+ if (id && val.match(/\.([a-z]+)/i)) {
+ that.ownerDocument.getElementById(id).addEventListener(RegExp.$1, ds);
+ } else if (val){
+ that.targetElement.addEventListener(val.match(/^[a-z]+/i)[0], ds)
+ }
+ }
+ val = searchId = id = void 0;
+ };
+ if (tar._begin) {
+ for (var i=0,tli=tar._begin.length;i<tli;++i) {
+ timing(tar._begin[i], "beginElementAt", tar._getOffset(tar._begin[i]));
+ }
+ } else {
+ tar.beginElementAt(0);
+ }
+ if (tar._end) {
+ for (var i=0,tli=tar._end.length;i<tli;++i) {
+ timing(tar._end[i], "endElementAt", tar._getOffset(tar._end[i]));
+ }
+ }
+ that = void 0;
if (tar.hasAttributeNS("http://www.w3.org/1999/xlink", "xlink:href")) {
tar.targetElement = tar.ownerDocument.getElementById(tar.getAttributeNS("http://www.w3.org/1999/xlink", "xlink:href").substring(1))
} else {
tar.targetElement = tar.parentNode;
}
- tar._eventSync(tar._beginValue,
- (function(te, offse, ta, t) {
- ta.addEventListener( t.match(te._eventRegExp)[0],
- function(){
- if (offse !== 0) {
- te.beginElementAt(offse);
- } else {
- te._begin = NAIBU.Time.currentFrame;
- te.beginElement();
- te._currentFrame++;
- }
- }, false);
- }), "beginElementAt");
- if (tar._endValue) {
- tar._eventSync(tar._endValue,
- (function(te, offse, ta, t) {
- ta.addEventListener( t.match(te._eventRegExp)[0],
- function(){
- te.endElementAt(offse);
- }, false );
- }), "endElementAt");
- }
evt = tar = void 0;
}, false);
evt = tar = void 0;
}, false);
- this.addEventListener("repeatEvent", function(evt) {
- var tar = evt.target;
- if ((tar._currentCount >= tar._maxCount) || (tar.getCurrentTime() >= (tar._maxDur+tar.getStartTime()))) {
- tar._isRepeat = false;
- }
- }, false);
return this;
};
SVGAnimationElement.constructor = SVGElement;
*別モジュールであるsmil::ElementTimeControl(smil.js)を参照のこと
*/
/*void*/ SVGAnimationElement.prototype.beginElement = function() {
- var ttd = this.ownerDocument, evt = ttd.createEvent("TimeEvents");
+ var ttd = this.ownerDocument,
+ evt = ttd.createEvent("TimeEvents");
+ this._starting = ttd.documentElement.getCurrentTime(); //getStartTimeメソッドで使う開始時刻
+ if (this.getCurrentTime() > 0) {
+ /*アニメーションの最中で、beginEventが起きるときは、endEventが前もって起こされる。SVG1.1の仕様を参照
+ *
+ * 19.4.2 Interface TimeEvent
+ * Note that if an element is restarted while it is currently playing, the element will raise an end event and another begin event, as the element restarts.
+ *
+ * http://www.w3.org/TR/SVG/animate.html#InterfaceTimeEvent
+ *
+ */
+ this.endElement();
+ this._currentFrame = 0;
+ }
evt.initTimeEvent("beginEvent", ttd.defaultView, 0);
this.dispatchEvent(evt);
+ /*新しくリストの頭を更新して、別の値も実行させるようにする*/
+ this._start.shift();
};
/*void*/ SVGAnimationElement.prototype.endElement = function() {
- var ttd = this.ownerDocument, evt = ttd.createEvent("TimeEvents");
+ var ttd = this.ownerDocument,
+ evt = ttd.createEvent("TimeEvents");
evt.initTimeEvent("endEvent", ttd.defaultView, 0);
this.dispatchEvent(evt);
+ this._finish.shift();
};
/*void*/ SVGAnimationElement.prototype.beginElementAt = function(/*float*/ offset) {
- var ntc = this.ownerDocument.documentElement.getCurrentTime();
- this._begin = offset + ntc;
+ var ntc = this.ownerDocument.documentElement.getCurrentTime(),
+ start = this._start || [];
+ for (var i=0,sli=start.length;i<sli;++i) {
+ if (start[i] === (offset+ntc)) {
+ ntc = start = offset = void 0;
+ return;
+ }
+ }
+ start.push(offset + ntc);
+ start.sort(function(a, b) {
+ return a - b;
+ });
+ this._start = start;
};
/*void*/ SVGAnimationElement.prototype.endElementAt = function(/*float*/ offset) {
- var ntc = this.ownerDocument.documentElement.getCurrentTime();
- this._end = offset + ntc;
+ var ntc = this.ownerDocument.documentElement.getCurrentTime(),
+ fin = this._finish || [];
+ for (var i=0,fli=fin.length;i<fli;++i) {
+ if (fin[i] === (offset+ntc)) {
+ ntc = fin = offset = void 0;
+ return;
+ }
+ }
+ fin.push(offset + ntc);
+ fin.sort(function(a, b) {
+ return a - b;
+ });
+ this._finish = fin;
};
SVGAnimationElement.prototype._eventRegExp = /(mouse|activ|clic|begi|en)[a-z]+/;
-SVGAnimationElement.prototype._timeRegExp = /[\-\d\.]+(h|min|s|ms)?/;
+SVGAnimationElement.prototype._timeRegExp = /[\-\d\.]+(h|min|s|ms)?$/;
SVGAnimationElement.prototype._unit = {
"h" : 2880000,
"min" : 48000,
** Note that when the simple duration is "indefinite", some simple use cases can yield surprising results. See the related example #4 in Appendix B.
*/
SVGAnimationElement.prototype._getOffset = function(/*string*/ t) {
- var n = parseFloat(t.match(this._timeRegExp));
- if (!isNaN(n) && RegExp.$1) {
+ var n = parseFloat((t.match(this._timeRegExp) || "0")),
+ offset = 0;
+ if (isFinite(n) && RegExp.$1) {
var offset = n * this._unit[RegExp.$1]
- } else if (!isNaN(n)) {
- var offset = n;
- } else {
- var offset = 0;
+ } else if (isFinite(n)) {
+ offset = n;
}
n = t = void 0;
return offset;
};
-/*_eventSyncメソッド
- *イベントがある場合とない場合とで、別々の処理に分けるメソッド
- */
-SVGAnimationElement.prototype._eventSync = function(/*string*/ t, /*function*/ f, /*string*/ methodName) {
- var offset = this._getOffset(t);
- this._begin = NAIBU.Time.Max;
- if ( /(mouse|activ|click|begin|end)/.test(t) ) { //イベントがある場合
- var tar;
- if ( /([^;]+)\.\D/.test(t) ) {
- tar = this.ownerDocument.getElementById(RegExp.$1);
- } else {
- tar = this.targetElement;
- }
- if (!offset && offset !== 0) {
- offset = NAIBU.Time.Max;
- }
- f(this, offset, tar, t);
- } else if (!offset && (t !== "undefined") && (offset !== 0)) {
- this._begin = 0;
- } else {
- this[methodName](offset);
- }
-};
+
/*float*/ SVGAnimationElement.prototype.getStartTime = function(){
- if (!!this._begin || (this._begin === 0)) {
- return (this._begin);
+ if (this._starting || (this._starting === 0)) {
+ return (this._starting);
} else {
throw new DOMException(DOMException.INVALID_STATE_ERR);
}
return (this._currentFrame * 125 * 0.8);
};
/*float*/ SVGAnimationElement.prototype.getSimpleDuration = function(){
- if (!!!this._simpleDuration && !!!this._end && (this._simpleDuration !== 0)) {
+ if (!this._dur && !this._finish && (this._dur === "indefinte")) {
throw new DOMException(DOMException.NOT_SUPPORTED_ERR);
- } else if (!!this._simpleDuration && !!this._end) {
- var s = (this._simpleDuration > this._end - this._begin) ? this._end - this._begin : this._simpleDuration;
} else {
- var s = !!this._end ? this._end - this._begin : this._simpleDuration;
+ return (this._getOffset(this._dur));
}
- return s;
};
//raises( DOMException );
NAIBU.Time = {
}
NAIBU.stop = setInterval( (function() {
/* try{*/
- var ntc = NAIBU.Time.currentFrame++;
- var nc = NAIBU.Clip;
- var s = ntc * 100; //フレーム数ntcをミリ秒数sに変換
+ var ntc = NAIBU.Time.currentFrame,
+ nc = NAIBU.Clip,
+ s = ntc * 100; //フレーム数ntcをミリ秒数sに変換 (100 = 125 * 0.8)
if (ntc > NAIBU.Time.Max) {
clearInterval(NAIBU.stop);
}
+ nc[0] && nc[0].ownerDocument.documentElement.setCurrentTime(s);
for (var i=0,ncli=nc.length;i<ncli;++i) {
- var nci = nc[i];
- nci.ownerDocument.documentElement.setCurrentTime(s);
- if ("_begin" in nci) {
- if (nci.getStartTime() <= s) {
- if (nci.getCurrentTime() === 0) {
+ var nci = nc[i]
+ s2 = s + 100,
+ s1 = s - 100;
+ if (nci._start) {
+ var sti = nci._start[0];
+ if ((sti || (sti === 0)) && s1 <= sti && sti < s) {
nci.beginElement();
}
- nci._currentFrame++;
+ sti = void 0;
}
- if (nci._end && (nci._end <= s) && (nci.getCurrentTime() !== 0)) {
- nci.endElement();
- nci._frame && nci._frame();
- nci._currentFrame = 0;
- delete nci._begin;
- nci._end = null;
- } else if (!!nci._frame) {
- nci._frame();
+ if (nci._isRepeat && (nci.getCurrentTime() !== 0) && ((nci.getSimpleDuration() % s) === 0)) {
+ var ttd = nci.ownerDocument,
+ evt = ttd.createEvent("TimeEvents");
+ ++nci._numRepeat;
+ evt.initTimeEvent("repeatEvent", ttd.defaultView, nci._numRepeat);
+ nci.dispatchEvent(evt);
+ ttd = evt = void 0;
+ }
+ if (nci._finish && (nci.getCurrentTime() !== 0)) {
+
+ var fti = nci._finish[0];
+ if ((fti || (fti === 0)) && s < fti && fti <= s2) {
+ nci.endElement();
+ nci._currentFrame = 0;
+ }
+ fti = void 0;
}
+ if (nci._frame) {
+ nci._currentFrame++;
+ nci._frame();
}
- nci = void 0;
}
+ ++NAIBU.Time.currentFrame;
+ nci = s1 = s2 = void 0;
/* } catch (e) {
stlog.add(e, 4157);
}*/
}, false);
}, false);
this.addEventListener("beginEvent", function(evt) {
- var tar = evt.target;
- var attrName = tar.getAttributeNS(null, "attributeName"), newAttr = tar.targetElement.attributes.getNamedItemNS(null, attrName);
- var ttr = tar.targetElement, tta = ttr[attrName];
- tar._frame = function() {
- var d = tar.getSimpleDuration() * 0.8, n = tar._valueList.length-1, tg = tar.getCurrentTime();
+ var _tar = evt.target,
+ attrName = _tar.getAttributeNS(null, "attributeName"),
+ newAttr = _tar.targetElement.attributes.getNamedItemNS(null, attrName),
+ ttr = _tar.targetElement,
+ tta = ttr[attrName];
+ _tar._frame = function() {
+ var tar = _tar,
+ d = tar._isRepeat ? tar.getSimpleDuration() : tar._activeDur,
+ n = tar._valueList.length-1,
+ tg = tar.getCurrentTime();
+ tar._activeDur || (d = 0);
+ d *= 0.8;
if ((n !== -1) && (d !== 0) && (tg <= d)) {
if (tar._isDiscrete) {
++n; //discreteモードは他のモードに比べて、分割数が多いことに注意
ttr.animatedNormalizedPathSegList = ttr.normalizedPathSegList;
ttr.normalizedPathSegList = base;
}
- evt = v1 = v2 = v = d = n = ii = tg = void 0;
+ evt = tar = v1 = v2 = v = d = n = ii = tg = void 0;
};
evt = vir = void 0;
}, false);
this.addEventListener("endEvent", function(evt) {
- var tar = evt.target, fill = tar.getAttributeNS(null, "fill");
+ var tar = evt.target,
+ fill = tar.getAttributeNS(null, "fill");
if (!fill || (fill === "remove")) {
var evt = tar.ownerDocument.createEvent("MutationEvents");
evt.initMutationEvent("DOMNodeInsertedIntoDocument", false, false, null, null, null, null, null);
tar.targetElement.dispatchEvent(evt);
evt = void 0;
+ tar._frame && tar._frame();
}
+ delete tar._frame;
}, false);
this.addEventListener("repeatEvent", function(evt) {
var tar = evt.target;
tta.baseVal = base;
}
}
+ ++tar._currentFrame; //これがないと、NAIBU.stopの内部の処理の都合上、endEventが発動しない。
evt = tar = attrName = void 0;
}, false);
this.addEventListener("endEvent", function(evt) {
tar._frame = function() {
var _tar = tar,
tpn = _tar._path,
- tgsd = _tar.getSimpleDuration(),
+ tgsd = _tar._isRepeat ? _tar.getSimpleDuration() : _tar._activeDur,
d = tgsd * 0.8,
tg = _tar.getCurrentTime(),
ii;
+ _tar._activeDur || (d = 0);
if (tgsd === 0) {
tgsd = void 0;
return;
var evtt = tar.ownerDocument.createEvent("MutationEvents");
evtt.initMutationEvent("DOMNodeInsertedIntoDocument", false, false, null, null, null, null, null);
tar.targetElement.dispatchEvent(evtt);
+ tar._frame && tar._frame();
}
- tar._frame = evt = evtt = void 0;
+ delete tar._frame;
+ evt = evtt = trans = fill = tar = void 0;
}, false);
this.addEventListener("repeatEvent", function(evt) {
var tar = evt.target;
* 3.4.2 Specifying the simple animation function f(t)
*http://www.w3.org/TR/2005/REC-SMIL2-20050107/animation.html#animationNS-SpecifyingAnimationFunction
*/
- var d = _tar.getSimpleDuration() * 0.8,
+ var d = _tar._isRepeat ? _tar.getSimpleDuration() : _tar._activeDur,
n = _tar._valueList.length - 1,
tg = _tar.getCurrentTime(),
ii, di, ti;
+ _tar._activeDur || (d = 0);
+ d *= 0.8;
if ((n !== -1) && (d !== 0) && (tg <= d)) {
ii = Math.floor((tg*n) / d);
if (ii === n) { //iiが境い目のときは、n-2を適用
tar._frame();
}, false);
this.addEventListener("endEvent", function(evt) {
- var tar = evt.target;
+ var tar = evt.target,
+ fill = tar.getAttributeNS(null, "fill");
if (!fill || (fill === "remove")) {
var evtt = tar.ownerDocument.createEvent("MutationEvents");
evtt.initMutationEvent("DOMNodeInsertedIntoDocument", false, false, null, null, null, null, null);
tar.targetElement.dispatchEvent(evtt);
+ tar._frame && tar._frame();
}
- tar._frame = evt = evtt = void 0;
+ delete tar._frame;
+ evt = evtt = tar = fill = void 0;
}, false);
this.addEventListener("repeatEvent", function(evt) {
var tar = evt.target;
trans.animVal.appendItem(tar.ownerDocument.documentElement.createSVGTransform());
}, false);
this.addEventListener("endEvent", function(evt) {
- var tar = evt.target;
+ var tar = evt.target,
+ fill = tar.getAttributeNS(null, "fill");
+ if (!fill || (fill === "remove")) {
+ var evtt = tar.ownerDocument.createEvent("MutationEvents");
+ evtt.initMutationEvent("DOMNodeInsertedIntoDocument", false, false, null, null, null, null, null);
+ tar.targetElement.dispatchEvent(evtt);
+ tar._frame && tar._frame();
+ }
+ delete tar._frame;
+ evt = evtt = tar = fill = void 0;
}, false);
this.addEventListener("repeatEvent", function(evt) {
var tar = evt.target;