Load data from mysql to leaflet - javascript

I need to make a map leaflet that contains some polygons and i want to color my poygons based on data from MYSQL. But when i try this code, my polygons are not show.
This is my code on my map.php:
<?php
include 'koneksi.php';
$sql="select sum(skor_bobot) as hasilnya from penilaian where bulan=1 and id_kelurahan=1";
$data=mysql_query($sql);
$js='';
while ($row=mysql_fetch_array($data)) {
$js .='L.geoJson(states, {
style: function(feature) {
if ((feature.properties.party=='.'Republican'.')&&('.$row['hasilnya'].'=='.'10'.')) {
return {color: "#ffff89"};
} else {
return {color: "#ff0000"};
};
}
}).addTo(mymap);';
}
echo $js; ?>
and below are my geojson code on my map.php:
var states = [{
"type": "Feature",
"properties": {"party": "Republican"},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-104.05, 48.99],
[-97.22, 48.98],
[-96.58, 45.94],
[-104.03, 45.94],
[-104.05, 48.99]
]]
}
}, {
"type": "Feature",
"properties": {"party": "Democrat"},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-109.05, 41.00],
[-102.06, 40.99],
[-102.03, 36.99],
[-109.04, 36.99],
[-109.05, 41.00]
]]
}
}];

Strange that you do not (double) quote Republican in your JS code?
'(feature.properties.party=='.'"Republican"'.')'
Without those double quotes, once your code is executed as JavaScript, you are passing a variable Republican (which you have not previously defined, hence your console error), instead of a String "Republican" to compare with.

Related

How to convert JSON to GeoJson JavaScript

I've got a JSON from a database but now I need to convert it into GeoJson to use it in my map
I found this solution but it shows an undefined array.
$.getJSON("./origin/neworigin.json", function(jsonData) {
var outGeoJson = {}
outGeoJson['properties'] = jsonData
outGeoJson['type']= "Feature"
outGeoJson['geometry']= {"type": "Point", "coordinates":
[jsonData['latitude'], jsonData['longitude']]}
console.log(outGeoJson)
});
This is an example from myJSON
[{"station":"BORJA","institution":"SENCICO","longitude":"-77.0064","latitude":"-12.0855"},
{"station":"SCARQ","institution":"SENCICO","longitude":"-71.5408","latitude":"-16.385"},
{"station":"SCAR2","institution":"SENCICO","longitude":"-71.5364","latitude":"-16.3934"},...
in browser
Check if the array is empty or not.
Try change the variable names.
OR
Provide more details.
You have two options to create a valid GeoJSON form JSON.
create GeoJSON.Point array and GeoJSON.FeatureCollection
create GeoJSON.MultiPoint object
Here are code snippets:
const jsonData = [{
"station": "BORJA",
"institution": "SENCICO",
"longitude": "-77.0064",
"latitude": "-12.0855"
},
{
"station": "SCARQ",
"institution": "SENCICO",
"longitude": "-71.5408",
"latitude": "-16.385"
},
{
"station": "SCAR2",
"institution": "SENCICO",
"longitude": "-71.5364",
"latitude": "-16.3934"
}
];
// to GeoJSON.Point array
const geoJSONPointArr = jsonData.map(row => {
return {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [row.longitude, row.latitude]
},
"properties": row
}
});
console.log(geoJSONPointArr);
// to GeoJSON.FeatureCollection
const pointArrFeatureCollection = {
"type": "FeatureCollection",
"features": geoJSONPointArr
}
console.log(pointArrFeatureCollection);
// to GeoJSON.MultiPoint
const geoJSONMultiPoint = {
"type": "Feature",
"geometry": {
"type": "MultiPoint",
"coordinates": jsonData.map(row => [row.longitude, row.latitude])
},
"properties": {
originalData: jsonData
}
}
console.log(geoJSONMultiPoint);
I would also recommend using the turf library, which is very convenient when working with the GeoJSON format.

Adding new paths to D3 Globe

