2012-07-19 62 views
11

Có ai đã thử sử dụng thư viện svg to canvas khi tạo trực quan d3.js không? Tôi đã cố gắng sử dụng canvg.js và d3.js để chuyển đổi svg để vải từ bên trong một webview 2.3 ứng dụng android, nhưng khi tôi gọi:SVG vào Canvas với d3.js

svg.selectAll(".axis") 
     .data(d3.range(angle.domain()[1])) 
    .enter().append("g") 
     .attr("class", "axis") 
     .attr("transform", function(d) { return "rotate(" + angle(d) * 180/Math.PI + ")"; }) 
    .call(d3.svg.axis() 
     .scale(radius.copy().range([-5, -outerRadius])) 
     .ticks(5) 
     .orient("left")) 
    .append("text") 
     .attr("y", 
     function (d) { 
      if (window.innerWidth < 455){ 
      console.log("innerWidth less than 455: ",window.innerWidth); 
      return -(window.innerHeight * .33); 
      } 
      else{ 
      console.log("innerWidth greater than 455: ",window.innerWidth); 
      return -(window.innerHeight * .33); 
      } 
     }) 
     .attr("dy", ".71em") 
     .attr("text-anchor", "middle") 
     .text(function(d, i) { return capitalMeta[i]; }) 
     .attr("style","font-size:12px;"); 

tôi nhận được lỗi: Loại lỗi chưa gặp: Không thể gọi phương thức ' setProperty 'of null http://mbostock.github.com/d3/d3.js?2.5.0:1707

Ứng dụng trình duyệt không đầu nào hoặc trình phân tích cú pháp phía máy chủ có hoạt động không? Có ai gặp phải điều này trước đây không?

+0

Đây là một câu hỏi lớn như vậy, tôi muốn ai đó sẽ trả lời nó. – Apollo

Trả lời

0

Bạn đã thử cùng một mã trên trình duyệt hỗ trợ SVG để xem đó có phải là sự cố với chế độ xem web không? Sau đó, hãy thử this example bằng cách sử dụng canvg hoặc this one bằng cách sử dụng tuần tự hóa DOM. Để hiển thị phía máy chủ, bạn có thể bắt đầu bằng this example để biết cách hiển thị nó ở phía máy chủ canvas bằng cách sử dụng Node.js.

1

Tôi chưa thử thư viện, nhưng đã hiển thị SVG d3 sản xuất cho canvas sau this đăng trên MDN.

Mã này là một mish-mash nhanh chóng của MDN và một số jQuery, bạn sẽ cần phải dọn dẹp và không có lỗi hoặc kiểm tra, nhưng nó hoạt động và tôi hy vọng nó sẽ giúp .

$(document.body).append(
    '<canvas id="canvas" width="'+diameter+'" height="'+diameter+'"></canvas>' 
); 

// https://developer.mozilla.org/en/docs/HTML/Canvas/Drawing_DOM_objects_into_a_canvas 
var el = $($('svg')[0]); 
var svgMarkup = '<svg xmlns="http://www.w3.org/2000/svg"' 
+ ' class="' + el.attr('class') +'"' 
+ ' width="' + el.attr('width') +'"' 
+ ' height="' + el.attr('height') +'"' 
+ '>' 
+ $('svg')[0].innerHTML.toString()+'</svg>'; 
var canvas = document.getElementById("canvas"); 
var ctx = canvas.getContext("2d"); 
var DOMURL = this.URL || this.webkitURL || this; 
var img = new Image(); 
var svg = new Blob([svgMarkup], {type: "image/svg+xml;charset=utf-8"}); 
var url = DOMURL.createObjectURL(svg); 
img.onload = function() { 
    ctx.drawImage(img, 0, 0); 
    alert('ok'); 
    DOMURL.revokeObjectURL(url); 
}; 
img.src = url; 
11

Dưới đây là một cách để bạn có thể viết svg của bạn để canvas (và sau đó lưu kết quả như một png hay bất cứ điều gì):

