18

d3.js ビジュアライゼーションを作成するときに、svg to canvas ライブラリを使用しようとした人はいますか? canvg.js と d3.js を使用して、Android 2.3 アプリケーションの webview 内から svg をキャンバスに変換しようとしましたが、呼び出すと:

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;");

エラーが表示されます: Uncaught TypeError: Cannot call method setPropertyof null http://mbostock.github.com/d3/d3.js?2.5.0:1707

ある種のヘッドレス ブラウザ アプリケーション、またはサーバー側の js パーサーは機能しますか? 誰もこれに遭遇したことがありますか?

4

4 に答える 4

11

@ace による回答は非常に優れていますが、外部 CSS スタイルシートのケースは処理されません。以下の例では、別のスタイルシートからスタイルを取得している場合でも、元の SVG の外観とまったく同じように、生成された画像を自動的にスタイル設定します。

// 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 + '"/>');
};

そして、完成させるために、関数を呼び出すボタン:

// save button
d3.select('body')
    .append("button")
    .on("click",saveSVG)
    .attr('class', 'btn btn-success')
于 2016-06-28T20:37:37.750 に答える
1

WebView に問題があるかどうかを確認するために、SVG をサポートするブラウザーで同じコードを試しましたか? 次に、canvg を使用してこの例を試すか DOM シリアライゼーションを使用してこの例を試してください。サーバー側レンダリングの場合、Node.js を使用してキャンバス サーバー側にレンダリングする方法について、この例から始めることができます。

于 2012-09-14T05:52:01.777 に答える
1

私はライブラリを試していませんが、 MDNのこの投稿に従って、d3 で生成された SVG をキャンバスにレンダリングしました。

このコードは、MDN といくつかの jQuery を簡単に混ぜ合わせたものであり、整理する必要があります。エラー チェックやプラットフォーム チェックはありませんが、機能します。お役に立てば幸いです。

$(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;
于 2013-10-09T10:43:12.450 に答える