markmarkoh / datamaps

Customizable SVG map visualizations for the web in a single Javascript file using D3.js
http://datamaps.github.io
MIT License
3.78k stars 1.01k forks source link

Mouseout breaks some click functionality #231

Open dmachat opened 9 years ago

dmachat commented 9 years ago

This is related to #191 (and another issue in angular-datamaps). When attempting to update the fill for a particular geography by clicking a geography and using updateChoropleth, the new color only persists until mouseout, when it reverts back to the value from data-previousAttributes. I've created a gist to demonstrate (http://bl.ocks.org/dmachat/b75a5a01cfb31cf92cf5/af5ce473d5ab0e96627775b374e8546f434c8cd6). Would be happy to take a swing at a fix eventually, but wanted to document and get any possible thoughts on the bug at this point.

markmarkoh commented 9 years ago

Yes, this is definitely a bug. They say "never store state in the DOM", but for this piece of functionality I did exactly that and bam, a bug appears.

Using data-previousAttributes might have to go away. Perhaps we could use a quick lookup to see what base color a geography is supposed to be (preferably the same lookup call that originally sets the color).

So the flow for painting would be:

  1. lookupFillColor(geo.id)
  2. on('mouseenter', (geo) => { lookupHighlightFillColor() }
  3. on('mouseexit', (geo) => { lookupFillColor(geo.id)}

Currently lookupFillColor in step 3 is parse(data-previousAttributes).fillColor, which leads to this bug.

lucaspiller commented 8 years ago

I also had this issue and solved it with CSS, and it works fine for me. I don't understand why JavaScript is used for highlighting / colouring.

Set this flag when initializing the map:

geographyConfig: {
  highlightOnHover: false
}

CSS:

#map path:hover { /* on mouse over */
  fill: #375682 !important;
}

#map path.active { /* on click */
  fill: #375682 !important;
}
getup8 commented 8 years ago

@lucaspiller Thanks for the work around. One issue though is that I think that only really works if your hover and clicked colors are the same. Is that right?

@markmarkoh Are you considering taking a different approach on this? Any fix in the works?

getup8 commented 8 years ago

Sorry, think I misinterpreted your code, I thought it was path:active.

Doing something like this works well.

Function assigned to done:

function handleDataMapClick(datamap) {
  datamap.svg.selectAll('.datamaps-subunit').on('click', function(geography) {
    this.classList.add('activePath');
  });
}

CSS

path:hover {
    fill: rgba(230, 230, 230, 0.4) !important;
}
path.activePath {
    fill: #3f9fb4 !important;
}
adg29 commented 8 years ago

Thx for clarifying that data-previousAttributes causes this state conflict @markmarkoh.

I'll disable highlightOnHover and use CSS for highlighting on hover, as suggested by @lucaspiller. I'm working on zoom to bounding box functionality based on work by @esphen

Anyway, if there is any progress on replacing the functionality covered by data-previousAttributes let us know here!