首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在d3中线经过的不同轴上添加工具提示

在d3中线经过的不同轴上添加工具提示
EN

Stack Overflow用户
提问于 2020-11-13 23:36:31
回答 1查看 33关注 0票数 2

我想添加一个工具提示,当鼠标悬停在绘图中的一条线上时,显示确切的值。当线悬停时,如何在线与轴接触的每个轴上添加工具提示?任何帮助都将不胜感激。例如。将鼠标悬停在car行上时,应显示属性first、second、The和fourth。测试和训练数据集也应该发生同样的情况。

代码语言:javascript
复制
var dataSet = [{
    "type": "car",
    "dataset": "test",
    "first": 0.65,
    "second": 0.34,
    "third": 0.55,
    "fourth": 0.39
  },
  {
    "type": "car",
    "dataset": "train",
    "first": 0.59,
    "second": 0.33,
    "third": 0.50,
    "fourth": 0.40
  },
  {
    "type": "bicycle",
    "dataset": "test",
    "first": 200,
    "second": 230,
    "third": 250,
    "fourth": 300
  },
  {
    "type": "bicycle",
    "dataset": "train",
    "first": 200,
    "second": 280,
    "third": 225,
    "fourth": 278
  },
  {
    "type": "boat",
    "dataset": "test",
    "first": 320,
    "second": 324,
    "third": 532,
    "fourth": 321
  },
  {
    "type": "boat",
    "dataset": "train",
    "first": 128,
    "second": 179,
    "third": 166,
    "fourth": 234
  },
  {
    "type": "airplane",
    "dataset": "test",
    "first": 1500,
    "second": 2000,
    "third": 2321,
    "fourth": 1793
  },
  {
    "type": "airplane",
    "dataset": "train",
    "first": 1438,
    "second": 2933,
    "third": 2203,
    "fourth": 2000
  }
];

var processedData = [];
dataSet.forEach(function(d) {
  var match = processedData.find(function(p) { return p.type === d.type; });
  if(!match) {
    match = {
      type: d.type,
    };
    processedData.push(match);
  }

  var values = [d.first, d.second, d.third, d.fourth];
  if(d.dataset === "train") {
    match.train = values;
  } else {
    match.test = values;
  }
});

processedData.forEach(function(d) {
  // Normalise the values in the arrays
  const min = Math.min(d3.min(d.train), d3.min(d.test));
  const max = Math.max(d3.max(d.train), d3.max(d.test));
  
  d.trainNormalised = d.train.map(function(v) {
    return (v - min) / (max - min);
  });
  d.testNormalised = d.test.map(function(v) {
    return (v - min) / (max - min);
  });
});

var margin = {
    top: 5,
    right: 50,
    bottom: 5,
    left: 70
  },
  width = 600 - margin.left - margin.right,
  height = 280 - margin.top - margin.bottom;

var categoryScale = d3.scale.ordinal()
  .domain(processedData.map(function(d) { return d.type; }))
  .rangePoints([0, height]);
var y = d3.scale.linear()
  .domain([0, 1])
  .range([height, 0]);

var x = d3.scale.ordinal()
  .domain(d3.range(5))
  .rangePoints([0, width]);

var line = d3.svg.line()
  .defined(function(d) {
    return !isNaN(d[1]);
  });

// CREATE A COLOR SCALE
var color = d3.scale.ordinal()
  .range(["#4683b8", "#79add2", "#a6c9de", "#cadbed", "#9d9bc4", "#bcbed9", "#dadaea", "#f6d2a8", "#f2b076", "#ef914e", "#d65e2a"])

var svg = d3.select("#parallel_coor")
  .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 + ")");

svg.selectAll(".dimension.axis")
  .data([categoryScale, y, y, y, y])
  .enter()
  .append("g")
  .attr("class", "dimension axis")
  .attr("transform", function(d, i) {
    return "translate(" + x(i) + ")";
  })
  .each(function(d) {
    const yAxis = d3.svg.axis()
      .scale(d)
      .ticks([])
      .orient("left");
    d3.select(this).call(yAxis);
  });