// Create an export button 
d3.select("body") 
    .append("button") 
    .html("Export") 
    .on("click",svgToCanvas); 

var w = 100, // or whatever your svg width is 
    h = 100; 

// Create the export function - this will just export 
// the first svg element it finds 
function svgToCanvas(){ 
    // Select the first svg element 
    var svg = d3.select("svg")[0][0], 
     img = new Image(), 
     serializer = new XMLSerializer(), 
     svgStr = serializer.serializeToString(svg); 

    img.src = 'data:image/svg+xml;base64,'+window.btoa(svgStr); 

    // You could also use the actual string without base64 encoding it: 
    //img.src = "data:image/svg+xml;utf8," + svgStr; 

    var canvas = document.createElement("canvas"); 
    document.body.appendChild(canvas); 

    canvas.width = w; 
    canvas.height = h; 
    canvas.getContext("2d").drawImage(img,0,0,w,h); 
    // Now save as png or whatever 
}; 
+0

Câu trả lời hay! Tôi cũng đã thêm một giải pháp bên dưới (dựa trên giải pháp của bạn) để kéo các kiểu từ các tệp định kiểu CSS bên ngoài. – Constantino

+0

@ace tôi có thể có mã đầy đủ, xin vui lòng, loại thực sự cần nó – sg28

+0

@ace, có thể là một plnkr/fiddle – sg28

4

Câu trả lời bởi @ace là rất tốt, tuy nhiên nó doesn' t xử lý trường hợp các bảng định kiểu CSS bên ngoài. Ví dụ của tôi bên dưới sẽ tự động tạo kiểu cho hình ảnh được tạo chính xác như thế nào trông SVG gốc, ngay cả khi kiểu dáng kéo có dạng biểu định kiểu riêng biệt.

// when called, will open a new tab with the SVG 
// which can then be right-clicked and 'save as...' 
function saveSVG(){ 

    // get styles from all required stylesheets 
    // http://www.coffeegnome.net/converting-svg-to-png-with-canvg/ 
    var style = "\n"; 
    var requiredSheets = ['phylogram_d3.css', 'open_sans.css']; // list of required CSS 
    for (var i=0; i<document.styleSheets.length; i++) { 
     var sheet = document.styleSheets[i]; 
     if (sheet.href) { 
      var sheetName = sheet.href.split('/').pop(); 
      if (requiredSheets.indexOf(sheetName) != -1) { 
       var rules = sheet.rules; 
       if (rules) { 
        for (var j=0; j<rules.length; j++) { 
         style += (rules[j].cssText + '\n'); 
        } 
       } 
      } 
     } 
    } 

    var svg = d3.select("svg"), 
     img = new Image(), 
     serializer = new XMLSerializer(), 

    // prepend style to svg 
    svg.insert('defs',":first-child") 
    d3.select("svg defs") 
     .append('style') 
     .attr('type','text/css') 
     .html(style); 


    // generate IMG in new tab 
    var svgStr = serializer.serializeToString(svg.node()); 
    img.src = 'data:image/svg+xml;base64,'+window.btoa(unescape(encodeURIComponent(svgStr))); 
    window.open().document.write('<img src="' + img.src + '"/>'); 
}; 

Và, để được hoàn thành, các nút gọi hàm:

// save button 
d3.select('body') 
    .append("button") 
    .on("click",saveSVG) 
    .attr('class', 'btn btn-success') 
+0

Điều này là rất hữu ích, nhưng ví dụ của bạn là nhầm lẫn về requireSheets vs document.styleSheets, dẫn đến một số lỗi cho tôi. Tôi đã sửa chúng bằng cách xóa 'var requiredSheets ...' và 'if (requiredSheets.indexOf ...' (có nghĩa là tôi có thể xóa 'var sheetName ...') .Đó là, requiredSheets là không cần thiết, gây ra lỗi và có thể –

+0

@Constantino: 'height' và' width' không bao giờ được sử dụng - tại sao chúng được gán giá trị? –

+0

Rất tiếc, đó là một số mã sao chép và dán cũ ... – Constantino

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