2015-09-16 2 views
1

У меня есть график D3, который должен выглядеть следующим образом:Почему моя диаграмма области D3 сложенная?

enter image description here

Но вместо этого он выглядит следующим образом:

enter image description here

Это код, я использую:

<!DOCTYPE html> 
<meta charset="utf-8"> 
<head> 

</head> 
<body> 
<svg id="chart"></svg> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> 
<script> 
var NSW = "NSW"; 
var QLD = "QLD"; 

var width = 600; 
var height = 400; 
var years = []; 

var getStat = function(year, volatility, basis) { 
    return { 
     d: year, 
     x: basis, 
     vol: volatility, 
     value: 45 * Math.pow(basis, year), 
     high: 45 * Math.pow(basis+volatility, year), 
     low: 45 * Math.pow(basis-volatility, year), 
    } 
} 

for(i = 0; i < 25; i++) { 
    years.push(i); 
} 

var data = years.map(function(year){ return [getStat(year, 0.03, 1.08),getStat(year, 0.02, 1.08), getStat(year, 0.01, 1.08)]; }); // generate bogus data 
var set_one = data.map(function(d) { return d[0];}); 
var set_two = data.map(function(d) { return d[1];}); 
var set_three = data.map(function(d) { return d[2];}); 

var chart = d3.select("#chart").attr("width", width).attr("height", height).append("g"); 
var x = d3.scale.linear().domain([0, years.length]).range([0, width]); 
var y = d3.scale.linear().domain([0, d3.max(data, function(d){ return Math.max(d[0].high, d[1].high); })]).range([0, height]); 
var area = d3.svg.area().x(function(d,i) { return x(i); }) 
.y0(function(d, i){ return d.low}) //FUNCTION FOR BASE-Y 
.y1(function(d, i){ return d.high * 0.99;}); //FUNCTION FOR TOP-Y 

chart 
.selectAll("path.area") 
.data([set_one,set_two,set_three])   // !!! here i can pass both arrays in. 
.enter() 
.append("path") 
.attr("fill", "rgba(0,0,0,0.5)") 
.attr("class", function(d,i) { return [NSW,QLD,"T"][i]; }) 
.attr("d", area); 

</script> 

Что я делаю неправильно?

ответ

1

На самом деле ваш не делает ничего плохого ось у идет вниз, начиная с 0 сверху вниз height. Таким образом, чтобы перевернуть его можно установить y значения height - yValue:

var area = d3.svg.area().x(function(d,i) { return x(i); }) 
.y0(function(d, i){ return (height - (d.low))}) //FUNCTION FOR BASE-Y 
.y1(function(d, i){ return (height - (d.high * 0.99))}); //FUNCTION FOR TOP-Y 

Fiddle Example

1

y ордината в SVG увеличивается вниз. Попробуйте это ...

var y = d3.scale.linear().domain([d3.max(data, function(d){ return Math.max(d[0].high, d[1].high); }), 0]).range([0, height]); 
1

Как и все в HTML/CSS/Canvas, ось Y начинается с 0 в верхней части и спускается к height на дно.

Итак, согласно вашей настройке, график ведет себя правильно.

Существует несколько способов изменения направления графиков.

а) Вы можете изменить диапазон вашей оси var y = d3.scale.linear().domain([...]).range([height, 0]);

б) Вы можете изменить домен вашей оси var y = d3.scale.linear().domain([d3.max(data, function(d){ return Math.max(d[0].high, d[1].high); }), 0]).range([...]);

или с) изменить способ графа получает Y-значение с d3.svg.area().y0(...) и d3.svg.area().y1(...)

Я бы порекомендовал первый вариант, потому что это фактически определяет диапазон , на который проецируется ваш домен.

1

Я думаю, что возникла проблема с вашим y-масштабированием. Я инвертировал диапазон от диапазона ([высота, 0], который изначально находился в диапазоне ([0, высота]), так как это должно быть так, как в соответствии с нормами d3 в противном случае вы должны изменить логику при расчете высоты участка.

Здесь я прилагаю фиксированный код.

<!DOCTYPE html> 
<meta charset="utf-8"> 
<head> 

</head> 
<body> 
<svg id="chart"></svg> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> 
<script> 
var NSW = "NSW"; 
var QLD = "QLD"; 

var width = 600; 
var height = 400; 
var years = []; 

var getStat = function(year, volatility, basis) { 
    return { 
     d: year, 
     x: basis, 
     vol: volatility, 
     value: 45 * Math.pow(basis, year), 
     high: 45 * Math.pow(basis+volatility, year), 
     low: 45 * Math.pow(basis-volatility, year), 
    } 
} 

for(i = 0; i < 25; i++) { 
    years.push(i); 
} 

var data = years.map(function(year){ return [getStat(year, 0.03, 1.08),getStat(year, 0.02, 1.08), getStat(year, 0.01, 1.08)]; }); // generate bogus data 
var set_one = data.map(function(d) { return d[0];}); 
var set_two = data.map(function(d) { return d[1];}); 
var set_three = data.map(function(d) { return d[2];}); 

var chart = d3.select("#chart").attr("width", width).attr("height", height).append("g"); 
var x = d3.scale.linear().domain([0, years.length]).range([0, width]); 
var y = d3.scale.linear().domain([0, d3.max(data, function(d){ return Math.max(d[0].high, d[1].high); })]).range([height, 0]); 
var area = d3.svg.area().x(function(d,i) { return x(i); }) 
.y0(function(d, i){ return y(d.low)}) //FUNCTION FOR BASE-Y 
.y1(function(d, i){ return y(d.high * 0.99);}); //FUNCTION FOR TOP-Y 

chart 
.selectAll("path.area") 
.data([set_one,set_two,set_three])   // !!! here i can pass both arrays in. 
.enter() 
.append("path") 
.attr("fill", "rgba(0,0,0,0.5)") 
.attr("class", function(d,i) { return [NSW,QLD,"T"][i]; }) 
.attr("d", area); 

</script> 
+0

Просьба уточнить, что именно вы изменили и что вызвало проблему. – Rouby

+0

объяснил, что я сделал. Это работа, которую вы можете проверить. –

Смежные вопросы