function parallel(data) {
  // Draw one line group per type (car, boat)
  // Each line group consists of a train and a test line;
  var lineGroup = svg.append("g")
    .selectAll(".lineGroup")
    .data(data)
    .enter()
    .append("g")
    .attr("class", "lineGroup")
    .each(function(d) {
      if(d.train)
        d3.select(this).append("path")
          .datum([d, "train"]);

      if(d.test)
        d3.select(this).append("path")
          .datum(function(d) { return [d, "test"]; });
    })

  lineGroup
    .attr("stroke", function(d) {
      var company = d.type.slice(0, d.type.indexOf(' '));
      return color(company);
    })
    .selectAll("path")
    .attr("class", function(d) { return d[1]; })
    .attr("d", draw);
  
  lineGroup
    .on("mouseover", function(d) {
      // show train when click others
      d3.select(this).classed("active", true);
      lineGroup
        .filter(function(e) { return e.type !== d.type; })
        .style('opacity', 0.2);
    })
    .on("mouseout", function(d) {
      d3.select(this).classed("active", false);
      lineGroup.style('opacity', null);
    });

  function draw(d) {
    var data = d[0], type = d[1];
    var points = data[type + "Normalised"].map(function(v, i) {
      return [x(i + 1), y(v)];
    });
    points.unshift([x(0), categoryScale(data.type)]);
    return line(points);
  }
}

parallel(processedData);
代码语言:javascript
复制
svg {
  font: 12px sans-serif;
}

.lineGroup path {
  fill: none;
}

.lineGroup.active .train {
  visibility: visible;
}

.train {
  visibility: hidden;
  stroke-dasharray: 5 5;
}

.axis line,
.axis path {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<div id="parallel_coor"></div>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-14 00:52:35

你可以像下面这样做。当您将鼠标悬停在一条线上时,为每个数据点绘制矩形,添加一些文本和样式,就完成了。我为工具提示提供了不同的类,以便可以根据它们是用于训练数据还是用于测试数据来设置样式

代码语言:javascript
复制
var dataSet = [{
    "type": "car",
    "dataset": "test",
    "first": 0.65,
    "second": 0.34,
    "third": 0.55,
    "fourth": 0.39
  },
  {
    "type": "car",
    "dataset": "train",
    "first": 0.59,
    "second": 0.33,
    "third": 0.50,
    "fourth": 0.40
  },
  {
    "type": "bicycle",
    "dataset": "test",
    "first": 200,
    "second": 230,
    "third": 250,
    "fourth": 300
  },
  {
    "type": "bicycle",
    "dataset": "train",
    "first": 200,
    "second": 280,
    "third": 225,
    "fourth": 278
  },
  {
    "type": "boat",
    "dataset": "test",
    "first": 320,
    "second": 324,
    "third": 532,
    "fourth": 321
  },
  {
    "type": "boat",
    "dataset": "train",
    "first": 128,
    "second": 179,
    "third": 166,
    "fourth": 234
  },
  {
    "type": "airplane",
    "dataset": "test",
    "first": 1500,
    "second": 2000,
    "third": 2321,
    "fourth": 1793
  },
  {
    "type": "airplane",
    "dataset": "train",
    "first": 1438,
    "second": 2933,
    "third": 2203,
    "fourth": 2000
  }
];

var processedData = [];
dataSet.forEach(function(d) {
  var match = processedData.find(function(p) { return p.type === d.type; });
  if(!match) {
    match = {
      type: d.type,
    };
    processedData.push(match);
  }

  var values = [d.first, d.second, d.third, d.fourth];
  if(d.dataset === "train") {
    match.train = values;
  } else {
    match.test = values;
  }
});

processedData.forEach(function(d) {
  // Normalise the values in the arrays
  const min = Math.min(d3.min(d.train), d3.min(d.test));
  const max = Math.max(d3.max(d.train), d3.max(d.test));
  
  d.trainNormalised = d.train.map(function(v) {
    return (v - min) / (max - min);
  });
  d.testNormalised = d.test.map(function(v) {
    return (v - min) / (max - min);
  });
});

var margin = {
    top: 5,
    right: 50,
    bottom: 5,
    left: 70
  },
  width = 600 - margin.left - margin.right,
  height = 280 - margin.top - margin.bottom;

var categoryScale = d3.scale.ordinal()
  .domain(processedData.map(function(d) { return d.type; }))
  .rangePoints([0, height]);
var y = d3.scale.linear()
  .domain([0, 1])
  .range([height, 0]);

var x = d3.scale.ordinal()
  .domain(d3.range(5))
  .rangePoints([0, width]);

var line = d3.svg.line()
  .defined(function(d) {
    return !isNaN(d[1]);
  });

// CREATE A COLOR SCALE
var color = d3.scale.ordinal()
  .range(["#4683b8", "#79add2", "#a6c9de", "#cadbed", "#9d9bc4", "#bcbed9", "#dadaea", "#f6d2a8", "#f2b076", "#ef914e", "#d65e2a"])

var svg = d3.select("#parallel_coor")
  .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 + ")");

