2013-01-06 48 views
6

Với phần tử Đường dẫn SVG, làm thế nào tôi có thể chuyển đổi tất cả các lệnh đường dẫn thành các tọa độ tương đối? Ví dụ, chuyển đổi con đường này (bao gồm tất cả các lệnh, tuyệt đối và tương đối, xen kẽ):Chuyển đổi đường dẫn SVG thành các lệnh tương đối

<path d="M3,7 L13,7 m-10,10 l10,0 V27 H23 v10 h10 
     C33,43 38,47 43,47 c0,5 5,10 10,10 
     S63,67 63,67  s-10,10 10,10 
     Q50,50 73,57  q20,-5 0,-10 
     T70,40    t0,-15 
     A5,5 45 1 0 40,20 a5,5 20 0 1 -10,-10 
     Z" /> 

vào con đường tương đương này:

<path d="m3,7 l10,0 m-10 10 l10,0 v10 h10 v10 h10 
     c0,6 5,10 10,10 c0,5 5,10 10,10 
     s10,10 10,10  s-10,10 10,10 
     q-23,-27 0,-20  q20,-5 0,-10 
     t-3,-7    t0-15 
     a5,5 45 1 0 -30,-5 a5,5 20 0 1 -10,-10 
     z"/> 

Câu hỏi này đã được thúc đẩy bởi this question.

Trả lời

6

Snap.SVG có Snap.path.toRelative().

var rel = Snap.path.toRelative(abspathstring); 

Fiddle

+0

Đáng chú ý: ít nhất là Snap.SVG phiên bản được liên kết tại đây (http://cdn.jsdelivr.net/snap.svg/0.3.0/snap.svg.js) sẽ không giữ lại độ chính xác tọa độ từ đầu vào của bạn, nhưng làm tròn đến 3 số thập phân cho tất cả các tọa độ. – ecmanaut

7

tôi chỉnh Phrogz' convertToAbsolute vào convertToRelative chức năng này:

function convertToRelative(path) { 
    function set(type) { 
    var args = [].slice.call(arguments, 1) 
     , rcmd = 'createSVGPathSeg'+ type +'Rel' 
     , rseg = path[rcmd].apply(path, args); 
    segs.replaceItem(rseg, i); 
    } 
    var dx, dy, x0, y0, x1, y1, x2, y2, segs = path.pathSegList; 
    for (var x = 0, y = 0, i = 0, len = segs.numberOfItems; i < len; i++) { 
    var seg = segs.getItem(i) 
     , c = seg.pathSegTypeAsLetter; 
    if (/[MLHVCSQTAZz]/.test(c)) { 
     if ('x1' in seg) x1 = seg.x1 - x; 
     if ('x2' in seg) x2 = seg.x2 - x; 
     if ('y1' in seg) y1 = seg.y1 - y; 
     if ('y2' in seg) y2 = seg.y2 - y; 
     if ('x' in seg) dx = -x + (x = seg.x); 
     if ('y' in seg) dy = -y + (y = seg.y); 
     switch (c) { 
     case 'M': set('Moveto',dx,dy);     break; 
     case 'L': set('Lineto',dx,dy);     break; 
     case 'H': set('LinetoHorizontal',dx);   break; 
     case 'V': set('LinetoVertical',dy);    break; 
     case 'C': set('CurvetoCubic',dx,dy,x1,y1,x2,y2); break; 
     case 'S': set('CurvetoCubicSmooth',dx,dy,x2,y2); break; 
     case 'Q': set('CurvetoQuadratic',dx,dy,x1,y1); break; 
     case 'T': set('CurvetoQuadraticSmooth',dx,dy); break; 
     case 'A': set('Arc',dx,dy,seg.r1,seg.r2,seg.angle, 
         seg.largeArcFlag,seg.sweepFlag); break; 
     case 'Z': case 'z': x = x0; y = y0; break; 
     } 
    } 
    else { 
     if ('x' in seg) x += seg.x; 
     if ('y' in seg) y += seg.y; 
    } 
    // store the start of a subpath 
    if (c == 'M' || c == 'm') { 
     x0 = x; 
     y0 = y; 
    } 
    } 
    path.setAttribute('d', path.getAttribute('d').replace(/Z/g, 'z')); 
} 

Được sử dụng như vậy với đường dẫn từ các câu hỏi:

var path = document.querySelector('path'); 
convertToRelative(path); 
console.log(path.getAttribute('d')); 
// m 3 7 l 10 0 m -10 10 l 10 0 v 10 h 10 v 10 h 10 c 0 6 5 10 10 10 c 0 5 5 10 10 10 s 10 10 10 10 s -10 10 10 10 q -23 -27 0 -20 q 20 -5 0 -10 t -3 -7 t 0 -15 a 5 5 45 1 0 -30 -5 a 5 5 20 0 1 -10 -10 z 

Tôi cũng làm một phantomjs chút shell tiện ích svg2rel mà biến đổi tất cả các đường dẫn trong một svg theo cách này (có một tương ứng svg2abs trong cùng một ý chính, để đo lường tốt).

+0

'pathSegList' bây giờ bị phản đối: https://stackoverflow.com/questions/34352624/alternative-for-deprecated-svg-pathseglist –

+0

Như câu trả lời này không còn là chính xác sau khi đã nói ở trên Ngừng sử dụng API trong Chrome (và các trình duyệt khác), tôi đang chuyển sang chế độ Snap snap - hoặc một giải pháp tương tự ở anh chị cả của nó Rafael: http://jsbin.com/voxemav/ – ecmanaut

Các vấn đề liên quan