Commit aea74d78 authored by S Anand's avatar S Anand
Browse files

ENH: MapViewer supports TopoJSON. Fixes #70

parent 5fd9effa
Pipeline #64975 passed with stage
in 2 minutes and 6 seconds
......@@ -1293,10 +1293,10 @@ Drilldown feature example:
- `url`: String
- `data`: An array of objects. data: takes preference over url.
- `options`: supports same options as [GeoJSON options](http://leafletjs.com/reference-1.3.0.html#geojson-style)
- `link`: adds attributes from input dataset to geojson
- `link`: adds attributes from input dataset to geojson/topojson
- `url` is url (String) to fetch data
- `mapKey` is attribute name in geojson to match
- `dataKey` is column name in input dataset that matches with geojson `mapKey`
- `mapKey` is attribute name in geojson/topojson to match
- `dataKey` is column name in input dataset that matches with geojson/topojson `mapKey`
- `attrs` Data driven styles. same as `options`. (`attrs` take priority over `options`)
- For `color`, `weight`, `opacity`, `fillColor`, `fillOpacity` properties, the options are:.
- `metric` string / function
......@@ -1310,7 +1310,7 @@ Drilldown feature example:
- function(properties) must return a string. feature properties are passed as argument.
- TODO: the properties currently include only geoJSON properties. link properties must be added
- `tooltipOptions`: An object with properties and values from [leaflet tooltip options](https://leafletjs.com/reference-1.3.0.html#tooltip-option)
- `topojson` - same as `Geojson`
- `topojson` - same as `geojson`
- `marker` layer MUST have a data as an array of objects or else MUST have a url (string).
- `url`: String
- `data`: An array of objects. data: takes preference over url.
......
......@@ -126,25 +126,28 @@ MapViewer.prototype._saveLayer = function (layerName, layer) {
}
}
MapViewer.prototype.mergeData = function (mapJSON, dataTable, mapKey, dataKey) {
var dataTableIndex = {}
dataTable.forEach(function (row) {
var prop = typeof (row[dataKey]) == 'string' ? row[dataKey].toLowerCase() : row[dataKey]
dataTableIndex[prop] = row
})
function _merge_features(feature) {
var prop = typeof (feature.properties[mapKey]) == 'string' ? feature.properties[mapKey].toLowerCase() : feature.properties[mapKey]
var row = dataTableIndex[prop]
for (let key in row)
feature.properties[key] = row[key]
}
switch (mapJSON.type) {
case 'Feature':
case 'FeatureCollection':
mapJSON.features.map(function (feature) {
var prop = typeof (feature.properties[mapKey]) == 'string' ? feature.properties[mapKey].toLowerCase() : feature.properties[mapKey]
var row = dataTableIndex[prop]
for (let key in row) {
feature.properties[key] = row[key]
}
})
// returning mapJSON to write unit testcases for mergeData
mapJSON.features.map(_merge_features)
return mapJSON
case 'Topology':
mapJSON.objects[Object.keys(mapJSON.objects)[0]].geometries.map(_merge_features)
return mapJSON
break
default:
mapJSON.map(function (json) {
var row = dataTableIndex[json[mapKey]]
......@@ -153,7 +156,6 @@ MapViewer.prototype.mergeData = function (mapJSON, dataTable, mapKey, dataKey) {
}
})
return mapJSON
break
}
}
......@@ -349,7 +351,7 @@ MapViewer.prototype.drilldown_recursive = function (currentLayer) {
}
if (typeof (nextLayer.layerOptions.data) == 'function') {
nextLayer.layerOptions.data = nextLayer.layerOptions.tata(sublayer.feature.properties)
nextLayer.layerOptions.data = nextLayer.layerOptions.data(sublayer.feature.properties)
}
if (nextLayer.layerOptions.link && typeof (nextLayer.layerOptions.link.data) == 'function') {
......
This diff is collapsed.
......@@ -6,7 +6,7 @@ var router = express.Router()
var g1 = require('./../dist/g1.js')
var fs = require('fs')
const port = process.argv.length <= 2 ? 1112 : 1116
const port = process.argv.length <= 2 ? 1112 : 1114
const app = express()
.use(express.static(path.resolve(__dirname, '..')))
......
......@@ -10,6 +10,7 @@
<link rel="stylesheet" href="../node_modules/leaflet/dist/leaflet.css">
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<script src="../node_modules/leaflet/dist/leaflet.js"></script>
<script src="../node_modules/topojson/dist/topojson.min.js"></script>
<script src="../node_modules/d3/build/d3.js"></script>
<script src="../node_modules/d3-scale-chromatic/dist/d3-scale-chromatic.min.js"></script>
<script src="../dist/mapviewer.min.js"></script>
......@@ -17,48 +18,66 @@
.map {
height: 300px;
}
</style>
</head>
<body>
<script>
tape.onFinish(function () { window.renderComplete = true })
tape.onFinish(function () {
window.renderComplete = true
})
</script>
<div id="choropleth" class="map"></div>
<div id="choropleth_topojson" class="map"></div>
<script>
var choro_map = g1.mapviewer({
id: 'choropleth',
layers: {
worldMap2: { type: 'tile', url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' },
indiaGeojson: {
type: 'geojson',
url: 'india-states.geojson',
link: {
url: 'state_score.json',
dataKey: 'name',
mapKey: 'ST_NM'
},
options: {
style: {
fillColor: '#ccc',
fillOpacity: 0.9
}
//GEO JSON
tape("g1.mapviewer test _choropleth without filter function", function (test) {
var choro_map = g1.mapviewer({
id: 'choropleth',
layers: {
worldMap2: {
type: 'tile',
url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
},
attrs: {
fillColor: {
metric: 'score', // same as function(d) { return d.age }
scale: 'linear',
domain: [10, 15, 30],
range: ['red', 'yellow', 'green'],
indiaGeojson: {
type: 'geojson',
url: 'india-states.geojson',
link: {
url: 'state_score.json',
dataKey: 'name',
mapKey: 'ST_NM'
},
options: {
style: {
fillColor: '#ccc',
fillOpacity: 0.9
}
},
attrs: {
fillColor: {
metric: 'score', // same as function(d) { return d.age }
scale: 'linear',
domain: [10, 15, 30],
range: ['red', 'yellow', 'green'],
}
}
}
}
}
})
})
tape("g1.mapviewer test _choropleth without filter function", function (test) {
choro_map
.on('indiaGeojsonloaded', function () {
.on('layersloaded', function () {
// Test if properties are linked from link: config url
choro_map.gLayers['indiaGeojson'].eachLayer(function (sublayer) {
if (['Haryana', 'Maharashtra', 'Kerala', 'Odisha'].includes(sublayer.feature.properties.ST_NM)) {
test.ok('name' in sublayer.feature.properties)
test.ok('score' in sublayer.feature.properties)
}
})
choro_map._choropleth('indiaGeojson', choro_map.options.layers.indiaGeojson)
choro_map.gLayers['indiaGeojson'].eachLayer(function (sublayer) {
if (sublayer.feature.properties['name'] == 'Kerala') {
......@@ -132,45 +151,106 @@
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(154, 205, 0)')
}
})
test.end()
})
tape("g1.mapviewer test _choropleth with filter function", function (test) {
choro_map._choropleth('indiaGeojson', choro_map.options.layers.indiaGeojson)
choro_map.gLayers['indiaGeojson'].eachLayer(function (sublayer) {
if (sublayer.feature.properties['name'] == 'Kerala') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(255, 43, 0)')
}
if (sublayer.feature.properties['name'] == 'Tamil Nadu') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(255, 57, 0)')
}
if (sublayer.feature.properties['name'] == 'Maharashtra') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(177, 216, 0)')
}
if (sublayer.feature.properties['name'] == 'Odisha') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(154, 205, 0)')
}
})
})
tape("g1.mapviewer test _choropleth with filter function", function (test) {
choro_map._choropleth('indiaGeojson', choro_map.options.layers.indiaGeojson)
choro_map.gLayers['indiaGeojson'].eachLayer(function (sublayer) {
if (sublayer.feature.properties['name'] == 'Kerala') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(255, 43, 0)')
}
if (sublayer.feature.properties['name'] == 'Tamil Nadu') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(255, 57, 0)')
}
if (sublayer.feature.properties['name'] == 'Maharashtra') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(177, 216, 0)')
}
if (sublayer.feature.properties['name'] == 'Odisha') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(154, 205, 0)')
}
choro_map._choropleth('indiaGeojson', choro_map.options.layers.indiaGeojson, (props) => props['name'] ==
'Kerala')
choro_map.gLayers['indiaGeojson'].eachLayer(function (sublayer) {
if (sublayer.feature.properties['name'] == 'Kerala') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(255, 43, 0)')
}
if (sublayer.feature.properties['name'] == 'Tamil Nadu') {
test.equals(sublayer._path.attributes.fill.nodeValue, '#ccc')
}
if (sublayer.feature.properties['name'] == 'Maharashtra') {
test.equals(sublayer._path.attributes.fill.nodeValue, '#ccc')
}
if (sublayer.feature.properties['name'] == 'Odisha') {
test.equals(sublayer._path.attributes.fill.nodeValue, '#ccc')
}
})
test.end()
})
choro_map._choropleth('indiaGeojson', choro_map.options.layers.indiaGeojson, (props) => props['name'] == 'Kerala')
})
choro_map.gLayers['indiaGeojson'].eachLayer(function (sublayer) {
if (sublayer.feature.properties['name'] == 'Kerala') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(255, 43, 0)')
}
if (sublayer.feature.properties['name'] == 'Tamil Nadu') {
test.equals(sublayer._path.attributes.fill.nodeValue, '#ccc')
}
if (sublayer.feature.properties['name'] == 'Maharashtra') {
test.equals(sublayer._path.attributes.fill.nodeValue, '#ccc')
}
if (sublayer.feature.properties['name'] == 'Odisha') {
test.equals(sublayer._path.attributes.fill.nodeValue, '#ccc')
// TOPO JSON
tape("g1.mapviewer test topojson", function (test) {
var topo_map = g1.mapviewer({
id: 'choropleth_topojson',
layers: {
AN: {
type: 'topojson',
url: 'a&n.topojson.json',
link: {
data: [{
"name": "Andaman Islands",
"score": 67
},
{
"name": "Nicobar Islands",
"score": 17
}
],
dataKey: 'name',
mapKey: 'NAME_2'
},
options: {
style: {
fillColor: '#ccc',
fillOpacity: 1
}
},
attrs: {
fillColor: {
metric: 'score', // same as function(d) { return d.age }
scale: 'linear',
domain: [10, 15, 30],
range: ['red', 'yellow', 'green'],
}
}
}
}
})
test.end()
$('#choropleth_topojson')
.on('ANloaded', function () {
// Test if properties are linked from link: config url
topo_map.gLayers['AN'].eachLayer(function (sublayer) {
test.ok('name' in sublayer.feature.properties)
test.ok('score' in sublayer.feature.properties)
})
topo_map.gLayers['AN'].eachLayer(function (sublayer) {
if (sublayer.feature.properties['name'] == 'Andaman Islands') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(0, 0, 0)')
}
if (sublayer.feature.properties['name'] == 'Nicobar Islands') {
test.equals(sublayer._path.attributes.fill.nodeValue, 'rgb(221, 238, 0)')
}
})
test.end()
})
})
</script>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment