我使用d3绘制了一个多系列线,并在鼠标悬停在点上时添加了一条垂直线。我想隐藏2018点没有数据的垂直线和文本。我不知道如何在translate(415,0)
的特定点选择该行,因此我无法将样式更改为display:none
;
以下是代码:
var data =[
{
'timescale': '2015',
'Not': 31,
'Nearly': 59,
'Standard': 81,
'Exceed':100
},
{
'timescale': '2016',
'Not': 28,
'Nearly': 55,
'Standard': 78,
'Exceed':100
},
{
'timescale': '2017',
'Not': 25,
'Nearly': 51,
'Standard': 75,
'Exceed':100
},
{
'timescale': '2018',
'Not': "null",
'Nearly': "null",
'Standard': "null",
'Exceed':"null"
},
{
'timescale': '2019',
'Not': 41,
'Nearly': 67,
'Standard': 90,
'Exceed':100
},
{
'timescale': '2020',
'Not': 36,
'Nearly': 61,
'Standard': 86,
'Exceed':100
},
{
'timescale': '2021',
'Not': 31,
'Nearly': 55,
'Standard': 82,
'Exceed':100
}
];
//d3.csv("test.csv", function(error,data){
console.log(data);
// set the dimensions and margins of the graph
var margin = { top: 20, right: 80, bottom: 30, left: 50 },
svg = d3.select('svg'),
width = +svg.attr('width') - margin.left - margin.right,
height = +svg.attr('height') - margin.top - margin.bottom;
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// set the ranges
var x = d3.scaleBand().rangeRound([0, width]).padding(1),
y = d3.scaleLinear().rangeRound([height, 0]),
z = d3.scaleOrdinal(["#BBB84B","#789952","#50DB51","#2D602A"]);
// define the line
var line = d3.line()
.defined(function (d) {
return !isNaN(d.total);
})
.x(function(d) { return x(d.timescale); })
.y(function(d) { return y(d.total); });
// scale the range of the data
z.domain(d3.keys(data[0]).filter(function(key) {
return key !== "timescale";
}));
var trends = z.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
timescale: d.timescale,
total: +d[name]
};
})
};
});
x.domain(data.map(function(d) { return d.timescale; }));
y.domain([0, d3.max(trends, function(c) {
return d3.max(c.values, function(v) {
return v.total;
});
})]);
// Draw the line
var trend = g.selectAll(".trend")
.data(trends)
.enter()
.append("g")
.attr("class", "trend");
trend.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return z(d.name); });
// Draw the empty value for every point
var points = g.selectAll('.points')
.data(trends)
.enter()
.append('g')
.attr('class', 'points')
.append('text');
// Draw the circle
trend
.style("fill", "#FFF")
.style("stroke", function(d) { return z(d.name); })
.selectAll("circle.line")
.data(function(d){return d.values} )
.enter()
.append("circle")
.filter(function(d) { return d.timescale !== "2018" })
.attr("r", 5)
.style("stroke-width", 3)
.attr("cx", function(d) { return x(d.timescale); })
.attr("cy", function(d) { return y(d.total); });
// Draw the axis
g.append("g")
.attr("class", "axis axis-x")
.attr("transform", "translate(0, " + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis-y")
.call(d3.axisLeft(y).ticks(6));
var focus = g.append('g')
.attr('class','focus')
.style('display', 'none');
focus.append('line')
.attr('class', 'x-hover-line hover-line')
.attr('y1' , 0)
.attr('y2', height)
.style('stroke',"black");
svg.append('rect')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("mousemove", mousemove);
// var timeScales = data.map(function(name) { return x(name.timescale); });
// console.log(timeScales);
var timeScales = [106,209,312,415,518,621,724];
// d3.select('.focus')
// .attr("x1",415)
// .attr("y1",0)
// .attr("x2",415)
// .attr("y2",height)
// .style("display","none");
function mouseover() {
focus.style("display", null);
d3.selectAll('.points text').style("display", null);
}
function mouseout() {
focus.style("display", "none");
d3.selectAll('.points text').style("display", "none");
}
function mousemove() {
var i = d3.bisect(timeScales, d3.mouse(this)[0], 1);
var di = data[i-1];
focus.attr("transform", "translate(" + x(di.timescale) + ",0)");
d3.selectAll('.points text')
.attr('x', function(d) { return x(di.timescale) + 5; })
.attr('y', function(d) { return y(d.values[i-1].total)-5; })
.text(function(d) { return d.values[i-1].total; })
.style('fill', function(d) { return z(d.name); });
}
body {
font-family: 'Proxima Nova', Georgia, sans-serif;
}
.line {
fill: none;
stroke-width: 3px;
}
.overlay {
fill: none;
pointer-events: all;
}
.hover-line {
stroke-width: 2px;
stroke-dasharray: 3,3;
}
<svg width="960" height="500"></svg>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js'></script>
答案 0 :(得分:0)
在mousemove函数中,如果时间刻度不是2018,则仅执行转换:
function mousemove() {
var i = d3.bisect(timeScales, d3.mouse(this)[0], 1);
var di = data[i-1];
if (di.timescale !== '2018') {
focus.attr("transform", "translate(" + x(di.timescale) + ",0)");
d3.selectAll('.points text')
.attr('x', function(d) { return x(di.timescale) + 5; })
.attr('y', function(d) { return y(d.values[i-1].total)-5; })
.text(function(d) { return d.values[i-1].total; })
.style('fill', function(d) { return z(d.name); });
}
}
答案 1 :(得分:-1)
你使用二分作为提示
所以只有当它被选中时它才会被绘制,让我们改变它以便在鼠标悬停时它不会绘制2018
var data =[
{
'timescale': '2015',
'Not': 31,
'Nearly': 59,
'Standard': 81,
'Exceed':100
},
{
'timescale': '2016',
'Not': 28,
'Nearly': 55,
'Standard': 78,
'Exceed':100
},
{
'timescale': '2017',
'Not': 25,
'Nearly': 51,
'Standard': 75,
'Exceed':100
},
{
'timescale': '2018',
'Not': "null",
'Nearly': "null",
'Standard': "null",
'Exceed':"null"
},
{
'timescale': '2019',
'Not': 41,
'Nearly': 67,
'Standard': 90,
'Exceed':100
},
{
'timescale': '2020',
'Not': 36,
'Nearly': 61,
'Standard': 86,
'Exceed':100
},
{
'timescale': '2021',
'Not': 31,
'Nearly': 55,
'Standard': 82,
'Exceed':100
}
];
//d3.csv("test.csv", function(error,data){
// console.log(data);
// set the dimensions and margins of the graph
var margin = { top: 20, right: 80, bottom: 30, left: 50 },
svg = d3.select('svg'),
width = +svg.attr('width') - margin.left - margin.right,
height = +svg.attr('height') - margin.top - margin.bottom;
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// set the ranges
var x = d3.scaleBand().rangeRound([0, width]).padding(1),
y = d3.scaleLinear().rangeRound([height, 0]),
z = d3.scaleOrdinal(["#BBB84B","#789952","#50DB51","#2D602A"]);
// define the line
var line = d3.line()
.defined(function (d) {
return !isNaN(d.total);
})
.x(function(d) { return x(d.timescale); })
.y(function(d) { return y(d.total); });
// scale the range of the data
z.domain(d3.keys(data[0]).filter(function(key) {
return key !== "timescale";
}));
var trends = z.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
timescale: d.timescale,
total: +d[name]
};
})
};
});
x.domain(data.map(function(d) { return d.timescale; }));
y.domain([0, d3.max(trends, function(c) {
return d3.max(c.values, function(v) {
return v.total;
});
})]);
// Draw the line
var trend = g.selectAll(".trend")
.data(trends)
.enter()
.append("g")
.attr("class", "trend");
trend.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return z(d.name); });
// Draw the empty value for every point
var points = g.selectAll('.points')
.data(trends)
.enter()
.append('g')
.attr('class', 'points')
.append('text');
// Draw the circle
trend
.style("fill", "#FFF")
.style("stroke", function(d) { return z(d.name); })
.selectAll("circle.line")
.data(function(d){return d.values} )
.enter()
.append("circle")
.filter(function(d) { return d.timescale !== "2018" })
.attr("r", 5)
.style("stroke-width", 3)
.attr("cx", function(d) { return x(d.timescale); })
.attr("cy", function(d) { return y(d.total); });
// Draw the axis
g.append("g")
.attr("class", "axis axis-x")
.attr("transform", "translate(0, " + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis-y")
.call(d3.axisLeft(y).ticks(6));
var focus = g.append('g')
.attr('class','focus')
.style('display', 'none');
focus.append('line')
.attr('class', 'x-hover-line hover-line')
.attr('y1' , 0)
.attr('y2', height)
.style('stroke',"black");
svg.append('rect')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("mousemove", mousemove);
// var timeScales = data.map(function(name) { return x(name.timescale); });
// console.log(timeScales);
var timeScales = [106,209,312,415,518,621,724];
// d3.select('.focus')
// .attr("x1",415)
// .attr("y1",0)
// .attr("x2",415)
// .attr("y2",height)
// .style("display","none");
function mouseover() {
focus.style("display", null);
d3.selectAll('.points text').style("display", null);
}
function mouseout() {
focus.style("display", "none");
d3.selectAll('.points text').style("display", "none");
}
function mousemove() {
var i = d3.bisect(timeScales, d3.mouse(this)[0], 1);
var di = data[i-1];
console.log(di)
if (di.timescale =="2018"){
focus.style('display','none')
d3.selectAll('.points text').style("display", "none");
}else{
focus.style('display','block')
d3.selectAll('.points text').style("display", "block");
focus.attr("transform", "translate(" + x(di.timescale) + ",0)");}
d3.selectAll('.points text')
.attr('x', function(d) { return x(di.timescale) + 5; })
.attr('y', function(d) { return y(d.values[i-1].total)-5; })
.text(function(d) { return d.values[i-1].total; })
.style('fill', function(d) { return z(d.name); });
}
body {
font-family: 'Proxima Nova', Georgia, sans-serif;
}
.line {
fill: none;
stroke-width: 3px;
}
.overlay {
fill: none;
pointer-events: all;
}
.hover-line {
stroke-width: 2px;
stroke-dasharray: 3,3;
}
<svg width="960" height="500"></svg>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js'></script>