代码之家  ›  专栏  ›  技术社区  ›  Datacrawler

响应式D3甜甜圈图

  •  0
  • Datacrawler  · 技术社区  · 6 年前

    我使用一个圆环图来呈现静态JSON查询中的数据。我现在想让它有反应。我已经使其他的d3图有了响应,但对于这个图来说是不同的。

    这个想法是首先计算屏幕两个角之间的距离(斜边),以便重新计算我的形状的半径。这对以后可能有用。此计算的代码段如下所示:

    console.log('width')
    console.log(window.innerWidth);
    console.log('height')
    console.log(window.innerHeight);
    console.log('final');
    console.log(Math.sqrt(Math.pow(window.innerWidth,2) + Math.pow(window.innerHeight,2)));
    
    
    $("#one").html(Math.sqrt(Math.pow(window.innerWidth,2) + Math.pow(window.innerHeight,2)));
    <script src="https://code.jquery.com/jquery-1.9.1.js"></script>
    <div id="one"></div>
    
     

    我的主要代码片段在这里,它是响应的,但是带有值(工具提示)的框显示在甜甜圈下面。

    var margin = {top: 20, right: 20, bottom: 50, left: 100},
        width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right,
        height = parseInt(d3.select("#chart").style("width")) - margin.top - margin.bottom,
        r = 180,
        inner = 180/2,
        color= d3.scale.ordinal()
        .range(["#124", "#214183", "#3061c2",  "#4876d1", "#87a5e1", "#c5d4f1"]);
        
    data = [{"label":"ONE", "value":194}, 
            {"label":"TWO", "value":567}, 
            {"label":"THREE", "value":1314},
            {"label":"FOUR", "value":793},
            {"label":"FIVE", "value":1929},
            {"label":"SIX", "value":1383}];
    
    var total = d3.sum(data, function(d) {
        return d3.sum(d3.values(d));
    });
    
     
     var vis = d3.select('#chart').append("svg:svg").data([data])
             .attr("width", '100%')
             .attr("height", '100%')
             .attr('viewBox',(-width / 2 ) + ' ' + (-height/2) + ' '+width +' '+height)
             .attr('preserveAspectRatio','xMinYMin')
    
    
    var textTop = vis.append("text")
        .attr("dy", ".35em")
        .style("text-anchor", "middle")
        .attr("class", "textTop")
        .text( "TOTAL" )
        .attr("y", -10),
    textBottom = vis.append("text")
        .attr("dy", ".35em")
        .style("text-anchor", "middle")
        .attr("class", "textBottom")
        .text(total.toFixed(2) + "m")
        .attr("y", 10);
    
    var arc = d3.svg.arc()
        .innerRadius(inner)
        .outerRadius(r);
    
    var arcOver = d3.svg.arc()
        .innerRadius(inner + 5)
        .outerRadius(r + 5);
     
    var pie = d3.layout.pie()
        .value(function(d) { return d.value; });
     
    var arcs = vis.selectAll("g.slice")
        .data(pie)
        .enter()
            .append("svg:g")
                .attr("class", "slice")
                .on("mouseover", function(d) {
                    d3.select(this).select("path").transition()
                        .duration(200)
                        .attr("d", arcOver)
                    
                    textTop.text(d3.select(this).datum().data.label)
                        .attr("y", -10);
                    textBottom.text(d3.select(this).datum().data.value.toFixed(2))
                        .attr("y", 10);
                })
                .on("mouseout", function(d) {
                    d3.select(this).select("path").transition()
                        .duration(100)
                        .attr("d", arc);
                    
                    textTop.text( "TOTAL" )
                        .attr("y", -10);
                    textBottom.text(total.toFixed(2) + "m");
                });
    
    arcs.append("svg:path")
        .attr("fill", function(d, i) { return color(i); } )
        .attr("d", arc);
    
    var legend = d3.select("#chart").append("svg")
        .attr("class", "legend")
        .attr("width", r)
        .attr("height", r * 2)
        .selectAll("g")
        .data(data)
        .enter().append("g")
        .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
    
    legend.append("rect")
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", function(d, i) { return color(i); });
    
    legend.append("text")
        .attr("x", 24)
        .attr("y", 9)
        .attr("dy", ".35em")
        .text(function(d) { return d.label; }); 
    *{
      font-family: 'Roboto', sans-serif;
      text-transform:capitalize;
      margin: 0 auto;
      text-align:left;
    }
    
    body {
            font-family: "Roboto"!important;
            width: 100%;
            height: 400px;
            position: relative;
        }
    
     
    
    .slice path {
        stroke: #fff;
        stroke-width: 1px;
    }
    
    .textTop {
        font-size: 12pt;
        fill: #bbb;
    }
    
    .textBottom {
        fill: #444;
        font-weight: bold;
        font-size: 18pt;
    }
    
    .top {
        border: 1px solid #bbb;
        color: #777;
        padding: 5px;
        text-decoration: none;
    }
    
    .top:hover {
        border: 1px solid #555;
        color: #333;
    }
    <script src="https://d3js.org/d3.v3.min.js"></script>
    <div id="chart"></div>
    
    <svg id="chart2"></svg>

    如何在甜甜圈的右侧包含工具提示(图例-不确定确切术语)?

    1 回复  |  直到 6 年前
        1
  •  1
  •   S. Bureau    6 年前

    您可以通过以下方式将图例直接包含到主SVG中:

    var svg = d3.select('#chart').append("svg:svg");
    var vis = svg.data([data])
    (...)
    

    而不是:

    var vis = d3.select('#chart').append("svg:svg").data([data])
    (...)
    

    然后,您可以将您的图例添加到该SVG,替换为:

    var legend = d3.select("#chart").append("svg")
    

    用:

    var legend = svg.append("svg")
    

    最后,您必须处理图例放置。下面是一个正在工作的jsiddle: https://jsfiddle.net/anh9Lr1e/4/ 以及一个代码片段,以防jsFiddle URL过期:

    var margin = {top: 20, right: 20, bottom: 50, left: 100},
        width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right,
        height = parseInt(d3.select("#chart").style("width")) - margin.top - margin.bottom,
        r = 180,
        inner = 180/2,
        color= d3.scale.ordinal()
        .range(["#124", "#214183", "#3061c2",  "#4876d1", "#87a5e1", "#c5d4f1"]);
        
    data = [{"label":"ONE", "value":194}, 
            {"label":"TWO", "value":567}, 
            {"label":"THREE", "value":1314},
            {"label":"FOUR", "value":793},
            {"label":"FIVE", "value":1929},
            {"label":"SIX", "value":1383}];
    
    var total = d3.sum(data, function(d) {
        return d3.sum(d3.values(d));
    });
    
     
     var svg = d3.select('#chart').append("svg:svg")
     			.attr("width", '100%')
            .attr("height", '100%')
            .attr('preserveAspectRatio','xMinYMin');
     var vis = svg.data([data])
             .attr("width", '100%')
             .attr("height", '100%')
             .attr('viewBox',(-width / 2 ) + ' ' + (-height/2) + ' '+width +' '+height)
             .attr('preserveAspectRatio','xMinYMin')
    
    
    var textTop = vis.append("text")
        .attr("dy", ".35em")
        .style("text-anchor", "middle")
        .attr("class", "textTop")
        .text( "TOTAL" )
        .attr("y", -10),
    textBottom = vis.append("text")
        .attr("dy", ".35em")
        .style("text-anchor", "middle")
        .attr("class", "textBottom")
        .text(total.toFixed(2) + "m")
        .attr("y", 10);
    
    var arc = d3.svg.arc()
        .innerRadius(inner)
        .outerRadius(r);
    
    var arcOver = d3.svg.arc()
        .innerRadius(inner + 5)
        .outerRadius(r + 5);
     
    var pie = d3.layout.pie()
        .value(function(d) { return d.value; });
     
    var arcs = vis.selectAll("g.slice")
        .data(pie)
        .enter()
            .append("svg:g")
                .attr("class", "slice")
                .on("mouseover", function(d) {
                    d3.select(this).select("path").transition()
                        .duration(200)
                        .attr("d", arcOver)
                    
                    textTop.text(d3.select(this).datum().data.label)
                        .attr("y", -10);
                    textBottom.text(d3.select(this).datum().data.value.toFixed(2))
                        .attr("y", 10);
                })
                .on("mouseout", function(d) {
                    d3.select(this).select("path").transition()
                        .duration(100)
                        .attr("d", arc);
                    
                    textTop.text( "TOTAL" )
                        .attr("y", -10);
                    textBottom.text(total.toFixed(2) + "m");
                });
    
    arcs.append("svg:path")
        .attr("fill", function(d, i) { return color(i); } )
        .attr("d", arc);
    
    var legend = svg.append("svg")
        .attr("class", "legend")
        //.attr("width", r)
        //.attr("height", r * 2)
        .selectAll("g")
        .data(data)
        .enter().append("g")
        .attr("transform", function(d, i) { return "translate(" + (r + 20) + "," + i * 20 + ")"; });
    
    legend.append("rect")
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", function(d, i) { return color(i); });
    
    legend.append("text")
        .attr("x", 24)
        .attr("y", 9)
        .attr("dy", ".35em")
        .text(function(d) { return d.label; }); 
    *{
      font-family: 'Roboto', sans-serif;
      text-transform:capitalize;
      margin: 0 auto;
      text-align:left;
    }
    
    body {
            font-family: "Roboto"!important;
            width: 100%;
            height: 400px;
            position: relative;
        }
    
     
    
    .slice path {
        stroke: #fff;
        stroke-width: 1px;
    }
    
    .textTop {
        font-size: 12pt;
        fill: #bbb;
    }
    
    .textBottom {
        fill: #444;
        font-weight: bold;
        font-size: 18pt;
    }
    
    .top {
        border: 1px solid #bbb;
        color: #777;
        padding: 5px;
        text-decoration: none;
    }
    
    .top:hover {
        border: 1px solid #555;
        color: #333;
    }
     
    <script src="https://d3js.org/d3.v3.min.js"></script>
    <div id="chart"></div>