svg.selectAll(".dimension.axis")
  .data([categoryScale, y, y, y, y])
  .enter()
  .append("g")
  .attr("class", "dimension axis")
  .attr("transform", function(d, i) {
    return "translate(" + x(i) + ")";
  })
  .each(function(d) {
    const yAxis = d3.svg.axis()
      .scale(d)
      .ticks([])
      .orient("left");
    d3.select(this).call(yAxis);
  });

function parallel(data) {
  // Draw one line group per type (car, boat)
  // Each line group consists of a train and a test line;
  var lineGroup = svg.append("g")
    .selectAll(".lineGroup")
    .data(data)
    .enter()
    .append("g")
    .attr("class", "lineGroup")
    .each(function(d) {
      if(d.train)
        d3.select(this).append("path")
          .datum([d, "train"]);

      if(d.test)
        d3.select(this).append("path")
          .datum(function(d) { return [d, "test"]; });
    })

  lineGroup
    .attr("stroke", function(d) {
      var company = d.type.slice(0, d.type.indexOf(' '));
      return color(company);
    })
    .selectAll("path")
    .attr("class", function(d) { return d[1]; })
    .attr("d", draw);
  
  lineGroup
    .on("mouseover", function(d) {
      // show train when click others
      d3.select(this).classed("active", true);
      lineGroup
        .filter(function(e) { return e.type !== d.type; })
        .style('opacity', 0.2);

      // add tooltip elements for all values
      drawTips(d, "train");
      drawTips(d, "test");
    })
    .on("mouseout", function(d) {
      d3.select(this).classed("active", false);
      lineGroup.style('opacity', null);
      
      svg.selectAll(".tooltip").remove();
    });

  function draw(d) {
    var data = d[0], type = d[1];
    var points = data[type + "Normalised"].map(function(v, i) {
      return [x(i + 1), y(v)];
    });
    points.unshift([x(0), categoryScale(data.type)]);
    return line(points);
  }
  
  function drawTips(data, type) {
    const newTips = svg.selectAll(".tooltip.tooltip-" + type)
      .data(data[type])
      .enter()
      .append("g")
      .attr("class", "tooltip tooltip-" + type)
      .attr("transform", function(d, i) {
        const v = data[type + "Normalised"][i];
        return "translate(" + [x(i +1), y(v)] + ")";
      });

    newTips.append("rect")
      .attr("width", 40)
      .attr("height", 16);
    
    newTips.append("text")
      .attr("dx", 4)
      .attr("dy", 8)
      .text(function(d) { return d; });
  }
}

parallel(processedData);
代码语言:javascript
复制
svg {
  font: 12px sans-serif;
}

.lineGroup path {
  fill: none;
}

.lineGroup.active .train {
  visibility: visible;
}

.train {
  visibility: hidden;
  stroke-dasharray: 5 5;
}

.axis line,
.axis path {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.tooltip-test rect {
  fill: #444;
}

.tooltip-train rect {
  fill: #888;
}

.tooltip text {
  dominant-baseline: middle;
  fill: white;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
<div id="parallel_coor"></div>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64823683

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档