我想在d3中更改以下代码中的域

时间:2015-11-13 06:40:53

标签: javascript d3.js

var margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
padding = 0.3;

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], padding);

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

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

var yAxis = d3.svg.axis()
        .scale(y)
         .orient("left")
        .tickFormat(function(d) { return percentage(d); })

var tooltip = d3.select("body").append("div")   
.attr("class", "tooltip")               
.style("opacity", 0)
 .attr("align","middle");

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

data = [
 {"name":"Product Revenue","value":420000},
 {"name":"Services Revenue","value":210000},
 {"name":"Employee Revenue","value":190000}, 
 {"name":"Fixed Costs","value":-170000},
 {"name":"Variable Costs","value":-140000}

  ];


//function to find all the positive values
var positive_val = data.filter(function(d) { return d.value > 0; });
console.log(JSON.stringify(positive_val));

//function to calculate the sum of all the positive values
var maxSum = positive_val.reduce(function(sum, d) {
return sum + d.value;
}, 0);
console.log("The maximum sum is "+maxSum);

//to calculate the new Domain by adding 120 
var yaxisRange=maxSum+120;
console.log("The y axis sum is "+yaxisRange);
var newDomain=percentage(yaxisRange);
console.log(newDomain);
var newDomain = newDomain.replace(/[!@#$%^&*]/g, "");
console.log(newDomain);

// Transform data (i.e., finding cumulative values and total)   
var cumulative = 0;
for (var i = 0; i < data.length; i++) {
data[i].start = cumulative;
cumulative += data[i].value;
data[i].end = cumulative;

data[i].class = ( data[i].value >= 0 ) ? 'positive' : 'negative'
}
data.push({
name: 'Total',
end: cumulative,
start: 0,
class: 'total',
value: cumulative
 });

 x.domain(data.map(function(d) { return d.name; }));
 y.domain([0, d3.max(data, function(d) { return d.end; })]);
//WHen i try to use this as my new domain,the bar increase the height 
//y.domain([0,newDomain]);


debugger;

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

 chart.append("g")
  .attr("class", "y axis")
  .call(yAxis);

  var bar = chart.selectAll(".bar")
  .data(data)
   .enter().append("g")
  .attr("class", function(d) { return "bar " + d.class })
  .attr("transform", function(d) { return "translate(" + x(d.name) +    ",0)"; });

  bar.append("rect")
   //.attr("y", function(d) { return y(d.value); })
  .attr("y", function(d) { return y( Math.max(d.start, d.end) ); })
  .attr("height", function(d) { return Math.abs( y(d.start) - y(d.end) );  })
  //function to draw the tooltip
  .attr("width", x.rangeBand()).on("mouseover", function(d) {
 // to find the parent node,to calculate the x position
 var parentG = d3.select(this.parentNode);
 var barPos = parseFloat(parentG.attr('transform').split("(")[1]);
 var xPosition = barPos+x.rangeBand()/2;
  //to find the y position
 var yPosition = parseFloat(d3.select(this).attr("y"))+ Math.abs( y(d.start) - y(d.end))/2;
       tooltip.transition()     
            .duration(200)      
            .style("opacity", .9);  
      tooltip.html(d.name + "<br/>"  + percentage(d.value)) 
            .style("left", xPosition + "px")        
            .style("top",  yPosition + "px");   
        }).on("mouseout", function(d) {     
        tooltip.transition()        
            .duration(500)      
            .style("opacity", 0);   
    });

    bar.append("text")
  .attr("x", x.rangeBand() / 2)
  .attr("y", function(d) { return y(d.end) + 5; })
  .attr("dy", function(d) { return ((d.class=='negative') ? '-' : '') + ".75em" })
  .text(function(d) { return percentage(d.end - d.start);});


   bar.filter(function(d) { return d.class != "total" }).append("line")
  .attr("class", "connector")
  .attr("x1", x.rangeBand() + 5 )
  .attr("y1", function(d) { return y(d.end) } )
  .attr("x2", x.rangeBand() / ( 1 - padding) - 5 )
  .attr("y2", function(d) { return y(d.end) } )


  function type(d) {
  d.value = +d.value;
   return d;
   }

 function percentage(n) {
  n = Math.round(n);
  var result = n;
  if (Math.abs(n) > 100) {
  result = Math.round(n/100) + '%';
  }
   return  result;
   }

- 这是更新的小提琴http://jsfiddle.net/7mkq4k8k/21/ - 我想让yaxis标签增加。例如9000,9500。我已经计算了新的Domian。 - 如果我尝试添加这个域名,我的图表就不会被正确绘制。条形图的高度会增加,因此不会绘制其余的条形图。请在这个问题上帮助我。

1 个答案:

答案 0 :(得分:0)

因此,您最初绘制的图表基于此域:

    y.domain([0, d3.max(data, function (d) {
        return d.end;
    })]);

尝试console.log(d3.max(data, function (d) {return d.end;})),你会发现它返回820000,这是累积计算的最大值。这意味着您的图表是使用0到820000之间的域绘制的。

现在让我们谈谈你的新域名。您正在使用 maxSum的百分比,这意味着您的新域等于8201.所以现在您正在尝试从0到8201绘制图表。 但你的酒吧高度计算如下: Math.abs(y(d.start) - y(d.end)),表示您正在计算从y(0)到y(820000)的范围(d.end最大等于820000)。

y(820000)不合适,正如您在域中指定的那样,它可以最大化为y(8201)。这就是为什么你的酒吧到达你图表的最顶层的原因,因为你提供的域名与内部的数字并不对应: y(这个数字太大而且不合适,因为它不在0和newDomain之间)。

如何解决这个问题? 您正确定义了域,删除了百分比行

//function to calculate the sum of all the positive values
var maxSum = positive_val.reduce(function (sum, d) {
    return sum + d.value;
}, 0);
console.log("The maximum sum is " + maxSum);

//to calculate the new Domain by adding 520000 (big number to show you it works) 
var newDomain = maxSum + 520000;
console.log(newDomain); //1340000

y.domain([0,newDomain]); 

以下工作片段:

&#13;
&#13;
var margin = {
    top: 20,
    right: 30,
    bottom: 30,
    left: 40
},
width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom,
    padding = 0.3;

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], padding);

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

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

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .tickFormat(function (d) {
    return percentage(d);
})

