GithubHelp home page GithubHelp logo

dc-js / dc.leaflet.js Goto Github PK

View Code? Open in Web Editor NEW

This project forked from yurukov/dc.leaflet.js

52.0 7.0 24.0 2.01 MB

DC charts using Leaflet maps

License: Apache License 2.0

JavaScript 96.43% HTML 1.41% CSS 2.16%
crossfilter maps leaflet

dc.leaflet.js's Introduction

dc.leaflet.js

This library provides support for DC.js charts in a Leaflet.js map. It is a fork of Boyan Yurukov's dc.js extension, upgraded to a full library with AMD support and updated for dc.js 2.0+.

Note: this repo is archived (read-only). If you are interested in maintaining the library, contact Gordon by email, or feel free to fork! Please see #44 for discussion.

Demo

Examples of each of the charts can be found here: http://dc-js.github.io/dc.leaflet.js/

Requirements

(These will be installed by npm install)

The charts should work with older versions with minor changes.

Usage

There are three charts currently implemented - marker, choropleth, and bubble. They extend the base abstract leaflet chart. Both support selection of datapoints and update in real time. Styling and map options can be set directly to the map object and though functions in the chart. Check the Leaflet reference for more information on the specific map, marker and geojson options. Location can be set as either 'lat,lng' string or as an array [lat,lng].

Leaflet base

Properties included in all dc_leaflet charts. Derives from dc.baseMixin and dc.marginMixin. This is a base class/mixin and can't be instantiated directly.

dc_leaflet.leafletBase = function(chart)
  .mapOptions({..})       - set leaflet specific options to the map object; Default: Leaflet default options
  .center([1.1,1.1])      - get or set initial location
  .zoom(7)                - get or set initial zoom level
  .map()                  - set or get map object
  .brushOn(true)          - if the map should select datapoints; Default: true
  .popupMod('alt')        - only display popup when 'alt' modifier key (or 'shift' or 'ctrlCmd') is pressed;
                            Default: null, no modifier key
  .filterMod('ctrlMod')   - only filter when control key (command key on Mac) is pressed
                            Default: null, no modifier key

Marker chart

Each group is presented as one marker on the map. Includes all properties from leafletBase, and:

dc_leaflet.markerChart(parent, chartGroup)
  .locationAccessor()     - function (d) to access the property indicating the latlng (string or array); Default: use keyAccessor
  .marker()               - set function(d, map) to build the marker object. Default: standard Leaflet marker is built
  .icon()                 - function(d, map) to build an icon object. Default: L.Icon.Default
  .popup()                - function(d, marker) to return the string or DOM content of a popup
  .renderPopup(true)      - get or set if popups should be shown; Default: true
  .cluster(false)         - get or set if markers should be clustered. Requires leaflet.markercluster.js; Default: false
  .clusterOptions({..})   - options for the markerCluster object
  .rebuildMarkers(false)  - set if all markers should be rebuild each time the map is redrawn. Degrades performance; Default: false
  .filterByArea(false)    - if the map should filter data based on the markers inside the zoomed in area instead of the user clicking on individual markers; Default: false
  .markerGroup()          - get the Leaflet group object containing all shown markers (regular group or cluster)
  .featureGroup()         - get or set featureGroup that will be used for fit on render or redraw
  .clickEvent()           - get or set the event to fire when a marker is clicked
  .fitOnRender()          - get or set a bool to determine whether to fit to bounds when markers are rendered
  .fitOnRedraw()          - get or set a bool to determine whether to fit to bounds on crossfilter redraw
  .showMarkerTitle()      - get or set a bool to determine whether title and alt should be shown for markers

Choropleth chart

Each group is mapped to an feature on the map. Includes all properties from leafletBase, and:

dc_leaflet.choroplethChart(parent, chartGroup)
  .geojson()              - get or set geojson object describing the features
  .featureOptions()       - object or a function(feature) to set the options for each feature
  .featureKeyAccessor()   - function(feature) to return a feature property that would be compared to the group key; Default: feature.properties.key
  .featureStyle()         - get or set the function(feature) to return style options for L.geoJson. Probably not helpful to override this, but it's possible. Default: use featureOptions, data, color, selection status to define the style; see source for details.
  .popup()                - function(d, feature) to return the string or DOM content of a popup
  .renderPopup(true)      - get or set if popups should be shown; Default: true

Bubble chart

Each group is mapped to a circle on the map. Includes all properties from leafletBase, and:

dc_leaflet.bubbleChart(parent, chartGroup)
  .r()                    - radius scale, used to convert value returned by valueAccessor(d) to pixels. Default: d3.scale.linear().domain([0, 100])
  .locationAccessor()     - function(d) to access the property indicating the latlng (string or array); Default: use keyAccessor
  .selectedColor()        - get or set the (constant) selected bubble color
  .unselectedColor()      - get or set the unselected bubble color, which by default passes the datum to dc.ColorMixin's getColor function to dynamically color bubbles (defaults to gray unless .colors(), .colorDomain() and .colorAccessor() are defined)
  .popup()                - function(d, marker) to return the string or DOM content of a popup
  .renderPopup()          - get or set if popups should be shown on mouseover; Default: true
  .layerGroup()           - get the layerGroup for the bubbles
  .marker()               - get or set function(d, map) to build the marker object. Probably not helpful to override this, but its's possible. Default: create L.circleMarker based on the other parameters; see source for details.

