我正在尝试为具有多个y轴的多折线图中的每条线分配一个特定的id,这样我就可以创建一个交互式图例,当单击图例时可以打开和关闭这些线。这是我的小提琴link。
var xValueArray = [0,10,20,30,40];
var arr = [[0,40],[0,200,300,400,500]];
//data array is obtained after structuring arr array
var data = [[{x: 0,y: 0},{x: 10,y: 10},{x: 20,y: 20},{x: 30,y: 30},{x: 40,y: 40}],[{x: 0,y: 200},y: 300},y: 400},y: 500}]];
const margin = {
left: 20,right: 20,top: 20,bottom: 80
};
const svg = d3.select('svg');
svg.selectAll("*").remove();
const width = 200 - margin.left - margin.right;
const height = 200 - margin.top - margin.bottom;
//const g = svg.append('g').attr('transform',`translate(${margin.left},${margin.top})`);
const g = svg.append('g').attr('transform',`translate(${80},${margin.top})`);
//************* Axes and Gridlines ***************
const xAxisG = g.append('g');
const yAxisG = g.append('g');
xAxisG.append('text')
.attr('class','axis-label' )
.attr('x',width / 3)
.attr('y',-10)
.style('fill','black')
.text(function(d) {
return "X Axis";
});
yAxisG.append('text')
.attr('class','axis-label' )
.attr('id','primaryYLabel')
.attr('x',-height / 2 )
.attr('y',-15)
.attr('transform',`rotate(-90)`)
.style('text-anchor','middle')
.style('fill','black')
.text(function(d) {
return "Y Axis 1";
});
// interpolator for X axis -- inner plot region
var x = d3.scaleLinear()
.domain([0,d3.max(xValueArray)])
.range([0,width])
.nice();
var yScale = new Array();
for (var i = 0; i < 2; i++){
// interpolator for Y axis -- inner plot region
var y = d3.scaleLinear()
.domain([0,d3.max(arr[i])])
.range([0,height])
.nice();
yScale.push(y);
}
const xAxis = d3.axisTop()
.scale(x)
.ticks(5)
.tickPadding(2)
.tickSize(-height)
const yAxis = d3.axisLeft()
.scale(yScale[0])
.ticks(5)
.tickPadding(2)
.tickSize(-width);
yAxisArray = new Array();
yAxisArray.push(yAxis);
for (var i = 1; i < 2; i++){
var yAxisSecondary = d3.axisLeft()
.scale(yScale[i])
.ticks(5)
yAxisArray.push(yAxisSecondary);
}
svg.append("g")
.attr("class","x axis")
.attr("transform",`translate(80,${height-80})`)
.call(xAxis);
svg.append("g")
.attr("class","y axis")
.attr("transform","translate(80,20)")
.call(yAxis);
var colors = ["blue","red"];
//plot lines
for (var i = 0; i < 2; i++){
var lineFunction = d3.line()
.x(function(d) {return x(d.x); })
.y(function(d) {return yScale[i](d.y); })
.curve(d3.curveLinear);
//plot lines
var paths = g.append("path")
.attr("class","path1")
.attr("id","blueLine")
.attr("d",lineFunction(data[i]))
.attr("stroke",colors[i])
.attr("stroke-width",2)
.attr("fill","none")
.attr("clip-path","url(#clip)")
//plot a circle at each data point
g.selectAll(".dot")
.data(data[i])
.enter().append("circle")
.attr("cx",function(d) { return x(d.x)} )
.attr("cy",function(d) { return yScale[i](d.y); } )
.attr("r",3)
.attr("class","blackDot")
.attr("clip-path","url(#clip)")
}
var translation = 50;
var textTranslation = 0;
var yLabelArray = ["Y Axis 1","Y Axis 2"];
//loop starts from 1 as primary y axis is already plotted
for (var i = 1; i < 2; i++){
svg.append("g")
.attr("transform","translate(" + translation + "," + 20 + ")")
.call(yAxisArray[i]);
yAxisG.append('text')
.attr('x',-height / 2 )
.attr('y',-60)
.attr('transform',`rotate(-90)`)
.style('text-anchor','middle')
.style('fill','black')
.text(yLabelArray[i]);
translation -= 40;
textTranslation += 40;
}
//************* Legend ***************
var legend = svg.selectAll(".legend")
.data(data)
.enter().append("g")
legend.append("rect")
.attr("x",width + 65)
.attr("y",30)
.attr("width",18)
.attr("height",4)
.style("fill","blue")
legend.append("text")
.attr("x",width + 60)
.attr("y",30)
.attr("dy",".35em")
.style("text-anchor","end")
.on("click",function(){
// Determine if current line is visible
var active = blueLine.active ? false : true,newOpacity = active ? 0 : 1;
// Hide or show the elements
d3.select("#blueLine").style("opacity",newOpacity);
// Update whether or not the elements are active
blueLine.active = active;
})
.text(function(d) {
return "Value1";
});
var legend1 = svg.selectAll(".legend")
.data(data)
.enter().append("g")
legend1.append("rect")
.attr("x",50)
.attr("width","red")
legend1.append("text")
.attr("x",50)
.attr("dy",newOpacity);
// Update whether or not the elements are active
blueLine.active = active;
})
.text(function(d) {
return "Value2";
});
var pointLegend = svg.selectAll(".pointLegend")
.data(data)
.enter().append("g")
pointLegend.append("circle")
.attr("r",3)
.attr("cx",width + 70)
.attr("cy",70)
pointLegend.append("text")
.attr("x",70)
.attr("dy",function(d){
// Determine if dots are visible
var active = d.active ? false : true,newOpacity = active ? 0 : 1;
// Hide or show the elements
d3.selectAll(".blackDot").style("opacity",newOpacity);
// Update whether or not the elements are active
d.active = active;
})
.text(function(d) {
return "Data";
});
可以绘制图表的事实意味着for循环可以绘制图表。我正在使用for循环,因为我希望根据用户的输入来绘制图表,在我的实际代码中有一个名为fieldCount的参数来跟踪用户输入中的序列数,因此我在for循环中使用“ 2”因为我的数据数组中只有2个数组以便简化。
从小提琴中,我只能使用可单击的图例切换蓝线,而不能切换红线,因为我为所有行都分配了相同的“ blueLine” ID。如何为特定的行分配特定的id,以便可以使用图例来切换行,是否可以对图例进行编码,从而不必声明那么多的图例变量?任何帮助将不胜感激!