我这样做了一个data.csv
文件:
CODE,YEAR,MODALITY,VALUE
AB,2000,first,15
AB,2000,second,
AB,2000,third,33
AB,2001,first,20
AB,2001,second,25
AB,2001,third,87
AB,2002,first,6
AB,2002,second,
AB,2002,third,16
AB,2003,first,50
AB,2003,second,50
AB,2003,third,10
AB,2004,first,20
AB,2004,second,55
AB,2004,third,8
AC,2000,first,
AC,2000,second,97
AC,2000,third,77
AC,2001,first,42
AC,2001,second,5
AC,2001,third,81
AC,2002,first,
AC,2002,second,63
AC,2002,third,14
AC,2003,first,5
AC,2003,second,7
AC,2003,third,0
AC,2004,first,5
AC,2004,second,7
AC,2004,third,0
AD,2000,first,11
AD,2000,second,2
AD,2000,third,36
AD,2001,first,95
AD,2001,second,78
AD,2001,third,88
AD,2002,first,89
AD,2002,second,32
AD,2002,third,79
AD,2003,first,5
AD,2003,second,32
AD,2003,third,9
AD,2004,first,7
AD,2004,second,32
AD,2004,third,91
AE,2000,first,15
AE,2000,second,78
AE,2000,third,1
AE,2001,first,5
AE,2001,second,2
AE,2001,third,64
AE,2002,first,44
AE,2002,second,51
AE,2002,third,
AE,2003,first,40
AE,2003,second,52
AE,2003,third,85
AE,2004,first,45
AE,2004,second,50
AE,2004,third,80
我创建了一个由一些用户可选元素组成的index.html
文件(在示例中,为简单起见,我选择了4个代码为 AB , AC 的圈子, AD 或 AE )和3个单选按钮(第一个,第二个和第三个)
用户可以选择一个或多个圈子,也可以选择一个单选按钮。
所以我有一个数组codes
,其中包含所选圈子的代码以及包含所选单选按钮的modalitySelected
变量。
我想要做的是一个折线图,它根据用户的选择来表示数据。
每个所选代码都有一行,其值与所选单选按钮对应。
在这个例子中有一些缺失数据,虚线就是这样。 (目前这并不重要)。
这是我的代码。最初管理圆圈的选择并创建包含所选元素的代码的codes
数组。
然后创建折线图。
的index.html :
<body>
<div id="circles">
<svg>
<circle id="AB" cx="10" cy="10" r="10" fill="purple" />
<circle id="AC" cx="60" cy="60" r="5" fill="red" />
<circle id="AD" cx="110" cy="110" r="15" fill="orange" />
<circle id="AE" cx="90" cy="50" r="7" fill="yellow" />
</svg>
</div>
<button type="button" id="finalSelection">Finish</button>
<span style="display:block;margin-top: 10px;">Selected codes: <span class="values"></span></span><br>
<div id="modality-selector-container">
<form id="modality-selector">
<input type="radio" name="modality-selector" id="rb-first" value="first" checked />
<label for="rb-first">First</label>
<input type="radio" name="modality-selector" id="rb-second" value="second" />
<label for="rb-second">Second</label>
<input type="radio" name="modality-selector" id="rb-third" value="third" />
<label for="rb-third">Third</label>
</form>
</div>
<div id="line-chart-container"></div>
<script src="./script.js"></script>
</body>
的script.js :
var codes = [];
modalitySelected = document.querySelector('input[name=modality-selector]:checked').value;
var filtered_data = null;
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 50};
var width = 600 - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// parse the date/time
var parseTime = d3.timeParse("%Y");
var svg = null;
var valueline = null;
d3.selectAll('#circles svg circle').on('click', function() {
var id = d3.select(this).attr('id');
if(d3.select(this).classed('clicked')) {
d3.select(this).classed('clicked', false).style('stroke', null);
codes.splice(codes.indexOf(id), 1);
}
else {
if(codes.length) {
if(d3.event.ctrlKey) {
d3.select(this).classed('clicked', true).style('stroke', 'blue');
codes.push(id);
}
else {
d3.selectAll(".clicked").classed('clicked', false).style('stroke', null);
codes = [];
d3.select(this).classed('clicked', true).style('stroke', 'blue');
codes.push(id);
}
}
else {
d3.select(this).classed('clicked', true).style('stroke', 'blue');
codes.push(id);
}
}
$('span.values').html(codes.join(', '));
});
$('button#finalSelection').click(function() {
$('span.values').html(codes.join(', '));
console.log("compare: " + codes);
compareCodes();
});
function compareCodes() {
// define the line
valueline = d3.line()
.x(function(d) {
return x(d.YEAR);
})
.y(function(d) {
return y(d.VALUE);
});
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
svg = d3.select("#line-chart-container").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
getData();
}
function getData() {
d3.queue()
.defer(d3.csv, './data.csv')
.await(makeLineChart);
}
function makeLineChart(error, data) {
if(error) {
console.log(error);
}
// radio button change
d3.selectAll("input[name='modality-selector']")
.on("change", function(){
console.log(this.value);
modalitySelected = this.value;
// filter data
filtered_data = data.filter(function(d) {
return d.MODALITY == modalitySelected && d.CODE == codes[0];
});
// format the data
filtered_data.forEach(function(d) {
d.YEAR = parseTime(d.YEAR);
d.VALUE = +d.VALUE;
});
updateGraph(filtered_data);
}); // end radio on change
// generate initial line chart - filter data
filtered_data = data.filter(function(d) {
return d.MODALITY == modalitySelected && d.CODE == codes[0];
});
updateGraph(filtered_data);
}
function updateGraph(data) {
var numTickXaxis = data.length;
// scale the range of the data
x.domain(d3.extent(filtered_data, function(d) {
return d.YEAR;
}));
y.domain([0, d3.max(filtered_data, function(d) {
return d.VALUE;
})]);
// add the valueline path
svg.append("path")
.data([filtered_data])
.attr("class", "line")
.attr("d", valueline);
// add the X Axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat("%Y"))
.ticks(numTickXaxis))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");
// add the Y Axis
svg.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y));
var state = svg.selectAll(".line");
state.exit().remove();
}
完整代码为HERE。
在此代码中有两个问题:
state.exit().remove();
)codes
中的第一个元素。我不知道如何处理codes
由多个元素组成并显示更多行的情况。我可以考虑修改data.csv
保持相同内容的结构的想法。
例如,我可以像这样编辑文件:
CODE,YEAR,FIRST,SECOND,THIRD
AB,2000,15,50,33
AB,2001,20,25,87
AB,2002,6,,16
AB,2003,50,50,10
AB,2004,20,55,8
AC,2000,,97,77
AC,2001,42,5,81
AC,2002,,63,14
AC,2003,5,7,0
AC,2004,5,7,0
AD,2000,11,2,36
AD,2001,95,78,88
AD,2002,89,32,79
AD,2003,5,32,9
AD,2004,7,32,91
AE,2000,15,78,1
AE,2001,5,2,64
AE,2002,44,51,
AE,2003,40,52,85
AE,2004,45,50,80
有谁知道如何帮助我?谢谢!
在this example之后,我能够解决问题。
HERE代码。
现在我只有一个小的(我希望)图形问题。 在这张图片中,我们可以清楚地看到问题所在。
线条在轴之前开始。为什么?
答案 0 :(得分:1)
问题在于"transform", "translate("
createAxis()
将您的轴移到一边。
所以我添加了
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
到原始svg
变量,使其与轴对齐并删除
.attr("transform", "translate(" + 0 + "," + 0 + ")");
来自createAxis()
这里是链接:Plunker