svnno****@sourc*****
svnno****@sourc*****
2010年 9月 16日 (木) 23:17:29 JST
Revision: 2003 http://sourceforge.jp/projects/sie/svn/view?view=rev&revision=2003 Author: dhrname Date: 2010-09-16 23:17:29 +0900 (Thu, 16 Sep 2010) Log Message: ----------- getTotalLengthとgetPointAtLengthとgetPathSegAtLengthメソッドの実装 set要素のイベントの修正 Modified Paths: -------------- branches/06x/061/org/w3c/dom/svg.js Modified: branches/06x/061/org/w3c/dom/svg.js =================================================================== --- branches/06x/061/org/w3c/dom/svg.js 2010-09-15 14:21:42 UTC (rev 2002) +++ branches/06x/061/org/w3c/dom/svg.js 2010-09-16 14:17:29 UTC (rev 2003) @@ -2500,10 +2500,9 @@ dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2)); dd += Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2)); s += dd / 2; - } else if (seg.pathSegType === SVGPathSeg.MOVETO_ABS) { - ms = seg; } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) { - s += Math.sqrt(Math.pow((seg.x-ms.x), 2) + Math.pow((seg.y-ms.y), 2)); + var ps = nl.getItem(i-1), ms = nl.getItem(0); + s += Math.sqrt(Math.pow((ps.x-ms.x), 2) + Math.pow((ps.y-ms.y), 2)); } } @@ -2511,14 +2510,52 @@ return s; }; /*SVGPoint*/ SVGPathElement.prototype.getPointAtLength = function(/*float*/ distance ) { - var seg = this.getPathSegAtLength(distance); + var segn = this.getPathSegAtLength(distance), x = 0, y = 0, nl = this.normalizedPathSegList, seg = nl.getItem(segn); + var s = this.ownerDocument.documentElement.createSVGPoint(); + if ((segn-1) <= 0) { + s.x = seg.x; + s.y = seg.y; + return s; + } + var ps = nl.getItem(segn-1); if (seg.pathSegType === SVGPathSeg.PATHSEG_LINETO_ABS) { + var segl = Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2)); + var t = (segl + this._dis) / segl; + s.x = ps.x + t * (seg.x-ps.x); + s.y = ps.y + t * (seg.y-ps.y); } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS) { + var dd = 0; + dd += Math.sqrt(Math.pow((seg.x1-ps.x), 2) + Math.pow((seg.y1-ps.y), 2)); + dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2)); + dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2)); + dd += Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2)); + var segl = dd / 2; + var t = (segl + this._dis) / segl; + /*以下はベジェ曲線の公式について、パラメータtによってまとめて整理したものを、 + *使って、ポイントの座標を演算する + */ + s.x = (3*seg.x1 + seg.x - 3*seg.x2 - ps.x) * Math.pow(t, 3) + +3*(ps.x - 2*seg.x1 + seg.x2) * Math.pow(t, 2) + +3*(seg.x1 - ps.x) * t + +ps.x; + s.y = (3*seg.y1 + seg.y - 3*seg.y2 - ps.y) * Math.pow(t, 3) + +3*(ps.y - 2*seg.y1 + seg.y2) * Math.pow(t, 2) + +3*(seg.y1 - ps.y) * t + +ps.y; + } else if (seg.pathSegType === SVGPathSeg.MOVETO_ABS) { + s.x = seg.x; + s.y = seg.y; + } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) { + var ms = nl.getItem(0), segl = Math.sqrt(Math.pow((seg.x-mx.x), 2) + Math.pow((seg.y-ms.y), 2)); + var t = (segl + this._dis) / segl; + s.x = ms.x + t * (seg.x-ms.x); + s.y = ms.y + t * (seg.y-ms.y); } + return s; }; /*unsigned long*/ SVGPathElement.prototype.getPathSegAtLength = function(/*float*/ distance ) { - var nl = this.normalizedPathSegList; - for (var i=1,nln=nl.numberOfItems,ms=null;i<nln;++i) { + var nl = this.normalizedPathSegList; //仕様ではpathSegList + for (var i=0,nln=nl.numberOfItems,ms=null;i<nln;++i) { var seg = nl.getItem(i); if (seg.pathSegType === SVGPathSeg.PATHSEG_LINETO_ABS) { var ps = nl.getItem(i-1); @@ -2530,15 +2567,23 @@ dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2)); dd += Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2)); distance -= dd / 2; - } else if (seg.pathSegType === SVGPathSeg.MOVETO_ABS) { - ms = seg; + dd = null; } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) { - distance -= Math.sqrt(Math.pow((seg.x-ms.x), 2) + Math.pow((seg.y-ms.y), 2)); + var ps = nl.getItem(i-1), ms = nl.getItem(0); + distance -= Math.sqrt(Math.pow((ps.x-ms.x), 2) + Math.pow((ps.y-ms.y), 2)); } if (distance <= 0) { - return seg; + /*_disプロパティは前述のgetPointAtLengthメソッドで使う*/ + this._dis = distance; + distance = null; + return i; } } + /*もし、distanceがパスの距離よりも長い場合、 + *最後のセグメントの番号を返す + *なお、これはSVG1.1の仕様の想定外のこと + */ + return (nl.numberOfItems - 1); }; /*SVGPathSegClosePath*/ SVGPathElement.prototype.createSVGPathSegClosePath = function() { var _SVGPathSegClosePath = SVGPathSegClosePath; @@ -4240,7 +4285,7 @@ } else { tar = this.targetElement; } - if (!offset) { + if (!offset && offset !== 0) { offset = NAIBU.Time.Max; } f(this, offset, tar, t);