I am working on an implementation of a D3 Globe. I am trying to add paths to the globe when the user clicks a button, but this is not proving successful. If I add all paths at once there is no issue, but if I try to add them after a trigger event then it fails. My jsfiddle: http://jsfiddle.net/Guill84/b6xvj76e/1/. I don't think there is an issue with the JSON, as it pops up in the console as expected.
The bit of the script that fails can be found right at the bottom of the fiddle. I paste it below for ease of reference:
$("#clickMe").click(function() {
data = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"name": "path1"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[117.5977,44.3408],[116.4551,40.2539]]]"
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path2"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[122.3438,41.0889],[116.4551,40.2539]]]"
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path3"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[105.9961,37.3096],[116.4551,40.2539]]]"
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path4"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": "[[[116.4551,40.2539],[109.5996,35.6396],[116.4551,40.2539]]]"
},
"id": "RML"
}]}
console.log(data);
var svg = d3.select("#body");
flows = svg.selectAll("path")
.data(data)
.enter().append("svg:path")
.attr("d", clip)
.style("stroke", "black")
.attr("id", function(d) {
return d.properties.name.split(' ').join('_')
});
});
The problems are three:
1) Your JSON structure has a problem: the arrays are specified in string format, thus causing an error when used by the clip function.
2) You are binding the data object directly, when you should instead binding data.features which is the array which contains the four paths you need to create.
3) The selection will select the already existing paths for countries. You can avoid this by adding a class to the new paths. For example, classing them as flow.
4) The flows paths are declared inside the scope of their rendering function, therefore they cannot be updated on the refresh function.
Here's your code with the three fixes:
$("#clickMe").click(function () {
// 1) Arrays: Fixed arrays for coordinates so they are not serialized in a string
var data = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "path1"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [117.5977, 44.3408], [116.4551, 40.2539]]]
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path2"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [122.3438, 41.0889], [116.4551, 40.2539]]]
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path3"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [105.9961, 37.3096], [116.4551, 40.2539]]]
},
"id": "RML"
},
{
"type": "Feature",
"properties": {
"name": "path4"
},
"year": "2010",
"geometry": {
"type": "Polygon",
"coordinates": [[[116.4551, 40.2539], [109.5996, 35.6396], [116.4551, 40.2539]]]
},
"id": "RML"
}
]
};
console.log(data);
var svg = d3.select("#body");
// 3) Selection: Add a class to avoid collision with existing paths
// 4) Using var declared outside so it can be used on the update function
flows = svg.selectAll("path.flow")
// 2) Data binding: Bind the features property instead, which is an array
.data(data.features);
// 3) Enter nodes: When appending them, class them as flow so they keep separated
flows.enter().append("svg:path")
.classed("flow", true)
.attr("d", clip)
.style("stroke", "black")
.style("stroke-width", "1px")
.attr("id", function (d) {
return d.properties.name.split(' ').join('_')
});
});
Now it works, but I still cannot see the added paths on the globe. The path elements are for sure appended to the DOM of the svg element, though, which solves your initial problem ;)
- UPDATE -
As indicated on the comments, the added paths didn't follow the movement of the globe. That was due to the paths being added to the svg but not updated along the country shapes on the refresh() function (added point 4).
To do so, the selection for these paths should be made available inside the refresh() function (it suffices declaring the var flows at the top of the script), and then adding an update for this selection inside that function. Like this:
function refresh(duration) {
(duration ? feature.transition().duration(duration) : feature).attr("d", clip);
// 4) Added the flows to the paths selection whose d attribute will be updated (only when present)
flows && (duration ? flows.transition().duration(duration) : flows).attr("d", clip);
}
A complete version can be seen on this fiddle: http://jsfiddle.net/oscar_dr/0psy5udk/2/

How to save a GeoJSON into file using javascript

I am wondering if I have a GeoJSON object such as
var geoJSONLoc= {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"timeReported": "2013-01-22 08:42:26+01"
},
"geometry": {
"type": "Point",
"coordinates": [
7.582512743,
51.933292258,
1
]
}
},
{
"type": "Feature",
"properties": {
"timeReported": "2013-01-22 10:00:26+01"
},
"geometry": {
"type": "Point",
"coordinates": [
7.602516645,
51.94962073,
1
]
}
}]}
How can I save this into a .json file for future use?
I am trying to use
localStorage.setItem('geoJSONLoc.json', geoJSONLoc);
but it doesnt seem to be the right answer.
I've done a little work in NodeJS, so this maybe way off base.
But couldn't you use the fs module for this?
something like
var fs = require('fs')
fs.writeFile('geoJSONLoc.json', geoJSONLoc, function(err){
if(err){
console.log(err);
}
});

Openlayers 3 z-ordering of features

I have a vector layer, which contains polygons and points loaded from GEOJSON source. It looks to me, points are always positioned above polygons regardless of their order in source GEOJSON file. See an example definition below. Is there a way, how to position points below polygons on the same layer?
The example:
Points are styled as white and red circle. Polygon is gray.
My GEOJSON looks like this (I even tried to reverse features order in the file):
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"radius": "1000"
},
"geometry": {
"type": "Point",
"coordinates": [
12.4,
50.08333
]
}
},
{
"type": "Feature",
"properties": {
"radius": "800"
},
"geometry": {
"type": "Point",
"coordinates": [
12.4,
50.08333
]
}
},
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[
12.4,
50.08333
],
...........
Use zIndex in the style objects.

Parent polygon in Leaflet js

I would like to wrap multiple polygons in a parent polygon. Example below:
Is this possible in Leaflet js? Assume I have an array of L.polygon objects.
Thank you
Short answer: no.
If you want to create an envelope for your polygones, then it is an algorithm problem that goes beyond the scope of leafletjs.
You can look at the answers of this question to start solving your problem.
EDIT: here is an example using Turfjs library (thanks to #IvanSanchez for the heads up and to #HudsonPH for the polygons).
// draw envelope
var points = {
"type": "FeatureCollection",
"features":
[
// collect the points of your polygons
turf.point([-104.05, 48.99]),
// ...
]
};
var hull = turf.convex(points);
L.geoJson(hull).addTo(map);
You can have a group, but you need define all the coordinates
more info: http://leafletjs.com/examples/geojson.html
var states = [{
"type": "Feature",
"properties": {"party": "Republican"},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-104.05, 48.99],
[-97.22, 48.98],
[-96.58, 45.94],
[-104.03, 45.94],
[-104.05, 48.99]
]]
}
}, {
"type": "Feature",
"properties": {"party": "Democrat"},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-109.05, 41.00],
[-102.06, 40.99],
[-102.03, 36.99],
[-109.04, 36.99],
[-109.05, 41.00]
]]
}
}];
L.geoJson(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Republican': return {color: "#ff0000"};
case 'Democrat': return {color: "#0000ff"};
}
}
}).addTo(map);

Categories