当鼠标悬停在多折线图上时,将相同的线条颜色填充到圆圈中,并在鼠标移开时从圆圈中移除颜色

Fill same line color in to circle on Multi Line chart when mouse over and remove color from circle when mouse out

这里我在 D3.js 的多线图表中有 2 条不同颜色的线和圆圈 我想在鼠标悬停时将相同的颜色填充到圆圈中,并在鼠标移开时移除颜色。

填充颜色属性有效,但填充的颜色与相应的线条不同。

.on("mouseenter", function (event, d) {
    d3.selectAll("g.circle")
      .attr('class', 'quadrantBorder') //style with a custom class and CSS
       .style('stroke', 'red')
       .style('fill', (d, i) => colors(i));

    //alert('enter mouseenter')
    // Show the tooltip and position it correctly
    var x = xScaleTest(new Date(d.date));
    var y = yScaleTest(d.stock);
    console.log("This " +d3.select(this));
    d3.select(this).style("fill",(d,i) => colors(i));

var data = [{
  depotID: 123,
  depotName: "All Depots",
  materials: [{
      materialName: "M7824 (MSB0011359C) 600 mg",
      materialTypeID: 1234,
      materialStock: [{
          date: "2020-10-01",
          stock: 100
        },
        {
          date: "2020-11-01",
          stock: 200
        },
        {
          date: "2020-12-01",
          stock: 300
        },
        {
          date: "2021-01-01",
          stock: 400
        },
        {
          date: "2021-02-01",
          stock: 500
        },
        {
          date: "2021-03-01",
          stock: 600
        },
        {
          date: "2021-04-01",
          stock: 700
        },
        {
          date: "2021-05-01",
          stock: 800
        },
        {
          date: "2021-06-01",
          stock: 900
        },
        {
          date: "2021-07-01",
          stock: 1000
        },
        {
          date: "2021-08-01",
          stock: 1100
        },
        {
          date: "2021-09-01",
          stock: 1200
        },

      ]
    },
    {
      materialName: "M7824 (MSB0011359C) 500 mg",
      materialID: 1232,
      materialStock: [{
          date: "2020-10-01",
          stock: 200
        },
        {
          date: "2020-11-01",
          stock: 300
        },
        {
          date: "2020-12-01",
          stock: 400
        },
        {
          date: "2021-01-01",
          stock: 500
        },
        {
          date: "2021-02-01",
          stock: 560
        },
        {
          date: "2021-03-01",
          stock: 870
        },
        {
          date: "2021-04-01",
          stock: 800
        },
        {
          date: "2021-05-01",
          stock: 900
        },
        {
          date: "2021-06-01",
          stock: 1000
        },
        {
          date: "2021-07-01",
          stock: 1100
        },
        {
          date: "2021-08-01",
          stock: 1200
        },
        {
          date: "2021-09-01",
          stock: 1300
        },

      ]
    }
  ]
}]
let width = 900,
  height = 400,
  margin = 100;

var dates = [];
for (let obj of data[0].materials[0].materialStock) {
  dates.push(obj.date);
}

var domain = d3.extent(dates);
var newStartDate = new Date(domain[0]).setDate(new Date(domain[0]).getDate() - 15);
var newEndtDate = new Date(domain[1]).setDate(new Date(domain[1]).getDate() + 15);

var xScaleTest = d3.scaleTime()
  .domain([new Date(newStartDate), new Date(newEndtDate)])
  .range([0, width - margin * 2]);


var yScaleTest = d3.scaleLinear()
  .domain([0, d3.max(data[0].materials, function(d) {
    return d3.max(d.materialStock, function(d) {
      return d.stock;
    })
  })])
  .range([height - margin, 0]);

/* Add SVG */
var svg = d3.select("#xyAxes").append("svg")
  .attr("width", (width + margin) + "px")
  .attr("height", (height + margin) + "px")
  .attr("style", "outline: thin solid black;")
  .append('g')
  .attr("transform", `translate(${margin}, ${margin})`);

//Add Line
var line = d3.line()
  .x(function(d) {
    return xScaleTest(new Date(d.date))
  })
  .y(function(d) {
    return yScaleTest(d.stock)
  });

let lines = svg.append('g')
  .attr('class', 'lines');

var groups = lines.selectAll('.line-group')
  .data(data[0].materials).enter()
  .append('g');

var colors = d3.scaleOrdinal((d3.schemeCategory10));

//line
groups.append("path")
  .attr("d", function(d) {
    return line(d.materialStock)
  })
  .attr("fill", "none")
  .attr("stroke", (d, i) => colors(i))
  .style("stroke-dasharray", "5,5") //dashed array for line;

//dot on line
svg.selectAll("dot")
  .data(data[0].materials)
  .enter().append("g")
  .attr("fill", "none")
  .style("stroke", (d, i) => colors(i))
  .attr("class", "dot")
  .selectAll("dot")
  .data(function(d) {
    return d.materialStock;
  })
  .enter().append("circle")
  .attr("class", "circle")
  .attr("r", 4)
  .attr("cx", function(d) {
    return xScaleTest((new Date(d.date)));
  })
  .attr("cy", function(d) {
    return yScaleTest(d.stock);
  })
  .on("mouseover", function(d) {
    d3.select(this).style("fill", (d, i) => colors(i));
  })
  .on("mouseout", function() {
    d3.select(this).style("fill", "none");
  });

/* Add Axis into SVG */
var xAxis = d3.axisBottom(xScaleTest)
  .ticks(d3.timeMonth.every(1))
  .tickSizeOuter(0)
  .tickSizeInner(-height + margin)
  .tickFormat(d3.timeFormat("%b -%Y"));

var yAxis = d3.axisLeft(yScaleTest)
  .ticks(12)
  .tickSize(-width + margin + 100)

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", `translate(0, ${height-margin})`)
  .call(xAxis)
  .call(g => g.selectAll(".tick:first-of-type line")
    .attr("class", "axis_bar")
    .attr("stroke", "#BEBEBE"))
  .call(g => g.selectAll(".tick:not(:first-of-type) line")
    .attr("class", "axis_y_tick")
    .attr("stroke", "#E8E8E8"));


svg.append("g")
  .attr("class", "y axis")
  .call(yAxis)
  .call(g => g.selectAll(".tick:first-of-type line")
    .attr("class", "axis_bar")
    .attr("stroke", "black"))
  .call(g => g.selectAll(".tick:not(:first-of-type) line")
    .attr("class", "axis_y_tick")
    .attr("stroke", "#E8E8E8"));
svg {
  font-family: Sans-Serif, Arial;
}

.line {
  stroke-width: 2;
  fill: none;
}

.text {
  font-size: 12px;
}

text.title {
  font-family: Arial, Helvetica, sans-serif;
  font-weight: bold;
  font-size: 14px;
  color: #353535;
  ;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="xyAxes"></div>

i 可能意味着不同的事情。它只是一个迭代器。当你画线时,你 selectAll(".dot"),每行给你一组。当你运行d3.select(this)时,你只select一件事,那意味着i永远是零。

要解决此问题,请在绘制点时将颜色作为 属性 添加到点中。 或者,您可以使用 materialNamematerialTypeID 作为标识符而不是数字。然后,您将 materialName 作为 属性 添加到所有圆圈,您可以从那里为它们着色:

var data = [{
  depotID: 123,
  depotName: "All Depots",
  materials: [{
      materialName: "M7824 (MSB0011359C) 600 mg",
      materialTypeID: 1234,
      materialStock: [{
          date: "2020-10-01",
          stock: 100
        },
        {
          date: "2020-11-01",
          stock: 200
        },
        {
          date: "2020-12-01",
          stock: 300
        },
        {
          date: "2021-01-01",
          stock: 400
        },
        {
          date: "2021-02-01",
          stock: 500
        },
        {
          date: "2021-03-01",
          stock: 600
        },
        {
          date: "2021-04-01",
          stock: 700
        },
        {
          date: "2021-05-01",
          stock: 800
        },
        {
          date: "2021-06-01",
          stock: 900
        },
        {
          date: "2021-07-01",
          stock: 1000
        },
        {
          date: "2021-08-01",
          stock: 1100
        },
        {
          date: "2021-09-01",
          stock: 1200
        },

      ]
    },
    {
      materialName: "M7824 (MSB0011359C) 500 mg",
      materialID: 1232,
      materialStock: [{
          date: "2020-10-01",
          stock: 200
        },
        {
          date: "2020-11-01",
          stock: 300
        },
        {
          date: "2020-12-01",
          stock: 400
        },
        {
          date: "2021-01-01",
          stock: 500
        },
        {
          date: "2021-02-01",
          stock: 560
        },
        {
          date: "2021-03-01",
          stock: 870
        },
        {
          date: "2021-04-01",
          stock: 800
        },
        {
          date: "2021-05-01",
          stock: 900
        },
        {
          date: "2021-06-01",
          stock: 1000
        },
        {
          date: "2021-07-01",
          stock: 1100
        },
        {
          date: "2021-08-01",
          stock: 1200
        },
        {
          date: "2021-09-01",
          stock: 1300
        },

      ]
    }
  ]
}]
let width = 900,
  height = 400,
  margin = 100;

var dates = [];
for (let obj of data[0].materials[0].materialStock) {
  dates.push(obj.date);
}

var domain = d3.extent(dates);
var newStartDate = new Date(domain[0]).setDate(new Date(domain[0]).getDate() - 15);
var newEndtDate = new Date(domain[1]).setDate(new Date(domain[1]).getDate() + 15);

var xScaleTest = d3.scaleTime()
  .domain([new Date(newStartDate), new Date(newEndtDate)])
  .range([0, width - margin * 2]);


var yScaleTest = d3.scaleLinear()
  .domain([0, d3.max(data[0].materials, function(d) {
    return d3.max(d.materialStock, function(d) {
      return d.stock;
    })
  })])
  .range([height - margin, 0]);

/* Add SVG */
var svg = d3.select("#xyAxes").append("svg")
  .attr("width", (width + margin) + "px")
  .attr("height", (height + margin) + "px")
  .attr("style", "outline: thin solid black;")
  .append('g')
  .attr("transform", `translate(${margin}, ${margin})`);

//Add Line
var line = d3.line()
  .x(function(d) {
    return xScaleTest(new Date(d.date))
  })
  .y(function(d) {
    return yScaleTest(d.stock)
  });

let lines = svg.append('g')
  .attr('class', 'lines');

var groups = lines.selectAll('.line-group')
  .data(data[0].materials).enter()
  .append('g');

var colors = d3.scaleOrdinal((d3.schemeCategory10))
  .domain(data[0].materials.map(function(d) {
    return d.materialName;
  }));

//line
groups.append("path")
  .attr("d", function(d) {
    return line(d.materialStock)
  })
  .attr("fill", "none")
  .attr("stroke", (d, i) => colors(i))
  .style("stroke-dasharray", "5,5") //dashed array for line;

//dot on line
svg.selectAll("dot")
  .data(data[0].materials)
  .enter()
  .append("g")
  .attr("fill", "none")
  .style("stroke", (d) => colors(d.materialName))
  .attr("class", "dot")
  .selectAll("dot")
  .data(function(d) {
    d.materialStock.forEach(function(v) {
      v.materialName = d.materialName;
    });
    return d.materialStock;
  })
  .enter().append("circle")
  .attr("class", "circle")
  .attr("r", 4)
  .attr("cx", function(d) {
    return xScaleTest((new Date(d.date)));
  })
  .attr("cy", function(d) {
    return yScaleTest(d.stock);
  })
  .on("mouseover", function(d) {
    d3.select(this).style("fill", colors(d.materialName));
  })
  .on("mouseout", function() {
    d3.select(this).style("fill", "none");
  });

/* Add Axis into SVG */
var xAxis = d3.axisBottom(xScaleTest)
  .ticks(d3.timeMonth.every(1))
  .tickSizeOuter(0)
  .tickSizeInner(-height + margin)
  .tickFormat(d3.timeFormat("%b -%Y"));

var yAxis = d3.axisLeft(yScaleTest)
  .ticks(12)
  .tickSize(-width + margin + 100)

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", `translate(0, ${height-margin})`)
  .call(xAxis)
  .call(g => g.selectAll(".tick:first-of-type line")
    .attr("class", "axis_bar")
    .attr("stroke", "#BEBEBE"))
  .call(g => g.selectAll(".tick:not(:first-of-type) line")
    .attr("class", "axis_y_tick")
    .attr("stroke", "#E8E8E8"));


svg.append("g")
  .attr("class", "y axis")
  .call(yAxis)
  .call(g => g.selectAll(".tick:first-of-type line")
    .attr("class", "axis_bar")
    .attr("stroke", "black"))
  .call(g => g.selectAll(".tick:not(:first-of-type) line")
    .attr("class", "axis_y_tick")
    .attr("stroke", "#E8E8E8"));
svg {
  font-family: Sans-Serif, Arial;
}

.line {
  stroke-width: 2;
  fill: none;
}

.text {
  font-size: 12px;
}

text.title {
  font-family: Arial, Helvetica, sans-serif;
  font-weight: bold;
  font-size: 14px;
  color: #353535;
  ;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="xyAxes"></div>