相对于条宽,在d3图表中自定义轴点

时间:2017-02-15 08:07:49

标签: d3.js bar-chart

我使用d3 js创建了一个分组条形图,以下是代码,我做了一些改动以减少条形宽度,并且它按预期工作。但是轴点位置不正确。你可以从图像中看到:

enter image description here

代码:

    <style>

    body {
      font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      width: 960px;
      height: 500px;
      position: relative;
    }

    svg {
        width: 100%;
        height: 100%;
        position: center;
    }

    text{
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    }

    .toolTip {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        position: absolute;
        display: none;
        width: auto;
        height: auto;
        background: none repeat scroll 0 0 white;
        border: 0 none;
        border-radius: 8px 8px 8px 8px;
        box-shadow: -3px 3px 15px #888888;
        color: black;
        font: 12px sans-serif;
        padding: 5px;
        text-align: center;
    }

    .legend {
        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        font-size: 60%;
    }

    rect {
        stroke-width: 2;
    }

    text {
      font: 10px sans-serif;
    }

    .axis text {
      font: 10px sans-serif;
    }

    .axis path{
      fill: none;
      stroke: #000;
    }

    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }

    .axis .tick line {
      stroke-width: 1;
      stroke: rgba(0, 0, 0, 0.2);
    }

    .axisHorizontal path{
      fill: none;
    }

    .axisHorizontal line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }

    .axisHorizontal .tick line {
      stroke-width: 1;
      stroke: rgba(0, 0, 0, 0.2);
    }

    .bar {
      fill: steelblue;
      fill-opacity: .9;
    }

    .x.axis path {
      display: none;
    }

    </style>
    <body>
    <div id="chart-container">

    </div>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script>

    var margin = {top: (60), right: (50), bottom: (70), left: (35)},
                    width = 700,
                    height = 300;

                var x0 = d3.scale.ordinal()
                    .rangeRoundBands([0, width], .1);

                var x1 = d3.scale.ordinal();

                var y = d3.scale.linear()
                    .range([height, 0]);

                var colorRange = d3.scale.category20();
                var color = d3.scale.ordinal()
                    .range(colorRange.range());

                var xAxis = d3.svg.axis()
                    .scale(x0)
                    .orient("bottom");

                var yAxis = d3.svg.axis()
                    .scale(y)
                    .orient("left")
                    .tickFormat(d3.format(".2s"));

                var divTooltip = d3.select("body").append("div").attr("class", "toolTip");

                var svg = d3.select("#chart-container").append("svg")
                    .attr("width", width + margin.left + margin.right)
                    .attr("height", height + margin.top + margin.bottom)
                    .append("g")
                    .attr("viewBox", "0 0 600 400")
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
                    .text("Value vs Date Graph");

                dataset = [
                    {label:"Men", "Actual":20, "Proposed":10},
                    {label:"Women", "Actual":10, "Proposed":15}
                ];


                if(dataset != undefined)
                {
                    var options = d3.keys(dataset[0]).filter(function(key) { return key !== "label"; });
                }

                dataset.forEach(function(d) {
                    d.valores = options.map(function(name) { return {name: name, value: +d[name]}; });
                });

                x0.domain(dataset.map(function(d) { return d.label; }));
                x1.domain(options).rangeRoundBands([0, Math.min(x0.rangeBand(), 100) ]);
                y.domain([0, d3.max(dataset, function(d) { return d3.max(d.valores, function(d) { return d.value; }); })]);

                svg.append("g")
                    .attr("class", "x axis")
                    .attr("transform", "translate(0," + height + ")")
                    .call(xAxis);

                svg.append("g")
                    .attr("class", "y axis")
                    .call(yAxis)
                    .append("text")
                    .attr("transform", "rotate(-90)")
                    .attr("y", 6)
                    .attr("dy", ".71em")
                    .style("text-anchor", "end")

                svg.append("text")
                    .attr("x", (width / 2))
                    .attr("y", 0 - (margin.top / 2))
                    .attr("text-anchor", "middle")
                    .style("font-size", "16px")
                    .style("text-decoration", "underline")
                    .text("Header");

                svg.append("text")
                    .attr("x", (width / 2))
                    .attr("y", 0-10)
                    .attr("text-anchor", "middle")
                    .style("font-size", "12px")
                    .text('Sub Header');

                var bar = svg.selectAll(".bar")
                    .data(dataset)
                    .enter().append("g")
                    .attr("class", "rect")                
                    .attr("transform", function(d) { return "translate(" + x0(d.label) + ",0)"; });

                bar.selectAll("rect")
                    .data(function(d) { return d.valores; })
                    .enter().append("rect")
                    .attr("width", x1.rangeBand())
                    .attr("x", function(d) { return x1(d.name); })
                    .attr("y", function(d) { return y(d.value); })
                    .attr("value", function(d){return d.name;})
                    .attr("height", function(d) { return height - y(d.value); })
                    .style("fill", function(d) { return color(d.name); });

                bar
                    .on("mousemove", function(d){
                        divTooltip.style("left", d3.event.pageX+10+"px");
                        divTooltip.style("top", d3.event.pageY-25+"px");
                        divTooltip.style("display", "inline-block");
                        var x = d3.event.pageX, y = d3.event.pageY
                        var elements = document.querySelectorAll(':hover');
                        l = elements.length
                        l = l-1
                        elementData = elements[l].__data__
                        divTooltip.html((d.label)+"<br>"+elementData.name+"<br>"+elementData.value);
                    });
                bar
                    .on("mouseout", function(d){
                        divTooltip.style("display", "none");
                    });


                var legend = svg.selectAll(".legend")
                    .data(options.slice())
                    .enter().append("g")
                    .attr("class", "legend")
                    .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

                legend.append("rect")
                    .attr("x", width - 35)
                    .attr("width", 18)
                    .attr("height", 18)
                    .style("fill", color);

                legend.append("text")
                    .attr("x", width - 45)
                    .attr("y", 9)
                    .attr("dy", ".35em")
                    .style("text-anchor", "end")
                    .text(function(d) { return d; });


    </script>
    </body>

1 个答案:

答案 0 :(得分:0)

对于定位bar的代码,请尝试此

var bar = svg.selectAll(".bar")
  ...
  .attr("transform", function(d) {
     var xpos = x0(d.label) + x0.rangeBand()/2 - x1.rangeBand()
     return "translate(" + xpos + ",0)"; });
  })

我们的想法是使用x0的带宽来正确居中<g>