var tooltip = d3.select("body").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0)
    .attr("align", "middle");

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

data = [{
    "name": "Product Revenue",
    "value": 420000
}, {
    "name": "Services Revenue",
    "value": 210000
}, {
    "name": "Employee Revenue",
    "value": 190000
}, {
    "name": "Fixed Costs",
    "value": -170000
}, {
    "name": "Variable Costs",
    "value": -140000
}

];


//function to find all the positive values
var positive_val = data.filter(function (d) {
    return d.value > 0;
});
console.log(JSON.stringify(positive_val));

//function to calculate the sum of all the positive values
var maxSum = positive_val.reduce(function (sum, d) {
    return sum + d.value;
}, 0);
console.log("The maximum sum is " + maxSum);

//to calculate the new Domain by adding 120 
var newDomain = maxSum + 520000;
console.log(newDomain);

// Transform data (i.e., finding cumulative values and total)   
var cumulative = 0;
for (var i = 0; i < data.length; i++) {
    data[i].start = cumulative;
    cumulative += data[i].value;
    data[i].end = cumulative;

    data[i].class = (data[i].value >= 0) ? 'positive' : 'negative'
}
data.push({
    name: 'Total',
    end: cumulative,
    start: 0,
    class: 'total',
    value: cumulative
});

x.domain(data.map(function (d) {
    return d.name;
}));
console.log(d3.max(data, function (d) {
    return d.end;
}));
            
/*y.domain([0, d3.max(data, function (d) {
    return d.end;
})]);*/
//WHen i try to use this as my new domain,the bar increase the height 
y.domain([0,newDomain]);


debugger;

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

chart.append("g")
    .attr("class", "y axis")
    .call(yAxis);

var bar = chart.selectAll(".bar")
    .data(data)
    .enter().append("g")
    .attr("class", function (d) {
    return "bar " + d.class
})
    .attr("transform", function (d) {
    return "translate(" + x(d.name) + ",0)";
});

bar.append("rect")
//.attr("y", function(d) { return y(d.value); })
.attr("y", function (d) {
    return y(Math.max(d.start, d.end));
})
    .attr("height", function (d) {
    return Math.abs(y(d.start) - y(d.end));
})
//function to draw the tooltip
.attr("width", x.rangeBand()).on("mouseover", function (d) {
    // to find the parent node,to calculate the x position
    var parentG = d3.select(this.parentNode);
    var barPos = parseFloat(parentG.attr('transform').split("(")[1]);
    var xPosition = barPos + x.rangeBand() / 2;
    //to find the y position
    var yPosition = parseFloat(d3.select(this).attr("y")) + Math.abs(y(d.start) - y(d.end)) / 2;
    tooltip.transition()
        .duration(200)
        .style("opacity", .9);
    tooltip.html(d.name + "<br/>" + percentage(d.value))
        .style("left", xPosition + "px")
        .style("top", yPosition + "px");
}).on("mouseout", function (d) {
    tooltip.transition()
        .duration(500)
        .style("opacity", 0);
});

bar.append("text")
    .attr("x", x.rangeBand() / 2)
    .attr("y", function (d) {
    return y(d.end) + 5;
})
    .attr("dy", function (d) {
    return ((d.class == 'negative') ? '-' : '') + ".75em"
})
    .text(function (d) {
    return percentage(d.end - d.start);
});


bar.filter(function (d) {
    return d.class != "total"
}).append("line")
    .attr("class", "connector")
    .attr("x1", x.rangeBand() + 5)
    .attr("y1", function (d) {
    return y(d.end)
})
    .attr("x2", x.rangeBand() / (1 - padding) - 5)
    .attr("y2", function (d) {
    return y(d.end)
})


function type(d) {
    d.value = +d.value;
    return d;
}

function percentage(n) {
    n = Math.round(n);
    var result = n;
    if (Math.abs(n) > 100) {
        result = Math.round(n / 100) + '%';
    }
    return result;
}
&#13;
.bar.total rect {
    fill: steelblue;
}
.bar:hover rect {
    fill:orange;
}
.bar.positive rect {
    fill: darkolivegreen;
}
.bar:hover rect {
    fill:orange;
}
.bar.negative rect {
    fill: crimson;
}
.bar:hover rect {
    fill:orange;
}
.bar line.connector {
    stroke: grey;
    stroke-dasharray: 3;
}
.bar text {
    fill: white;
    font: 12px sans-serif;
    text-anchor: middle;
}
.axis text {
    font: 10px sans-serif;
}
.axis path, .axis line {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
}
div.tooltip {
    position:absolute;
    text-align: center;
    padding: 2px;
    font: 12px sans-serif;
    background: #33CC00;
    border: 0px;
    border-radius: 8px;
    pointer-events: none;
    width: 90px;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg class="chart"></svg>
&#13;
&#13;
&#13;

希望这有帮助!