I have a leaflet map using leaflet-realtime to display and update a position, polygon and line from a geoJson source (data is the position and field of view from an airborne camera). I want to change the style of the line and polygon from the default blue. I understand the leaflet-realtime extends L.geojson so I thought the following code should work but I get options.style is not a function. I have been looking at other examples to try and do this but have spent the day frustrated.
var lineStyle = {
color: 'black',
weight: 5,
opacity: 0.5
}
los = L.realtime({
url: 'http://127.0.0.1/geojson/los2.geojson',
crossOrigin: true,
type: 'json'
}, {
interval: 1 * 500,
style: lineStyle
}).addTo(map);
los.on('update', function(){
map.flyTo(
[this._features.los.geometry.coordinates[1][1],
this._features.los.geometry.coordinates[1][0]]
)
});
If anyone can point me in the right direction it would be hugely appreciated.
Thanks
Yes options.style must be a function - look at:
https://leafletjs.com/reference-1.7.1.html#geojson-style
Change your code:
var lineStyle = {
color: 'black',
weight: 5,
opacity: 0.5
}
los = L.realtime({
url: 'http://127.0.0.1/geojson/los2.geojson',
crossOrigin: true,
type: 'json'
}, {
interval: 1 * 500,
style: function() { return lineStyle; }
}).addTo(map);
los.on('update', function(){
map.flyTo(
[this._features.los.geometry.coordinates[1][1],
this._features.los.geometry.coordinates[1][0]]
)
});
Related
I have a leaflet map with an overlay made from a geojson file that contains polygons, lines and points. I'd like to be able to use custom markers (let's say the image marker is CustomMarker.png). So far, I have the following code that works perfectly well, the only thing is that it displays standard marker icons :
$.getJSON(url, function(geojson) {
overlay = L.geoJson(geojson, {
style: function(feature) {
return {
fillColor: 'red',
weight: 1,
opacity: 0.5,
color: 'red',
dashArray: 3,
fillOpacity: 0.5,
}
},
onEachFeature: function(feature, layer) {
layer.bindPopup("<strong>" + layer.feature.properties.Titre + "</strong><br/>" + " : nom de la région")
}
}).addTo(map);
I know the solution is at my grasp and that something should be put just above "onEachFeature" but can't figure it out so far.
so browsers throw
warning about using momentJS incorrectly.
Deprecation warning: value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.
Arguments:
[0] _isAMomentObject: true, _isUTC: false, _useUTC: false, _l: undefined, _i: 12.30, _f: false, _strict: undefined, _locale: [object Object]
Error
So i looked at my code
data: {
labels: ['01.01', '02.01', '03.01', '04.01', '05.01', '06.01', '07.01', '08.01', '09.01', '10.01', '11.01', '12.01'],
datasets: createChatterData(data, this)
},
And read that I should provide a format when dealing with non iso strings.
labels: [moment('01.01', 'MM.DD'), moment('02.01', 'MM.DD'), ...];
Ok that removed first deprecation.
But my datasets data also contains of date
dataset.data.pushObject({
x: moment(datum).format('MM.DD'),
y: parseInt(moment(datum).format('YYYY'))
});
So I tried different variations to that (premodified ambigious datetime)
x: moment(date, 'YYYY.MM.DD').format('MM.DD')
and
x: moment(date, 'MM.DD')
But my graph doesnt map correctly anymore.
Example of codepen chart working in chrome: http://codepen.io/kristjanrein/pen/wJrQLE
Does not display in firefox/opera
I see a couple of issues here.
1) Since you want your X axis to be a time scale, then you should leave your X data value as a moment object. Your current implementation is creating a moment object from a date string and then formatting it back to a string. When you do this, chart.js then takes the string and tries to create a moment object internally when it builds the chart.
Therefore, It is best to keep the data as either a Date or Moment object and use the time scale configuration properties to determine how the data is displayed on the chart. This prevents chart.js from having to construct the moment object and guess at the string format.
2) You are using the pre-2.0 way to create a chart when you use Chart.Scatter. Instead you should use the new style (new Chart()) and pass in a type property.
Here is a modified version of you code that results in no browser warnings and works in Chrome and Firefox (I did not test in Opera).
var getData = function() {
var dummyDataset = [
'2007-11-09T00:00:00.000Z',
'2006-08-04T00:00:00.000Z',
'2006-08-06T00:00:00.000Z',
'2008-01-10T00:00:00.000Z'
];
return dummyDataset.map(function(datum) {
var myMoment = moment(datum);
return {
x: myMoment,
y: parseInt(myMoment.format('YYYY')),
};
});
};
var ctx = document.getElementById("chart1").getContext("2d");
var myScatter = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "My First dataset",
borderColor: 'rgb(255, 99, 132)',
fill: false,
pointRadius: 4,
pointHoverRadius: 8,
showLine: false,
data: getData()
}]
},
options: {
responsive: true,
title: {
display: true,
text: 'Random Data'
},
legend: {
display: true,
labels: {
fontSize: 10,
boxWidth: 20
}
},
elements: {
point: {
pointStyle: 'rect'
}
},
hover: {
mode: 'nearest'
},
scales: {
xAxes: [{
type: 'time',
position: 'bottom',
scaleLabel: {
display: true,
labelString: 'Months'
},
time: {
unit: 'month',
displayFormats: {
month: 'MM'
},
}
}],
yAxes: [ {
type: 'linear',
ticks: {
min: 2005,
max: 2015,
stepSize: 1
},
scaleLabel: {
display: true,
labelString: 'Year'
}
}]
}
}
});
You can see it in action at this forked codepen.
One other thing to keep in mind is that because your data spans multiple years, you will see duplicate months on the X axis. Remember, a time scale is used to plot dates so even if you only display the months, a data point with the same month but with different years will not be plotted at the same location.
If you are actually only wanting to show month string/number values in the X axis, then you should not use the time scale at all and use the linear scale instead. Then when you build your data values, you would extract the month from the data (the same way you are already doing for your Y value).
var getData = function() {
var dummyDataset = [
'2007-11-09T00:00:00.000Z',
'2006-08-04T00:00:00.000Z',
'2006-08-06T00:00:00.000Z',
'2008-01-10T00:00:00.000Z'
];
return dummyDataset.map(function(datum) {
var myMoment = moment(datum);
return {
x: parseInt(myMoment.format('MM')),
y: parseInt(myMoment.format('YYYY')),
};
});
};
So in addition to jordan's answer
I changed my labels and x axis from
['01.01', '02.01', ...] to [1,2,...]
and
from type: 'time' to type: 'linear'
And to make it map not only by month but also by day. I had to make date objects to correct floats. 05.20 to 5.66
const date = datum.key;
const day = parseInt(moment(date).format('DD')) / 30 * 100;
const fullDate = parseFloat(moment(date).format('MM') + '.' + Math.round(day))
// 05.10 would be 5.3 (10 of 30 is 33%)
{
x: fullDate,
y: parseInt(moment(date).format('YYYY'))
date: date, // for tooltip
count: count // for tooltip
}
And i also had to make corrections to my tooltips
callbacks: {
title: function([tooltipItem], data) {
const tooltipInfo = getTooltip(tooltipItem, data.datasets);
return tooltipInfo.date;
},
label: function(tooltipItem, data) {
const tooltipInfo = getTooltip(tooltipItem, data.datasets);
return i18n.t('chart.count') + ': ' + tooltipInfo.count;
},
}
corresponding tooltip dataset
function getTooltip(tooltipItem, datasets) {
return datasets[tooltipItem.datasetIndex].data.find(datum => {
return datum.x === tooltipItem.xLabel && datum.y === tooltipItem.yLabel;
});
}
I am a novice to OpenLayers, so sorry for an obvious (and perhaps dumb) question, for which I found different approaches for solutions, but none working. Tried this and that, a dozen different suggestions (here, here, here, here, here) but in vain.
Basically, I want to pass the coordinates of a drawn rectangle to another webservice. So, after having drawn the rectangle, it should spit me out the four corners of the bounding box.
What I have so far is the basic OL layers example for drawing a rectangle:
var source = new ol.source.Vector({wrapX: false});
vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(0, 255, 0, 0.5)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vector
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
var draw; // global so we can remove it later
function addInteraction()
{
var value = 'Box';
if (value !== 'None')
{
var geometryFunction, maxPoints;
if (value === 'Square')
{
value = 'Circle';
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
}
else if (value === 'Box')
{
value = 'LineString';
maxPoints = 2;
geometryFunction = function(coordinates, geometry)
{
if (!geometry)
{
geometry = new ol.geom.Polygon(null);
}
var start = coordinates[0];
var end = coordinates[1];
geometry.setCoordinates([
[start, [start[0], end[1]], end, [end[0], start[1]], start]
]);
return geometry;
};
}
draw = new ol.interaction.Draw({
source: source,
type: /** #type {ol.geom.GeometryType} */ (value),
geometryFunction: geometryFunction,
maxPoints: maxPoints
});
map.addInteraction(draw);
}
}
addInteraction();
Now, what comes next? What is a good way of extracting the bounding box?
Thanks for any hints!
You need to asign a listener to the draw interaction. Like so:
draw.on('drawend',function(e){
alert(e.feature.getGeometry().getExtent());
});
Here is a fiddle
Below is the code for a pie chart i have in my Sencha touch app. The issue i face is that whenever the space to display chart is not enough for all labels there are callout lines and labels, but then i want these callout lines to be shorter in length then they are right now because they do not fit my screen and labels get cut.
I cannot find the correct config property for that.
EDIT - the two charts in image have the same code and are placed in hbox layout in container
{
xtype: 'polar',
itemId: 'pieChart',
background: 'white',
store: 'GraphsStore',
shadow: true,
innerPadding: 25,
//bind the chart to a store with the following structure
//interactions: ['rotate'],
colors: ["#115fa6", "#94ae0a", "#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
//configure the legend.
legend: {
position: 'top',
//width: 100
hidden: true
},
//describe the actual pie series.
series: [{
type: 'pie',
xField: 'g1',
renderer: function(sprite, config, rendererData, index) {
var changes = {},
store = rendererData.store,
curentRecord = store.getData().items[index];
var text = curentRecord.data.g1;
changes.text = text;
return changes;
},
label: {
field: 'name',
display: 'rotate',
font: '8px'
},
donut: 25,
style: {
miterLimit: 5,
lineCap: 'miter',
lineWidth: 1
}
}]
}
Any pointers will be helpful !
Thanks.
In the chart/series/sprite/PieSlice.js, modify the following two lines:
x = centerX + Math.cos(midAngle) * (endRho + 40);
y = centerY + Math.sin(midAngle) * (endRho + 40);
Change the 40 to a smaller number.
Is there a way to create a Legend control for series that belong to Indicator Plot with Dojo Charting.
I've tried some standard well described ways from the documentation. But with no success! Legend are not appearing for Indicator Plot.
Maybe somebody know is it possible to draw legend for this case or not?
Thanks in advance!
EDIT(my code added):
1. id - id of chart dom element.
2. opts.chartOpts - chart options from outside js.
3. legname - id of legend dom element.
4. scale.avg - is just a double value.
this.chart = new Chart(id, this.opts.chartOpts);
this.chart.addPlot("default", {
animate: { duration: 1000, easing: easing.linear },
type: ColumnsPlot,
markers: true,
gap: 1
});
this.chart.addPlot("avgline", {
type: IndicatorPlot,
vertical: false,
lineStroke: { color: "#00ff00", style: "ShortDash" },
stroke: { width: '1.2px' },
fill: '#eeeeee',
font: 'normal normal normal 11px Arial',
labels: 'none',
offset: { x: 32, y: 4 },
values: [scale.avg],
precision: this.opts.precision
});
//Add axis code goes here... cutted for clearance
this.chart.addSeries('Power', chartOptions.data);
this.chart.addSeries('Average', [scale.avg], { plot: 'avgline' });
var tip = new Tooltip(this.chart, "default", { 'class' : 'kaboom' });
var mag = new Magnify(this.chart, "default");
var hightlight = new Highlight(this.chart, "default");
this.chart.render();
this.leg = new Legend({ chart: this.chart, horizontal: false }, this.legName);
And as result of this code I see legend for 'default' plot 'Power' series only. And nothing for 'Average' series.