dc.leaflet.js's People

Contributors

alan-unravel avatar doshisunny avatar gordonwoodhull avatar katirg avatar mheisoku avatar monostop avatar tayden avatar yurukov avatar zephschafer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

dc.leaflet.js's Issues

initialization of parameters that may have been set by createLeaflet

Simon Johnson writes:

I haven't had a chance to try this particular version of the extension as I used my tweaked version as under time pressure. I did, however, use the same method of createLeaflet customization point. My feedback on this is that it needs to include the creation/adding of tiles and setting the zoom as these could already be set when the map has been created before DC is used.

Heat Map Functionality

I am a big fan of dc.js, but realized that it doesn't support heatmaps for leaflet, which my company would love to use. Is there any plans to add that? I know leaflet supports it natively, so hopefully getting it to connect to crossfilter is doable.

Issue while importing module

I am having issue with importing dc.leaflet while importing it.
const dcLeaflet = require('dc.leaflet');
gives me error unable to resolve path module
Currently I am able to resolve it by adding index.js in dc.leaflet inside node_module directory with following.

dc = require("dc");
leaflet = require('leaflet');
leaflet.markercluster = require('leaflet.markercluster');
crossfilter = require("crossfilter2");
module.exports = require("./dc.leaflet");

This is something we can not do with application deployment.
Do you have any alternative or better suggestion to so?

LeafletMarkerChart hangs when popup moves chart 2 times

From @thebarbarian on January 17, 2017 8:7

I am not sure if it's a bug or my terrible JS-coding, please remove this if i messed up.

When displaying a LeafletMarkerChart and clicking a marker on the edge of the map, the creation of the textballoon will move the map slighly until it fits inside the frame. If i do this two times, i'm unable to drag the map. It's stuck.
The console gave me the following error after the map is stuck and i click a marker:

_markerList.indexOf is not a function(…)

After changing line 583 of dc-leaflet.js :

