Related
I have a web app I am creating that maps 30k+ symbols, but my issue is that on initialization, the map.on('load') is way too slow. I've added timers all throughout my code and it is specifically this line of code that takes 10+ seconds to run.
I've looked through all of Mapbox's resources on performance but none of the suggestions work or are relevant, (e.g., minimize the amount of layers used even though my layers take 0.1 seconds to load, using vector tiles instead of GeoJSON data, changing the properties of the data source, minimizing features etc.).
Has anyone else had this issue and figured out how to resolve it? I've been trying for days to optimize this map but I can't figure it out!
// Set map properties with the predefined configuration
mapboxgl.accessToken = 'my access token';
const map = new mapboxgl.Map({
container: 'fullMap',
style: 'mapbox://styles/mapbox/light-v10',
center: [-100.83, 39.22],
zoom: 5,
});
startTime = performance.now();
map.on('load', () => {
endTime = performance.now(); // Ends up being 10+ seconds...
map.addSource('gc_offices', {
type: 'geojson',
data: geojsonData,
buffer: 0,
cluster: true,
clusterMaxZoom: 12, // Max zoom to cluster points on
clusterRadius: 50, // Radius of each cluster when clustering points
});
map.addLayer({
id: 'clusters',
type: 'circle',
source: 'gc_offices',
paint: {
'circle-color': [
'step',
['get', 'point_count'],
'#2288f2',
5, '#3d97f5',
25, '#64abf5',
50, '#83bcf7',
100, '#a3ccf7',
250, '#cfe4fa',
500, '#eb4034'
],
'circle-radius': [
'step',
['get', 'point_count'],
13,
20, 18,
50, 25,
100, 30,
250, 40,
500, 50,
]
}
});
map.addLayer({
id: 'cluster-count',
type: 'symbol',
source: 'gc_offices',
filter: ['has', 'point_count'],
layout: {
'text-field': '{point_count_abbreviated}',
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
'text-size': 12,
'text-allow-overlap': true
}
});
map.addLayer({
id: 'locationData',
type: 'symbol',
source: 'gc_offices',
minzoom: 10,
layout: gc_office_layout_properties,
paint: gc_office_paint_properties,
});
});
I am using layer of symbols and want to make it possible as much as possible pixel perfect the icon be. How i can achieve this i am using custom maki icons for these symbols.
Is it somehow possible to increase the size of the icon but reduce the size of square for example?
Ive tried to play with size and paddings in the layer setup but this did not help.
My Layer looks like this:
"id": tableName + "-layer",
"type": "symbol",
"source": tableName,
"source-layer": tableName,
"layout": {
"icon-image": 'marker-15-svg',
"icon-size": ["interpolate",
["linear"], ["zoom"],
4, 1.3,
8, 1.5,
13, 2.5
],
"icon-allow-overlap": true,
"icon-padding": 0,
"icon-offset": [0, -3],
"icon-anchor": "center",
"symbol-z-order": "source"
},
"paint": {
"icon-color": materialSetColor,
"icon-opacity": {"stops": [[10, 0.7], [30, 1]]},
}
I'm developing a report in Jaspersoft Studio 6.4 using custom visualization component and Highcharts.
Long story short, when doing a bubble chart or an area chart, plotOptions.fillColor -attribute does not work properly, but leaves the bubbles inside or stacked area chart's insides black. Black color usually means the color is not found, but the line of the bubble/lines in the area chart work as they should.
Here is the following Highcharts script for area chart:
define(['jquery_hc','hchart'], function ($, Highcharts) {
return function (instanceData) {
// Creating the chart
var config = {
chart: {
type: 'area',
plotBorderWidth: 1,
renderTo: instanceData.id,
width: instanceData.width,
height: instanceData.height,
marginBottom: 15,
marginLeft: 40,
marginRight: 5,
marginTop: 5
},
title: {
text: ""
},
colors: ['#927453', '#9b672c', '#b0771e', '#e66726', '#474747', '#949494', '#feb40b', '#bd9c31', '#e0b33a'],
xAxis: {
allowDecimals: false,
title: {enabled: false},
labels: {enabled: false},
visible: false
},
legend: {
itemStyle: {"fontSize": 6},
symbolPadding: 4,
symbolHeight: 4,
symbolWidth: 4,
y: 20
},
credits: {enabled: false},
yAxis: {
title: {enabled: false},
labels: {
style: {"fontSize": 6},
formatter: function () {
return this.value;
},
},
tickInterval: 2
},
plotOptions: {
area: {
stacking: 'percent',
animation: false,
marker: {
enabled: false
},
lineWidth: 1
}
},
series: [{
name: 'that',
data: [502, 635, 809, 947, 1402, 3634, 5268]
}, {
name: 'it',
data: [106, 107, 111, 133, 221, 767, 1766]
}, {
name: 'with',
data: [163, 203, 276, 408, 547, 729, 628]
}, {
name: 'who',
data: [18, 31, 54, 156, 339, 818, 1201]
}, {
name: 'how',
data: [2, 2, 2, 6, 13, 30, 46]
}, {
name: 'this',
data: [82, 72, 62, 46, 113, 320, 443]
}, {
name: 'that',
data: [11, 12, 14, 16, 13, 55, 113]
}, {
name: 'those',
data: [7, 1, 3, 11, 15, 37, 49]
}, {
name: 'these',
data: [108, 301, 504, 1056, 3039, 8018, 10201]
}, {
name: 'this too',
data: [10, 30, 50, 105, 303, 801, 1020]
}]
}
new Highcharts.Chart(config);
}
});
And the build.js:
({
baseUrl: '',
paths: {
jquery_hc: "../jquery-3.2.1",
hchart: "../highcharts",
'areaChart': 'areaChart'
},
shim: {
'hchart' : {
deps: ["jquery_hc"],
exports: 'Highcharts'
}
},
name: 'areaChart',
out: "areaChart.min.js"
})
The highchart is using newest highchart.js and jquery-3.2.1.js.
Few things I've tried to add the color:
Using theme to put the charts main color
Setting plotOptions.fillColor: null
Setting plotOptions.fillColor: '#927453'
Setting plotOptions to "series" from "area"
Setting plotOptions.color: [the same colors]
and maybe few other things based on the API reference from Highcharts.
One thing on the other hand is working, if I put the plotOptions.fillColor: '#ffffff', the color of all changes, which means the issue is mostly about matching one color per dataset.
One huge issue is, that this is not reproducible in JSFiddle (JSFiddle).
So, Jasper Report is possibly to blame, but I'm starting to be out of ideas. I've found one issue, which could be related to this: (https://
community.jaspersoft.com/jaspersoft-studio/issues/8641) , but I haven't been able to do much about it with this setup. My web application is using jasper engine to produce reports and the problem is also present in there.
People of StackOverflow, employees of Highcharts and employees of Jaspersoft, combine your knowledge and help me to solve this issue!
Lastly, a picture of the Jasper Report studio of the generated report:
After looking to code, I found report is properly working when we see it in HTML format but pdf format is not working properly. As we kow CVC component utilises phantmjs in order to download report then I tried to search issue related to phantomjs and highcharts but unable to find anything.
Then I tried looked plotOption property and added following plotOption to your code.
plotOptions: {
series: {
animation: false,
stacking: 'percent',
lineWidth: 1,
fillColor: null,
fillOpacity: 1, // this is default to 0.75
marker: {
enabled: false
}
}
},
Then it starts showing the result in PDF format as well. So the main culprit is fillOpacity If you set it to 1 then your problem will be resolved.
Note: If you use fillOpacity other than 1 then it is not showing result.
You can also specify color, fillcolor and opacity as shown below.
series: [{
name: 'that',
data: [502, 635, 809, 947, 1402, 3634, 5268],
fillColor:'red', // use this color light as compared to color
fillOpacity: 1,
color: 'white' // use this color dark as compared to fillcolor
},
...
...
...
,{
name: 'this too',
data: [10, 30, 50, 105, 303, 801, 1020],
fillColor:'#00ff00',
fillOpacity: 1,
color: 'orange'
}]
You can download code from here.
I am trying to use Mapbox/Turfjs to understand how many points are in a polygon. I have rendered my polygon and points in map.onload Is then possible to call Turf.js from another function AFTER the polygon and points have been rendered to the map?
Something like this...?
$(document).ready(function(){
mapboxgl.accessToken = 'eeeeeeeeee';
map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v9',
center: [ 32.62939453125,1.7355743631421197],
zoom: 6.5,
pitch: 40,
maxZoom: 17
});
map.on('load', function () {
//geofence data
map.addSource('fencedata', {
type: 'geojson',
data: 'data/fence.geojson'
});
map.addLayer({
id: 'fence',
type: 'fill',
"source": "fencedata",
'layout': {},
'paint': {
'fill-color': '#FF0000',
'fill-opacity': 0.3
}
});
//points data
map.addSource("pointdata", {
type: "geojson",
data: 'data/points.geojson',
cluster: true,
clusterRadius: 20
});
map.addLayer({
"id": "points",
"type": "circle",
"source": "pointdata",
"paint": {
'circle-color': 'rgba(255, 255, 46, 1.0)',
'circle-radius': 8
}
});
});
map.addControl(new mapboxgl.NavigationControl());
});
geofence();
function geofence(){
var ptsWithin = turf.within(points, fence);
}
You have your points as GeoJSON, and your polygon as GeoJSON - so, yes, you can use TurfJS to find out which points are within the polygon. It looks like the code you've proposed is correct. The fact you're using Mapbox is irrelevant to this particular task.
If you're experiencing a problem with this approach, indicate it in your question.
Try to add the geofence() function inside the map on-load function after adding those layers, By that way you can make sure that the geofence() function is called after the layers have been loaded
map.on('load', function () {
//geofence data
map.addSource('fencedata', {
type: 'geojson',
data: 'data/fence.geojson'
});
map.addLayer({
id: 'fence',
type: 'fill',
"source": "fencedata",
'layout': {},
'paint': {
'fill-color': '#FF0000',
'fill-opacity': 0.3
}
});
//points data
map.addSource("pointdata", {
type: "geojson",
data: 'data/points.geojson',
cluster: true,
clusterRadius: 20
});
map.addLayer({
"id": "points",
"type": "circle",
"source": "pointdata",
"paint": {
'circle-color': 'rgba(255, 255, 46, 1.0)',
'circle-radius': 8
}
});
geofence();
});
map.addControl(new mapboxgl.NavigationControl());
});
function geofence() {
var ptsWithin = turf.within(points, fence);
}
I have a Tornado chart like the one below:
This chart has a baseline at 29.5, and it's fiddle is here.
series:[{
name: 'Low',
grouping:false,
type:'bar',
data:[
{y:12.15-baseValue, label:10},
{y:15.45-baseValue, label:1},
{y:31.25-baseValue, label:2},
{y:12.15-baseValue, color:'#99CCFF', label: ""},
],
labels:[10,5,1,2,]
},{
name: 'High',
grouping:false,
type:'bar',
data:[
{y:46.86-baseValue, label:30},
{y:42.28-baseValue, label:3},
{y:27.77-baseValue, label:4},
{y:46.86-baseValue, color:'#99CCFF', label:""},
],
labels:[30,10,3,4,]
},
{
name: 'Median',
type: 'scatter',
data: [
null,
null,
null,
27-baseValue
],
marker: {
lineWidth: 2,
lineColor: Highcharts.getOptions().colors[3],
fillColor: 'white'
}
}]
I am trying to add a shadow chart of a second Tornado, where the baseline can be different. For instance, consider four more bars, shifted to the right, in the mockup shown below:
I have been stuck at this because the shadow bars only show relative to the baseValue of the first chart (29.5), and not to the baseValue of the second chart (39.5). So if I try to add them into the existing series, they will work only if the values are in the same direction (as in value-baseValue has the same sign as the original data).
To illustrate, suppose the shadow chart has the following data:
Annual Revenue: 25, 39.5, 55
Number of Years: 33, 39.5, 48
Annual Costs: 35, 39.5, 48
Combined Uncertainty: 23,43,55
How do I add this to the code in the fiddle above and make it look like the mockup? Here is a modified fiddle that does not work.
series:[{
name: 'Low',
grouping:false,
type:'bar',
data:[
{y:12.15-baseValue, label:10},
{y:25-baseValue, label:50},
{y:15.45-baseValue, label:1},
{y:33-baseValue, label:20},
{y:31.25-baseValue, label:2},
{y:48-baseValue, label:8},
{y:12.15-baseValue, color:'#99CCFF', label: ""},
{y:40-baseValue, color:'#99DDDD', label: ""}
],
labels:[10,50,1,20,2,8]
},{
name: 'High',
grouping:false,
type:'bar',
data:[
{y:46.86-baseValue, label:30},
{y:55-baseValue, label:70},
{y:42.28-baseValue, label:3},
{y:48-baseValue, label:30},
{y:27.77-baseValue, label:4},
{y:35-baseValue, label:5},
{y:46.86-baseValue, color:'#99CCFF', label:""},
{y:80-baseValue, color:'#99DDDD', label: ""}
],
labels:[30,70,3,30,4,5,]
},
{
name: 'Median',
type: 'scatter',
data: [
null,
null,
null,
null,
null,
null,
27-baseValue,
60-baseValue
],
marker: {
lineWidth: 2,
lineColor: Highcharts.getOptions().colors[3],
fillColor: 'white'
}
}]
The problems are annotated in the image below:
If you want to have point with 0/origin in different position that rest of series - then instead you should use different series and add hidden another horizontal axis (in your code it will be y-axis because of invert caused by bar charts).
To synchronize those axes you can set proper max and min on axes.
Example: http://jsfiddle.net/frgo4Lun/3/
OR
You can use threshold http://api.highcharts.com/highcharts#plotOptions.bar.threshold.
Example: http://jsfiddle.net/frgo4Lun/4/
You have also posted image with series on between of ticks. You can set x position of point to not round values like 1.5.
Example: http://jsfiddle.net/frgo4Lun/5/