I have a leaflet map in R with a lot of LineStrings in it. The lines default to blue, with a certain thickness. I want to change the line color and have the thickness depend on a weight variable. I create the map by reading a geojson file. Adding a "style" section directly to each linestring feature in the geojson isn't working. Here is my R code for the map:
colchoice = "red"
ptl_str = paste("#! function(feature, latlng){
return L.circleMarker(latlng, {
radius: feature.properties.radius || 5,
fillColor: feature.properties.fillColor || '", colchoice, "',
color: '#000',
weight: 1,
fillOpacity: 0.8
})
} !#", sep="")
m <- Leaflet$new()
m$setView(c(38.892682, -77.031681), zoom = 12)
m$geoJson(geojson,
onEachFeature = "#! function(feature, layer){
layer.bindPopup(feature.properties.popup)
} !#",
pointToLayer = ptl_str)
m
This successfully formats points on the map into dots. But now I want to format the lines differently too. I appreciate any help. Thanks!
Upfront: i know nothing about R and not able to test what i'm saying, but i know my way around Leaflet in Javascript and can tell you how i would go about accomplishing that in JS, so you can translate it to R:
var geoJsonLayer = L.geoJson(data, {
onEachFeature: function (feature, layer) {
if (layer instanceof L.Polyline) {
layer.setStyle({
'color': feature.properties.color
});
}
}
});
Here's a working example on Plunker: http://plnkr.co/edit/g4juen?p=preview
Related
I have created a line graph using highchart js .I want to set a grey color marker at the starting and a red colored mrker at the end of my graph.Is there a way to do it with highcharts?
In the load event (chart.events.load) you can extract first and last point from series. Then call update() function to modify fillColor parameter.
chart:{
events:{
load:function() {
var chart = this,
series = chart.series[0],
data = series.data,
len = data.length;
//first point
data[0].update({
marker:{
fillColor: 'gray'
}
},false);
//last point
data[len - 1].update({
marker:{
fillColor: 'red'
}
});
}
}
},
Example:
http://jsfiddle.net/s9erv8f0/
I am trying to make a Sankey diagram using R for a printed report. I have currently used 2 methods to do this but neither is achieving quite what I wanted.
The first uses the Riverplot function and produces this:
My problems with this plot is that I can't work out how to control the whitespace around the plot (it appears to be fixed and does not adjust to different sized datasets) or the positioning of the annotated text. I want to repeat this plot for a number of similar but differently sized datasets but the text placing is very variable in its positioning. This is the code I am currently using to add the text annotations:
riverplot(a, srt = 0)
y_lim<-par("yaxp") #gets y axis limits to spicify text placements
# text(1.5,y_lim[1], Name,font=2) #labels plot with Name (LA)
text(1,y_lim[1],"2004")
text(2,y_lim[1],"2010")
The second uses the rCharts and produces this:
My problems with this are (a) I would like to fix the order of the categories on each side (as in the first image) and (b) I would like to annotate the diagram as in the first image.
My questions are:
How I can fine tune the formatting of the Riverplot figure (first image), or,
How do I add annotations to the rCharts Sankey plot (I'm guessing this could be through the script section but I am new to rCharts, d3 and javascript), and,
Is it possible to fix the order of the categories int the rCharts sankey plot.
After a lot of tinkering and pinching code from a bunch of places, I have managed to produce what I wanted (solving point 2 of my original question).
The code could be refined in a number of places and could probably be done more elegantly but I have included it below in case it helps anyone else.
sankeyPlot$setTemplate(
afterScript = "
<script>
var cscale = d3.scale.ordinal()
.domain(['N','E', 'G' ,'I','T','N ','E ', 'G ' ,'I ','T '])
.range(['#d3d3d3', '#32ca32', '#1f78b4', '#e31a1c','#ecd736','#d3d3d3', '#32ca32', '#1f78b4', '#e31a1c','#ecd736'])
d3.selectAll('#{{ chartId }} svg path.link')
.style('stroke', function(d){
return cscale(d.source.name);
//returns grey links
})
d3.selectAll('#{{ chartId }} svg .node rect')
.style('fill', function(d){
return cscale(d.name)
})
.style('stroke', 'none')
var text_box = d3.selectAll('#{{ chartId }}').append('svg')
.attr('width', 500)
.attr('height', 100)
var TextData = [
{ 'cx': 0, 'cy': 20 ,'label': 'Type A', 'pos': 'left'},
{ 'cx': 250, 'cy': 20,'label': 'Label','pos': 'middle'},
{ 'cx': 500, 'cy': 20, 'label': 'Type B','pos': 'end'}];
var text = text_box.selectAll('text')
.data(TextData)
.enter()
.append('text');
//Add the text attributes
var textLabels = text
.attr('x', function(d) { return d.cx; })
.attr('y', function(d) { return d.cy; })
.text( function (d) { return d.label ; })
.attr('text-anchor', function(d) { return d.pos ;})
.attr('font-family', 'sans-serif')
.attr('font-size', '14px')
.attr('fill', 'black');
</script>
")
I'm using leaflet with custom CRS.Simple projection. If I draw a polyline at the page Load it is more or less drawn ok (Although much more accurate in firefox than in chrome) but if I drag the map the polyline remains in the same place of the browser window, so then appears shifted respect of the background map.
Example:
Initial load
After drag the map, the map moves but the polyline remains in the same place
To add the polyline I'm converting the coordinates to the CRS.Simple projection. I don't think there is a problem here as every other map marker or text appears correctly
.....
//initialize leaflet map
map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
zoomControl: false,
crs: L.CRS.Simple //simple coordinates system
}).setView([0, 0], mapMaxZoom);
//set the bounds of the map to the current dimension
var mapBounds = new L.LatLngBounds(
map.unproject([0, mapHeight], mapMaxZoom),
map.unproject([mapWidth, 0], mapMaxZoom)
);
//load the tiles
map.fitBounds(mapBounds);
L.tileLayer(mapData.info.tiles+'/{z}/{x}/{y}.png', {
minZoom: mapMinZoom,
maxZoom: mapMaxZoom,
bounds: mapBounds,
attribution: '',
noWrap: true,
continuousWorld: true
}).addTo(map);
.....
var pointList = [getMapCoordinates(1750,1750),
getMapCoordinates(1520,1764),
getMapCoordinates(1300,1560),
getMapCoordinates(1132,1258),
getMapCoordinates(1132,1060),
getMapCoordinates(926,960)];
polyline = new L.Polyline(pointList, {
color: 'red',
weight: 3,
opacity: 0.5,
smoothFactor: 1
});
polyline.addTo(map);
....
function getMapCoordinates(px,py)
{
//as we use simple system, transform the point (based on pixel) on map coordinates that leaflet understand
return map.unproject([px, py], map.getMaxZoom());
}
Any idea what I'm doing wrong, or is it a bug? Any workaround would be appreciated
Ok, it seems the problem was in stable version (0.7.3) Using dev version (1.0-dev) works ok and even solves the problem with the different browser drawing
This is the meat of the code I am using and I am not getting errors, but I am not seeing the points that are in the area of the rectangle. Any help would be appreciated:
`enter code here`/** #this {google.maps.Rectangle} */
function showNewRect(event) {
var ne = rectangle.getBounds().getNorthEast();
var sw = rectangle.getBounds().getSouthWest();
google.maps.event.addlistener(rectangle, "bounds_changed", function(){
document.getElementById("map-selected").innerHTML=rectangle.getBounds();
var rectA = (ne*sw);
})
}
function listSelected () {
var inside = $.map( sites, function ( s ) {
var d;
if ( ( (d = google.maps.geometry.poly.containsLocation( s.position )) <= rectA ) )
return s.location + ' ('+(Math.round(d/100)/10)+' km)';
$('#map-selected').html( inside.sort().join('') );
});
}
google.maps.event.addListener(drawingManager, 'rectanglecomplete', function( rectangle ) {
selectedArea = rectangle;
listSelected();
google.maps.event.addListener(rectangle, 'center_changed', listSelected);
google.maps.event.addListener(rectangle, 'bounds_changed', listSelected);I am working with the Google maps API and I have a map I am drawing on with a rectangle. I need to have a user draw the rectangle, and on the map there will be predefined locations, that when the rectangle crosses the locations there will be details of each location put into a list.
This is an example:
http://hmoodesigns.com/ksi/
I have an example using the circle draw tool, which I can get to work fine, but the rectangle tool I have not been able to have this identify the points on the map.
How can I check for these points without having a predefined rectangle on the page?
Thanks,
When the Rectangle has been drawn iterate over the locations and use the method contains() of the Rectangle's bounds to test if the LatLng's are within the bounds of the Rectangle
I know I am overlooking/not considering something elementary, but I don't know what I don't know...
Trying to use Fusion Tables to populate an array of Google Maps API circle objects and place them on a map.
Currently I am able to hard-code the array like so:
citymap['Dane'] = {
center: new google.maps.LatLng(43.10599621690524, -89.38682556152344),
population: 5000000
};
...and place them on a map.
And I am able to return JSON from the Fusion Tables, loop through and create what I think is an array and display it, but I can't make the circle objects appear.
Any advice on what I need to google/learn would be appreciated.
Here's an example using the new Trusted Tester API to generate Polygons to display on the map:
https://developers.google.com/fusiontables/docs/samples/mouseover_map_styles
The logic should be similar, but instead of a Polygon, you would create a Circle:
new google.maps.Circle({
center: new google.maps.LatLng(<lat>, <lng>),
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
map: map,
radius: <radius>
});
You want to check out the Circle class; it provides a simple way to create circular shapes and place them on the map. Ok, so I see you've already found the shape class, so you are good there.
I think your problem is that you are turning everything into strings in your processing loop:
citymap = {};
for (var i = 0; i < data.table.rows.length; i++) {
citymap += 'citymap[\'' + data.table.rows[i][0] + '\'] = {' +
'center: new google.maps.LatLng(' + data.table.rows[i][1] + '),' +
'population: 2842518};';
}
I think you want code that looks more like this:
citymap = new Array();
for ( var i = 0; i < data.table.rows.length; i++ ) {
var circleData = {
center: new google.maps.LatLng( data.table.rows[i][1] );
position: 2842518
}
citymap.push( circleData );
}
I realize I have left some other bit of data out, but you get the idea. I believe your primary problem was that you were stringifying the code.