(_markerList.indexOf(_chart.filter()) !== -1 &&

into this:

(_markerList.toString().indexOf(_chart.filter()) !== -1 &&

the problem is solved. Adding the toString()-method doesn't seem to affect any of the other graphs on my dashboard.

My apologies if this isn't a bug, but it seemed to make sense to let the developers know.

Copied from original issue: dc-js/dc.js#1263

The popup in Choropleth doesn't work

In dc.leaflet version 0.2.3 for the Choropleth Chart the popup doesn't work or it doesn't get rendered. Am I wrong or it happens to anybody else? I will be happy to fix that but I would need some help.

      .renderPopup(true)
      .popup(function(d,feature) {
        return feature.properties.name+" : "+d.value;
      });

Anyway, any help would be really appreciated

encode data by color in bubbleChart

Currently the color is used to encode the selection status.

But sometimes it's nice to encode some other property using color.

I'm not sure we want to go as way-out as dc.graph.js, where attributes are cascaded, and selection can set arbitrary properties. But maybe this could be more flexible.

color accessor and color scale for bubbleChart

Currently it's selectedColor and unselectedColor, which is limiting - should be data-driven.

Could follow dc.scatterPlot or dc.bubbleChart or could even follow dc.graph and have cascading data-driven styles...

Seeking new maintainers

Gordon Woodhull is stepping down from maintaining dc.leaflet.js at the end of 2022.

He may occasionally respond on Stack Overflow or on GitHub Issues, but will no longer maintain or contribute to the project.

We are seeking new maintainers for dc.leaflet.js. (Deepak Kumar @kum-deepak will maintain dc.js, and he's also seeking new maintainers to help on that project; see dc-js/dc.js#1868)

There is a lot that could be improved with dc.leaflet.js, such as:

  • factoring it in ES6 mdoules
  • updating it to latest Leaflet
  • adding features and visual encodings

If you're interested in helping, please reach out here or via email.

A note regarding the dimension creation of markerChart

I have now spent 4 or 5 days, figuring out (two times) how you have to create the geo dimension to make it work with markerChart. I thought that the geo attribute of my data object has to look like this:

{ geo: {lat: 23.2323, lng:34.2323}}

The solution is that the object you give the dimension a geo object on your data object that is formatted like this:

geo: "343.34343, 34.23232"

BUT! This alone still does not make the graph show the map markers. You ALSO need to have a lat and a lng attribute on your data object. So completely your data object has to look like this:

[... , {geo: "34.34343, 23.2323", lat: 34.34343, lng: 23.2323, value: 5000}, ... ]

THEN the markers show up on the map, in this case showing the grouped data for the attribute value. Note, that lat and lng have to be Numbers and geo has to be a String!

I believe this should be noted in the documentation somewhere, because it just drove me nuts for the second time now, because of course I forgot how to fix it.

Colors mixin weird behaviour

If a featureOptions are defined via anonymous function for a choropleth map before defining colors and colorAccessor, you get unexpected behaviour. eg:

  var mapDimension = birds.dimension(function(i) { return i.island; });
  var mapGroup = mapDimension.group()
      .reduce(speciesDictAdd, speciesDictRemove, speciesDictInit);
  var mapColors = d3.scale.ordinal()
    .domain(d3.extent(mapGroup.all(), function(g) {
       return d3.keys(g.value).length;
    }))
    .range(['#fef0d9', '#fdd49e', '#fdbb84', '#fc8d59',
              '#ef6548', '#d7301f', '#990000']);
  mapChart
    .width($('#map .box-body').width())
    .height(500)
    .mapOptions({scrollWheelZoom: false})
    .center([51.86, -128.28])
    .zoom(10)
    .dimension(mapDimension)
    .group(mapGroup)
    .geojson(islandData)
    .featureKeyAccessor(function(d) { return d.properties.island;})
    .featureOptions(function(d) {
        console.log(mapColors.domain());  // <<<<<<<<<<<<<<< Domain is not consistent here
        var map = d3.map(mapGroup.top(Infinity), function(d) { return d.key; });
        var grp = map.get(d.properties.island);
        var species = grp ? d3.keys(grp.value).length : -1;
        return {
          stroke: species > 0,
          fillOpacity: 0.7,
          opacity: 0.7,
          color: grp ? mapColors(species) : null
        };
    })
    .colors(mapColors)
    .colorAccessor(function(d) { return d3.keys(d.value).length; })
    .renderPopup(false);

This is due to the color domain being redefined by the dc color mixin. The above code attempts to set the stroke of each polygon equal to the same color as the polygon fill. However, because The colorAccessor is trying to redefine the domain (which is already defined), the stroke colors end up being off.

To fix this, you can define the featureOptions function after colors, and everything works as expected.

gray-out colors?

In the dc charts (not dc leaflet), when selecting a group, the other groups get grayed-out. (tested with the bubbleChart)

Would this also be desired behavior for the dc leaflet maps?

Reset all

When executing a "reset all"..

<a href="javascript:dc.renderAll(); dc.redrawAll()">Reset all</a>

.. the layer of circles on a bubbleChart get stacked on top of each other.

It seems like the old layer first has to be removed.

composite leaflet chart

Someone could fairly easily implement a composite leaflet chart - it wouldn't share any code with (dc.compositeChart)[https://github.com/dc-js/dc.js/blob/develop/web/docs/api-latest.md#dc.compositeChart] and very little interface, but the same concept of the composite chart owning the leaflet instance and the children drawing layers within it.

Change basemap before map rendered?

Is it possible to change the basemap tiles before calling render on the map? Defining the base map tile layer under layers in the .mapOptions accessor doesn't seem to work and results in a blank map with no basemap or geojson data.

Broken demo

The demo doesn't render the maps properly and is complaining about the deprecated renderlet method. I'm also having trouble with getting the maps to render. Is the library working with dc 2.0.0-beta.19?

Edit: It seems that the problem is with width being properly set on the div.dc-leaflet.leaflet-container element and its child divs

Second render does not reinitialize Leaflet

Originally the code attempted to apply Leaflet twice to the div, resulting in the error

map container is already initialized

#14 fixes the error - are there circumstances where we do need to completely reinitialize Leaflet? In dc.js this is usually a punt where there is code that can't gracefully transform/transition from one kind of data to another.

support other layout backends

It would be great to support other layout algorithms such as

In terms of the model and parameters, cola is probably the most complicated, so this may be a matter of moving general stuff to base classes and creating a hierarchy of layouts. Constraints is something no other layout algo has, afaik.

Obviously the parameters that affect layout will all be applied differently, so there's some kind of generator. But the parameters that just affect drawing parameters may be shared somewhat.

move brushOn to leafletBase

I've documented it as part of the base, but actually it's implemented on each chart separately.

Easy to fix but needs a little testing.

D3-bind svg elements after Leaflet creates them?

As reported here, d3.tip and other d3 stuff won't work on the shapes in dc.leaflet because the data isn't bound:

http://stackoverflow.com/questions/31790830/d-undefined-for-d3-tip-tooltip-with-dc-leafletchoroplethchart

Since leaflet is creating the svg elements, not d3, the data is not attached and dc.leaflet.js is internally keeping a _dataMap to specify colors etc.

Could we bind those elements post hoc? Or is this dangerous?

Does leaflet have its own notion of data binding?

Upgrading leaflet versions

Is it possible to update leaflet version to 1.0.2 and leaflet.markercluster to 1.0.0 ?
These are the latest versions of leaflet.
I am planning use in new app and just wanted to start with newer versions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.