隐藏或删除特定点D3图表中的垂直线

时间:2017-08-25 00:12:04

标签: javascript css d3.js

我使用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>

2 个答案:

答案 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>