auto
auto

Reputation: 1153

D3: Highlighting Parts of Path on Mouseover in Line Graph

I am wondering if it is possible to have a d3 line graph in which a draggable window highlights or changes the color of only the parts of a line (path) that are in the window.

Here is an image that exemplifies the use case

I can alter the entire line or break the line up into parts, but I'm wondering if it is possible to simply alter each point on the path that is in the window.

How would I be able to access the points in the path in order to alter them? From there I think I would be able to alter them. it's a matter of grabbing their attributes.

Upvotes: 1

Views: 1045

Answers (2)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

What you have in your image is not a window that changes the path's colour. That is just a regular rectangle with an opacity smaller than 1.

However, I'd like to drop my two cents mentioning something that is normally ignored: mix-blend-mode.

It's very difficult getting the exact colours you want to change with mix-blend-mode, but it is a funny feature and, the most important, you don't have to break the path.

Have a look at this demo, dragging the rectangular "window". It highlights the green path turning it into a red path:

var data = d3.range(50).map(() => [Math.random() * 300, Math.random() * 150]);

var svg = d3.select("svg");
var path = svg.append("path")
  .attr("d", d3.line().curve(d3.curveBasis)(data))
  .style("stroke", "green")
  .style("stroke-width", "3px")
  .style("fill", "none");

var backRect = svg.append("rect")
  .datum({
    x: 100,
    y: 50
  })
  .attr("x", d => d.x)
  .attr("y", d => d.y)
  .attr("width", 60)
  .attr("height", 40)
  .style("fill", "none")
  .style("stroke", "black");

var rect = svg.append("rect")
  .datum({
    x: 100,
    y: 50
  })
  .attr("x", d => d.x)
  .attr("y", d => d.y)
  .attr("width", 60)
  .attr("height", 40)
  .attr("cursor", "pointer")
  .style("fill", "red")
  .style("mix-blend-mode", "hue")
  .call(d3.drag().on("drag", function(d) {
    rect.attr("x", d.x = d3.event.x)
      .attr("y", d.y = d3.event.y);
    backRect.attr("x", d.x = d3.event.x)
      .attr("y", d.y = d3.event.y)
  }))
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

Upvotes: 1

Matjaž Drolc
Matjaž Drolc

Reputation: 386

  1. Render whole path twice, once normal and once highlighted
  2. Use clip-path on the highlighted version
  3. Dynamically change used clipPath to be in the shape of highlighted rectangle.

Upvotes: 2

Related Questions