Is it possible to have layered svg elements that interact with each other in d3?

StackOverflow https://stackoverflow.com/questions/8854665

  •  28-10-2019
  •  | 
  •  

سؤال

I have a bar graph that is basically a navigational element, so I need easy predictable rollover behavior over the bars. Essentially I need to make sure that the small bars are as easily clicked on as the big ones, so I've made the entire column a clickable rollover.

Here is an example of the behavior I am referring to:

screenshot http://img6.imageshack.us/img6/6674/screengraph.png

I'd tried to do this with d3 and svg, but found that it was difficult to manage the z-indexes between svg elements and divs (or svg elements and other svg elements, honestly I forget the exact nature of where this was a sticking point). But I remember concluding that the only effective way to make what I was looking for happen was to have each column be 3 separate svg elements, essentially a top background, the bar, and then a bottom background, and to manually fire all 3 items to show the rollover change whenever one of them is hovered over.

I eventually just ditched svg and ended up using all divs just using d3 for the scale methods and drawing everything by hand using knockout.js templates. But now I'm looking at 200 lines of refactored javascript and I'm wondering if perhaps d3 would have given me a cleaner solution. Was I missing anything in d3 that could have accomplished what I am looking for easily?

هل كانت مفيدة؟

المحلول

Good on you for making the columns easily hoverable! The technique I would use for this is an invisible overlay with pointer-events: all, and optionally assigning the mouseover listener to a parent svg:g element rather than one of the rects.

The structure for each bar would look like this:

<g class="bar" transform="translate(0,…)">
  <rect class="green"></rect>
  <rect class="overlay"></rect>
</g>

(You probably have other things you might want to add, like the highlighted "14" in your screenshot, which you implement as another rect with rounded corners and a text element.)

The overlay rect is the full-height of the chart (70px, in your example). It has the following style:

.overlay {
  fill: none;
  pointer-events: all;
}

The green rect is just the height of the bar, and offset vertically so the bottom of the bar is at y=0. Same deal for the red negative rects.

In a nutshell, the invisible rect with pointer-events all receives all of the pointer-events for that bar. So you can use :hover styles on the parent g elements, say tweaking the bar color on hover:

.bar:hover .green {
  fill: lightgreen;
}

Likewise, you can register "mouseover" and "mouseout" events on the parent g element, or the overlay rect.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top