2017-11-28 16 views
2

ズーム可能な太陽のチャートを作成しています。最後にイメージを中央に配置したいと思っています。私は他のstackoverflowの質問をチェックしましたが、私はD3.jsやsvgグラフィックスであまり経験がないので、実行可能な解決策を見つけることができませんでした。
私は使用しているJSONファイルに画像プロパティを含めましたが、画像を必要とする唯一の場所はセンターです。だから私は、D3.jsによって描かれたキャンバスの中心に単に画像を置く方がいいと考えていました 誰かがこの問題を解決する方法に関する提案や考え方を持っていれば大変感謝しています。ここでD3.jsを使用したSunburstチャートの中心にイメージを配置

Here is an image of the chart

JSONファイル内の画像のプロパティである:ここで

{ 
"name": "Wine Aroma Wheel", 
"description": "The Davis Wine Aroma Wheel is divided into several sections to help you visualize the different flavors, scents and aromatic qualities found in most red and white wines, regardless of the grape variety. The same aromatic complexities and sensations pictured on the wine aroma wheel are found in red and white wines all over the world, from Bordeaux, to California and the Rhone Valley, as well as every other viticultural area.", 
"image": "images/Grape-2.jpg", 
"children": [ 
    { 
. . . 

は私のCSS3のコードです:ここで

circle, 
path { 
    cursor: pointer; 
} 

circle { 
    fill: none; 
    pointer-events: all; 
} 

#tooltip { background-color: white; 
       padding: 3px 5px; 
       border: 1px solid black; 
       text-align: center;} 

html { 
    font-family: sans-serif; 
} 

はサンバーストチャートのJavaScriptコードです:

var margin = {top: 650, right: 650, bottom: 650, left: 650}, 
    radius = Math.min(margin.top, margin.right, margin.bottom, margin.left) - 168; 

function filter_min_arc_size_text(d, i) {return (d.dx*d.depth*radius/1)>14}; 

var hue = d3.scale.category10(); 

var luminance = d3.scale.sqrt() 
    .domain([0, 1e6]) 
    .clamp(true) 
    .range([80, 20]); 

var svg = d3.select("body").append("svg") 
    .attr("width", margin.left + margin.right) 
    .attr("height", margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

var partition = d3.layout.partition() 
    .sort(function(a, b) { return d3.ascending(a.name, b.name); }) 
    .size([2 * Math.PI, radius]); 

var arc = d3.svg.arc() 
    .startAngle(function(d) { return d.x; }) 
    .endAngle(function(d) { return d.x + d.dx - .01/(d.depth + .5); }) 
    .innerRadius(function(d) { return (radius + 6)/3 * d.depth; }) 
    .outerRadius(function(d) { return (radius + 6)/3 * (d.depth + 1.) - 1; }); 

//Tooltip description 
var tooltip = d3.select("body") 
    .append("div") 
    .attr("id", "tooltip") 
    .style("position", "absolute") 
    .style("z-index", "10") 
    .style("opacity", 0); 

function format_number(x) { 
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 
} 


function format_description(d) { 
    var description = d.description; 
     return '<b>' + d.name + '</b></br>'+ d.description + '<br> (' + format_number(d.value) + ')'; 
} 

function computeTextRotation(d) { 
    var rotation = (d.x + d.dx/2) * 180/Math.PI - 90; 
    return { 
     global: rotation, 
     correction: rotation > 90 ? 180 : 0 
    }; 
} 

function isRotated(d) { 
    var rotation = (d.x + d.dx/2) * 180/Math.PI - 90; 
    return rotation > 90 ? true : false 
} 

function mouseOverArc(d) { 
      d3.select(this).attr("stroke","black") 
      tooltip.html(format_description(d)); 
      return tooltip.transition() 
      .duration(50) 
      .style("opacity", 0.9); 
     } 

function mouseOutArc(){ 
    d3.select(this).attr("stroke","") 
    return tooltip.style("opacity", 0); 
} 

function mouseMoveArc (d) { 
      return tooltip 
      .style("top", (d3.event.pageY-10)+"px") 
      .style("left", (d3.event.pageX+10)+"px"); 
} 

var root_ = null; 
d3.json("data/davis-aroma-wheel.json", function(error, root) { 
    if (error) return console.warn(error); 
    // Compute the initial layout on the entire tree to sum sizes. 
    // Also compute the full name and fill color for each node, 
    // and stash the children so they can be restored as we descend. 

    partition 
     .value(function(d) { return d.size; }) 
     .nodes(root) 
     .forEach(function(d) { 
     d._children = d.children; 
     d.sum = d.value; 
     d.key = key(d); 
     d.fill = fill(d); 
     }); 

    // Now redefine the value function to use the previously-computed sum. 
    partition 
     .children(function(d, depth) { return depth < 3 ? d._children : null; }) 
     .value(function(d) { return d.sum; }); 

    var center = svg.append("circle") 
     .attr("r", radius/3) 
     .on("click", zoomOut); 

    center.append("title") 
     .text("Zoom Out"); 


    var partitioned_data = partition.nodes(root).slice(1) 

    var path = svg.selectAll("path") 
     .data(partitioned_data) 
     .enter().append("path") 
     .attr("d", arc) 
     .style("fill", function(d) { return d.fill; }) 
     .each(function(d) { this._current = updateArc(d); }) 
     .on("click", zoomIn) 
      .on("mouseover", mouseOverArc) 
     .on("mousemove", mouseMoveArc) 
     .on("mouseout", mouseOutArc); 

    var texts = svg.selectAll("text") 
     .data(partitioned_data) 
     .enter().append("text") 
      .filter(filter_min_arc_size_text) 
     .attr("transform", function(d) 
     { 
      var r = computeTextRotation(d); 
      return "rotate(" + r.global + ")" 
      + "translate(" + radius/3. * d.depth + ")" 
      + "rotate(" + -r.correction + ")"; 
     }) 
     .style("font-weight", "bold") 
     .style("text-anchor", "middle") 
      .attr("dx", function(d) {return isRotated(d) ? "-85" : "85"}) //margin 
     .attr("dy", ".35em") // vertical-align 
     .on("click", zoomIn) 
      .text(function(d,i) {return d.name}) 

    function zoomIn(p) { 
    if (p.depth > 1) p = p.parent; 
    if (!p.children) return; 
    zoom(p, p); 
    } 

    function zoomOut(p) { 
    if (!p.parent) return; 
    zoom(p.parent, p); 
    } 

    // Zoom to the specified new root. 
    function zoom(root, p) { 
    if (document.documentElement.__transition__) return; 

    // Rescale outside angles to match the new layout. 
    var enterArc, 
     exitArc, 
     outsideAngle = d3.scale.linear().domain([0, 2 * Math.PI]); 

    function insideArc(d) { 
     return p.key > d.key 
      ? {depth: d.depth - 1, x: 0, dx: 0} : p.key < d.key 
      ? {depth: d.depth - 1, x: 2 * Math.PI, dx: 0} 
      : {depth: 0, x: 0, dx: 2 * Math.PI}; 
    } 

    function outsideArc(d) { 
     return {depth: d.depth + 1, x: outsideAngle(d.x), dx: outsideAngle(d.x + d.dx) - outsideAngle(d.x)}; 
    } 

    center.datum(root); 

    // When zooming in, arcs enter from the outside and exit to the inside. 
    // Entering outside arcs start from the old layout. 
    if (root === p) enterArc = outsideArc, exitArc = insideArc, outsideAngle.range([p.x, p.x + p.dx]); 

    var new_data=partition.nodes(root).slice(1) 

    path = path.data(new_data, function(d) { return d.key; }); 

    // When zooming out, arcs enter from the inside and exit to the outside. 
    // Exiting outside arcs transition to the new layout. 
    if (root !== p) enterArc = insideArc, exitArc = outsideArc, outsideAngle.range([p.x, p.x + p.dx]); 

    d3.transition().duration(d3.event.altKey ? 7500 : 750).each(function() { 
     path.exit().transition() 
      .style("fill-opacity", function(d) { return d.depth === 1 + (root === p) ? 1 : 0; }) 
      .attrTween("d", function(d) { return arcTween.call(this, exitArc(d)); }) 
      .remove(); 

     path.enter().append("path") 
     .style("fill-opacity", function(d) { return d.depth === 2 - (root === p) ? 1 : 0; }) 
     .style("fill", function(d) { return d.fill; }) 
     .on("click", zoomIn) 
       .on("mouseover", mouseOverArc) 
     .on("mousemove", mouseMoveArc) 
     .on("mouseout", mouseOutArc) 
     .each(function(d) { this._current = enterArc(d); }); 


     path.transition() 
      .style("fill-opacity", 1) 
      .attrTween("d", function(d) { return arcTween.call(this, updateArc(d)); }); 

    }); 


    texts = texts.data(new_data, function(d) { return d.key; }) 

    texts.exit() 
     .remove() 
    texts.enter() 
     .append("text") 

    texts.style("opacity", 0) 
     .attr("transform", function(d) { 
     var r = computeTextRotation(d); 
     return "rotate(" + r.global + ")" 
     + "translate(" + radius/3 * d.depth + ",0)" 
     + "rotate(" + -r.correction + ")"; 
     }) 
     .style("font-weight", "bold") 
     .style("text-anchor", "middle") 
      .attr("dx", function(d) {return isRotated(d) ? "-85" : "85"}) //margin 
     .attr("dy", ".35em") // vertical-align 
     .filter(filter_min_arc_size_text) 
     .on("click", zoomIn) 
     .text(function(d,i) {return d.name}) 
      .transition().delay(750).style("opacity", 1) 

    } 
}); 

function key(d) { 
    var k = [], p = d; 
    while (p.depth) k.push(p.name), p = p.parent; 
    return k.reverse().join("."); 
} 

function fill(d) { 
    var p = d; 
    while (p.depth > 1) p = p.parent; 
    var c = d3.lab(hue(p.name)); 
    c.l = luminance(d.sum); 
    return c; 
} 

function arcTween(b) { 
    var i = d3.interpolate(this._current, b); 
    this._current = i(0); 
    return function(t) { 
    return arc(i(t)); 
    }; 
} 

function updateArc(d) { 
    return {depth: d.depth, x: d.x, dx: d.dx}; 
} 

d3.select(self.frameElement).style("height", margin.top + margin.bottom + "px"); 

答えて

3

イメージ要素はsvg内で使用できます。あなたのコードで応じD3を使用した(Reference here

、それは私がダニエラMoginiの提案の助けを借りて、このジレンマを解決することができた

svg.append("image").attr("xlink:href", "firefox.jpg") 
    .attr("width", w).attr("height", h) 
    .attr("x", -w/2).attr("y", -h/2) 
+0

はあなたダニエラをありがとう、この例では動作しませんでしたが、あなたはソリューションに私をリードしました。 –

+0

はい、あなたのコードに基づいているだけの例でした。画像のパスを変更し、画像サイズに基づいてwとhのプロパティを割り当てなければなりませんでした。 –

+0

コードで画像のサイズを変更しようとしましたが、私はフィットするように画像を編集するためにPhotoshopを使いました –

0

のようなものになります。 ブドウのイメージのキャンバスサイズを1300x1300pxに、透明な背景とサークル内のブドウのイメージでリサイズしました。私は下のこの寒さを追加

その後:VARアーク= d3.svg.arc()

svg.append("image") 
    .attr("xlink:href", "images/grapes.png") 
    .attr("x", -650) 
    .attr("y", -650); 
関連する問題