ramnathv / rMaps

Interactive Maps from R
http://rmaps.github.io
388 stars 194 forks source link

Use several GeometryCollections #28

Open joelgombin opened 10 years ago

joelgombin commented 10 years ago

Hi,

suppose I have a custom TopoJSON with several GeometryCollections objects in it (something similar to this D3 example : http://bl.ocks.org/mbostock/4090848). Is it possible, while using only one layer to make a choropleth map, to plot other layers, with different styles? More generally, is it possible to use custom CSS bits inside rMaps with Datamaps?

ramnathv commented 10 years ago

Yes. It should be possible. Can you provide a more concrete example so that I can understand what you are looking for?

joelgombin commented 10 years ago

Yes. Suppose I have this TopoJSON: http://joelgombin.fr/cartes/comm.couleur.json, which has two layers: comm.couleur and dept, and this data: http://joelgombin.fr/data/couleur.pol.Rdata. My script is here: https://gist.github.com/joelgombin/6bd5159107383ae460cd.

So at the moment I use the comm.couleur layer to plot the data, but I also would like to plot the dept layer for decoration (without any data to map as choropleth). I guess I just need to add a few javascript lines, but I'm not sure how exactly.

ramnathv commented 10 years ago

I am beginning to understand your question. How would you want to display this layer? DataMaps has an elaborate plugin system that should make this possible. I am copying @markmarkoh, the author of datamaps on this thread, since he will have more insights on how this can be done. Once, we figure out how to do it in DataMaps, I can work on creating the bindings in rCharts to support it.

joelgombin commented 10 years ago

I indeed realised this is actually more of a datamaps question than a rMaps question - but I'm a complete JS noob. I guess achieving something as in http://bl.ocks.org/mbostock/4090848 would be great!

ramnathv commented 10 years ago

Anything d3 does with maps, datamaps should be able to do, since it wraps d3. @markmarkoh will be able to provide more insightful comments :smile:

markmarkoh commented 10 years ago

but I also would like to plot the dept layer for decoration (without any data to map as choropleth).

So you just want to add the dept layer on top of the comm-couler layer? I can see if I can whip up a quick plugin that might do that for you.

If you want dept to respect fillKeys it might be a bit trickier.

joelgombin commented 10 years ago

No, you got it right. Only one choropleth layer, with additional layers to get a more readable/pretty map.

markmarkoh commented 10 years ago

I made a small change to the library to save off the custom fetched topojson.

Here is a quick plugin I wrote just for your purposes:

http://jsbin.com/uPOyuJU/460/edit

I named it dept just to be clear this isn't a one-size-fits-all solution, but as you can see the dept layer is drawn in the background. You can style it with CSS (also in the example).

I don't know how plugins work with rMaps, but I hope this satisfies the datamaps dependency.

ramnathv commented 10 years ago

This is really slick @markmarkoh . I haven't included support for datamaps plugins as yet, but it should be simple, since I will just piggyback on your spec and make the user write a javascript function.

markmarkoh commented 10 years ago

Thinking about it a little more, this doesn't need to be a plugin (it actually bypasses the new layer anyways since in this case, the layer should be on the bottom).

Here is a simplified version that just uses done: http://jsbin.com/uPOyuJU/462/edit?html,output

ramnathv commented 10 years ago

That looks even better and in fact is easy to do with rMaps under the current setup, since you can simply pass done as a js function. Thanks @markmarkoh for adding this, datamaps truly rocks!

joelgombin commented 10 years ago

Thanks a lot @markmarkoh, that looks amazing! @ramnathv, I'm not quite sure how to add the function to my rCharts object. I tried

d1$setTemplate(chartDiv = '
      <style>
        .land {
          fill: rgba(240, 175, 10, 0.5) ;
          stroke-width: 0.5px;
          stroke: #f0af0a !important;
          pointer-events: none;
        }
      </style>    
      <script>
               done: function(datamap) {
                datamap.svg.insert("path", ".datamaps-subunits")
                  .datum(topojson.feature(datamap.customTopo, datamap.customTopo.objects.dept))
                  .attr("class", "land")
                  .attr("d", datamap.path)
        }
      </script>'
)

but it doesn't seem to have any effect. I cant' even see it in the structure of the d1 object. Any thaught?

ramnathv commented 10 years ago

Here is how I think it can be made to work.

First add the done function to the payload. The "#! .. !#" markup is to tell rCharts to pass this as a javascript object and not as JSON (in which case it will merely be a string).

d1$set(done = "#! function(datamap) {
  datamap.svg.insert('path', '.datamaps-subunits')
    .datum(topojson.feature(datamap.customTopo, datamap.customTopo.objects.dept))
    .attr('class', 'land')
    .attr('d', datamap.path)
} !#")

To pass the style, you can use the afterScript partial. It adds this code as-is after the chart javascript.

d1$setTemplate(afterScript = "
  <style>
    .land {
      fill: rgba(240, 175, 10, 0.5) ;
      stroke-width: 0.5px;
      stroke: #f0af0a !important;
      pointer-events: none;
    }
  </style>"
)

I have not tested this, but I think it should work. Let me know if you face any issues.

joelgombin commented 10 years ago

The javascript works fine, but the afterScript part doesn't seem to work. I can see it in the d1 object, but not in the html source code.

Another thing: I need to modify the call to the Datamaps library, to use @markmarkoh's change. Is there any way to do it through rMaps (or should I wait for the change we discusses in another thread)? At the moment I just change it by hand in the html source.

ramnathv commented 10 years ago

If you can wait, I will update the DataMaps binding in rCharts based on the changes made by @markmarkoh.