2012-03-13 41 views
8

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 độ tuyệt đối? Ví dụ, chuyển đổi đường dẫn này:Chuyển đổi đường dẫn SVG thành các lệnh tuyệt đối

<path d="M17,42 l100,0 v100 h-100 z"/> 

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

<path d="M17,42 L117,42 V142 H17 Z"/> 

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

Trả lời

11

Dưới đây là các mã JavaScript tôi đến với:

function convertToAbsolute(path){ 
    var 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 (/[MLHVCSQTA]/.test(c)){ 
     if ('x' in seg) x=seg.x; 
     if ('y' in seg) y=seg.y; 
    }else{ 
     if ('x1' in seg) x1=x+seg.x1; 
     if ('x2' in seg) x2=x+seg.x2; 
     if ('y1' in seg) y1=y+seg.y1; 
     if ('y2' in seg) y2=y+seg.y2; 
     if ('x' in seg) x+=seg.x; 
     if ('y' in seg) y+=seg.y; 
     switch(c){ 
     case 'm': segs.replaceItem(path.createSVGPathSegMovetoAbs(x,y),i);     break; 
     case 'l': segs.replaceItem(path.createSVGPathSegLinetoAbs(x,y),i);     break; 
     case 'h': segs.replaceItem(path.createSVGPathSegLinetoHorizontalAbs(x),i);   break; 
     case 'v': segs.replaceItem(path.createSVGPathSegLinetoVerticalAbs(y),i);    break; 
     case 'c': segs.replaceItem(path.createSVGPathSegCurvetoCubicAbs(x,y,x1,y1,x2,y2),i); break; 
     case 's': segs.replaceItem(path.createSVGPathSegCurvetoCubicSmoothAbs(x,y,x2,y2),i); break; 
     case 'q': segs.replaceItem(path.createSVGPathSegCurvetoQuadraticAbs(x,y,x1,y1),i); break; 
     case 't': segs.replaceItem(path.createSVGPathSegCurvetoQuadraticSmoothAbs(x,y),i); break; 
     case 'a': segs.replaceItem(path.createSVGPathSegArcAbs(x,y,seg.r1,seg.r2,seg.angle,seg.largeArcFlag,seg.sweepFlag),i); break; 
     case 'z': case 'Z': x=x0; y=y0; break; 
     } 
    } 
    // Record the start of a subpath 
    if (c=='M' || c=='m') x0=x, y0=y; 
    } 
} 

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

var path = document.querySelector('path'); 
convertToAbsolute(path); 
console.log(path.getAttribute('d')); 
// M 17 42 L 117 42 V 142 H 17 Z 

Sửa: Đây là một trang thử nghiệm với một con đường mà bao gồm mọi lệnh (tuyệt đối và tương đối) xen kẽ và cho thấy rằng chuyển đổi hoạt động trong các phiên bản hiện tại của IE, Chrome, FF và Safari.
http://phrogz.net/svg/convert_path_to_absolute_commands.svg

+0

seg.pathSegTypeAsLetter luôn trả về chữ cái viết hoa ngay cả khi tôi có dấu phẩy chữ cái nhỏ trong đường dẫn. Bất kỳ ý tưởng nào khác đằng sau các câu lệnh switch – rajkamal

+0

Nếu không phải là vấn đề mà bạn không nhận được tất cả các loại phân đoạn được bảo tồn thì nó cũng là một tùy chọn để sử dụng chức năng tích hợp trong svg, [pathElm.normalizedPathSegList] [1]. tuyệt đối moveto, lineto, curveto và đóng. [1]: http://www.w3.org/TR/SVG11/paths.html#__svg__SVGAnimatedPathData__normalizedPathSegList –

+0

@ ErikDahlström Tôi muốn sử dụng điều đó, nhưng 'normalizedPathSegList' không tồn tại trên WebKit (luôn trả về' chưa xác định'). – Phrogz

8

Nếu bạn có Raphaël, bạn có cả hai Raphael.pathToRelativeRaphael._pathToAbsolute.

Raphael._pathToAbsolute không có trong tài liệu (like pathToRelative) và được sử dụng ở nhiều nơi trong nguồn Raphael trong nội bộ. Nhưng nó cũng có thể được sử dụng bên ngoài, nếu bạn thêm _ trước tên hàm theo cách này: Raphael._pathToAbsolute.

chuyển đổi trực tuyến: http://jsbin.com/mudusiseta

Việc sử dụng cũng giống như tương đối một:

<script src="raphael.js"></script> 
<script> 
    // ... 

    var paper = Raphael(10, 50, 320, 200); 
    var path_string = "M10 10 L 20 20 L 100 10"; // Original coordinates 
    var path = paper.path(path_string); 

    // To relative coordinates 
    var path_string_rel = Raphael.pathToRelative(path_string); 
    console.log(path_string_rel); 

    // To absolute coordinates 
    var path_string_abs = Raphael._pathToAbsolute(path_string_rel); 
    console.log(path_string_abs); 

    // ...  
</script> 

Tôi không biết tại sao pathToAbsolute không có trong tài liệu. Nó nên.

Nếu bạn muốn tính năng này hoạt động trong Web Worker (để tăng tốc mã), bạn có thể dễ dàng lấy hàm mong muốn từ Raphael (được phép) và sử dụng nó như một phương thức miễn phí DOM. Raphael là một thư viện thao tác DOM (cũng như jQuery) và nó không thể được sử dụng trong các Worker, bởi vì DOM không được hỗ trợ trong các Worker. Nếu bạn có các đường dẫn rất phức tạp, trình duyệt có thể treo và ngăn chặn Công nhân Web này cung cấp giải pháp trong các trình duyệt hiện đại.

1

Đây là thư viện cho đường dẫn svg (d attr) thao tác: https://github.com/fontello/svgpath.

+0

Làm thế nào chúng ta có thể sử dụng thư viện này trong một trang html, không phải trong nút? – Kpym

+0

@Kpym bạn có thể gói gói trình duyệt với http://browserify.org/ chẳng hạn. – Vitaly

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