MapBox GL JS Setup Sprites for Icon Properties - geojson

I am having difficulty wrapping my head around MapBox GL. I am coming from a Leaflet background, and am finding some of the abstractions hard to understand.
I work with a lot of GPS trip log data, and need to do things like display a fragment of a trip, hilight a section of it in a color, put markers on it with custom pins. Another common function is to mark all units on a map with pins that differ by some status. eg: Last Reported, Fuel Level, etc.
To create markers, I currently have a helper objectthat spits out some js.
public string EmitJs()
{
Debug.WriteLine("Emit Marker");
StringBuilder sb = new StringBuilder();
sb.AppendFormat("var container{0} = document.createElement('div');", UniqueId).AppendLine();
sb.AppendFormat("container{0}.className = '{1}';", UniqueId, ContainerCss).AppendLine();
sb.AppendFormat("var popup{0} = new mapboxgl.Popup({{ offset: 25 }}).setHTML(", UniqueId).AppendLine(); // escape { } with {{ }} in String.Format
sb.AppendFormat(" \'{0}\'", Point.Label).AppendLine();
sb.AppendLine(");");
sb.AppendFormat("var marker{0} = new mapboxgl.Marker(container{1}, {{", UniqueId, UniqueId).AppendLine();
sb.AppendLine(" anchor: 'bottom'");
sb.AppendLine("})");
sb.AppendFormat(" .setLngLat({0})", Point.EmitForMapBox()).AppendLine();
sb.AppendFormat(" .setPopup(popup{0})", UniqueId).AppendLine();
sb.AppendLine(" .addTo(map);");
sb.AppendLine();
return sb.ToString();
}
this returns:
var container5 = document.createElement('div');
container5.className = 'marker marker-pu-green';
var popup5 = new mapboxgl.Popup({ offset: 25 }).setHTML(
'<p><b>Name:</b> 1310 PU2003<br /><b>Last Reported:</b> 25/03/2020 11:16:35<br /><b>Last Status:</b> Operating</p>'
);
var marker5 = new mapboxgl.Marker(container5, {
anchor: 'bottom'
})
.setLngLat([151.047211,-32.537003])
.setPopup(popup5)
.addTo(map);
This lets me display images overlaid on a map, governed by CSS. This is fairly straightforward.
The GeoJson FeatureCollection, contains Feature's that represent individual markers. I can see that the icon properties in the Layer object are meant to represent named values in some spritesheet, but damned If I can figure where this is, and how to upload to it. I've been all thru Studio, and its documentation. It seems to refer to to a 'sprites': 'path to file' json property that you can't actually set or upload.
In addition, it wants the sprites to be in SVG format., despite casting them back to raster as PNG. Thats a different question, but I need to convert a bunch of PNG's to SVG format as a result, if I ever get this working.
The Question
How do I add custom sprites to my MapBox style so I can reference them in GeoJson icon properties.
** Edit 27 Mar 202 **
The following is cut from the page. The polylines are not included (they work well), just the lines to try an make a symbol layer work. The image paths are local to my dev environment and are valid. They would be rewritten when moved to prod.
<script id="mapScript" type="text/javascript">
var baseUrl = '/';
mapboxgl.accessToken = '[snip]';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/fleetlogixmaps/ck6r4knm10smq1irxvnvfmq1b',
center: [148.381332397461,-21.4777641296387],
setMinZoom: 13,
setMaxZoom: 18,
zoom: 15,
});
map.loadImage('http://localhost:7933/Images/pin_path_start_128x128.png', function(error, image) {
if (error) throw error;
map.addImage('pathStart', image);
});
map.loadImage('http://localhost:7933/Images/pin_path_end_128x128.png', function(error, image) {
if (error) throw error;
map.addImage('pathEnd', image);
});
map.loadImage('http://localhost:7933/Images/pin_event_start_128x128.png', function(error, image) {
if (error) throw error;
map.addImage('eventStart', image);
});
map.loadImage('http://localhost:7933/Images/pin_event_end_128x128.png', function(error, image) {
if (error) throw error;
map.addImage('eventEnd', image);
});
var markers = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates':
[148.370483398438,-21.4804000854492],
'properties': {
'title': 'Path Start',
'icon': 'pathStart'
}
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates':
[148.381332397461,-21.4777641296387],
'properties': {
'title': 'Event Start',
'icon': 'eventStart'
}
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates':
[148.385375976563,-21.4819965362549],
'properties': {
'title': 'Event End',
'icon': 'eventEnd'
}
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates':
[148.393402099609,-21.4885864257813],
'properties': {
'title': 'Path End',
'icon': 'pathEnd'
}
}
}
]
};
map.on('load', function() {
map.addLayer({
'id': 'markers',
'source': 'markerSrc',
'type': 'symbol',
'layout': {
'icon-image': ['get', 'icon'],
'icon-size': 0.25,
},
});
});
</script>

You're confusing Markers (HTML elements that sit over the map) with Symbol layers (images that exist within the map, tied to a source like a GeoJSON).
Markers don't have anything to do with Sprites: you style them with CSS. See this example.
If you do want to use a Symbol layer, the easiest way to use custom images is to upload them to Mapbox Studio, which will generate the Sprite file for you.
Alternatively, you can use loadImage to load images dynamically.

Related

Get icon url from geojson in mapbox gl

I have this geojson
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"geometry":{
"type":"Point",
"coordinates":[
-75.70439994335175,
4.72285137053331
]
},
"properties":{
"category":"pajaros",
"icon":{
"iconUrl":"http:\/\/tupale.co\/milfs\/images\/secure\/?file=150\/b93a3b673df42a1eb5ca85ffcfa21389.jpg\u002674",
"iconSize":[
60
]
},
"563":"",
"564":"b93a3b673df42a1eb5ca85ffcfa21389.jpg",
"567":"-75.70439994335175 4.72285137053331 18",
"title":"Semillero andino ( hembra )",
"566":"Semillero andino ( hembra )",
"localizacion":"-75.70439994335175 4.72285137053331 18 ",
"description":"Contenido del json",
"control":"024a69ad3b495e5c323402211bc7aa97",
"latLng":[
-75.70439994335175,
4.72285137053331
],
"time":1467590201,
"name":1480263964
}
}
]
}
And this function
/**
* This is where your '.addLayer()' used to be, instead
* add only the source without styling a layer
*/
map.addSource('places', {
'type': 'geojson',
// 'data': stores
'data': 'http://localhost/tupali/cache/45.json'
});
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'places',
'layout': {
// get the icon name from the source's "icon" property
// concatenate the name to get an icon from the style's sprite sheet
'icon-image': ['concat', ['get', 'iconUrl'], '-15'],
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': ['Open Sans Semibold', 'Arial Unicode MS Bold'],
'text-offset': [0, 0.6],
'text-anchor': 'top'
}
});
});
How i can get the iconUrl and icon size from geojson ?
i try " 'icon-image': ['concat', ['get', 'icon'], '-15'],"
but get any array and I don't how explode it.
" Image "{"iconUrl":"http://localhost//tupali/milfs/images/secure/?file=150/e1b0013409d0ed4a67c292999928c295.jpg&74","iconSize":[60]}" could not be loaded. "
Mapbox-GL-JS can't load images by URL in this way. You need to first add the images you need, using map.loadImage() and map.addImage().
https://docs.mapbox.com/mapbox-gl-js/api/#map#loadimage

how to upload image server side in ionic 2 / 3

I'm building an app with Ionic 2. I need to take a photo from gallery or camera and upload this picture to my server.
I have this code that opens the Gallery and takes a picture.
accessGallery() {
this.camera.getPicture({
sourceType: this.camera.PictureSourceType.SAVEDPHOTOALBUM,
destinationType: this.camera.DestinationType.DATA_URL
}).then((imageData) => {
this.base64Image = 'data:image/jpeg;base64,' + imageData;
this.uploadFile();
}, (err) => {
console.log(err);
});
}
upload image to server side
uploadFile() {
let body = new FormData();
body.append('images', this.base64Image);
let headers = new Headers({
'token': this.token,
'sid': this.sid,
'user': this.user,
'to': this.to,
'node': this.node,
'type':'image'
});
let options = new RequestOptions({ headers: headers });
console.log("header ----" +JSON.stringify(headers));
console.log("images data body----" +JSON.stringify(body));
this.http.post(this.apiurl,body,options)
.map(res => res.json())
.subscribe(
data => {
console.log(data);
},
err => {
console.log("ERROR!: ", err);
}
);
}
ERROR :- Field value too long
As the error description clearly suggests, it seems you are trying to pass a value to one of your mysql table's field which is smaller than the value you are trying to pass.
Try outputting your options array and cross check each of its value against the respective db field and if you find any discrepancy modify the respective field length accordingly.
Hope this helps!

Fetching all the Project Name for a Project Cumulative Flow Chart in Rally

I am generating a Project Cumulative Flow Chart, which is based on the Project name that I fetch using a "find," however I can't get it working.
Here is the Problem:
1) The "Find" in my code is just fetching one kind of project name, "FE," however, I have a lot of other Project name such as FE, BE, VisualRF, etc. I am not sure what's going on
2) I return this to "storeConfig" inside the chart and then I want try to give "Name" to the "stateFieldName." This is not working! I don't see any graph at all.
Here is the code.
_chart2: function() {
var projectName = this.getContext().getProject()._refObjectName;
console.log("========");
console.log(projectName); <<<<<<<<<< This always prints one name'FE' (My project name are FE, BE, etc)
this.chart = {
xtype: 'rallychart',
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: this._getStoreForChart2(),
calculatorType: 'Rally.example.CFDCalculator',
calculatorConfig: {
stateFieldName: this.getContext().getProject()._refObjectName, <<<<< I think usage is not fetching name of all projects
stateFieldValues: ['FE','BE','VisualRF']
},
width: 1000,
height: 600,
chartConfig: this._getChart2Config()
};
this.chartContainer.add(this.chart);
},
_getStoreForChart2: function() {
var obj1 = {
find: {
_TypeHierarchy: { '$in' : [ 'Defect' ] },
Children: null,
_ProjectHierarchy: this.getContext().getProject().ObjectID,
_ValidFrom: {'$gt': Rally.util.DateTime.toIsoString(Rally.util.DateTime.add(new Date(), 'day', -30)) },
State: "Open",
},
fetch: ['Severity','Project','ObjectID','FormattedID'],
hydrate: ['Severity','Project','ObjectID','FormattedID'],
sort: {
_ValidFrom: 1
},
context: this.getContext().getDataContext(),
limit: Infinity,
val: this.Name,
};
return obj1;
},
Though this should not matter but here is the code for the high chart function I am calling above
_getChart2Config: function() {
console.log("starting chart config");
return {
chart: {
zoomType: 'xy'
},
title: {
text: 'Chart2'
},
xAxis: {
tickmarkPlacement: 'on',
tickInterval: 20,
title: {
text: 'Date'
}
},
yAxis: [
{
title: {
text: 'Count'
}
}
],
plotOptions: {
series: {
marker: {
enabled: false
}
},
area: {
stacking: 'normal'
}
}
};
},
Down below you can see 'FE' getting printed:
Thanks a lot!
Kay
stateFieldName is the field which is used to calculate the CFD- usually ScheduleState or a custom dropdown field like KanbanState that captures your process. The stateFieldValues should be the values of that field (Defined, In-Progress, Accepted, Completed, etc.) This doesn't deal with projects at all. Definitely remember to include that field in your hydrate and fetch as well.

Add multiple data points to a series

I am trying to build a chart from JS that has multiple "y:" data points in multiple series. I have got the chart working fine using a static configuration, but am struggling to get it to work when adding the points via the API.
I am trying to acheive:
'series':[
{
'name':'Series 1',
'color':'#FF8500',
'data':[
{
'y':1.0002193448599428
},
{
'y':0.4999027241865406
},
{
'y':4.499986649534549
},
{
'y':0.4998817439627601
}
]
},
{
'name':'Series 2',
'color':'#66B3FF',
'data':[
{
'y':12.99999999901047
},
{
'y':13.00000000082946
},
{
'y':18.99999999841384
},
{
'y':5.000000001018634
}
]
},
My code so far looks like this:
var options = {
'chart':{
'renderTo':'MyChart',
'zoomType':'xy',
'defaultSeriesType':'bar',
'width':880
},
<snip>
...
</snip>
'yAxis':{
'title':{
'text':'Seconds'
},
},
'xAxis':{
'title':{
'text':'Objects'
},
'categories': [],
'opposite':true
},
'series':[
{
'name':'Series 1',
'color':'#FF8500',
'data':[]
},
'series':[
{
'name':'Series 2',
'color':'#66B3FF',
'data':[]
}
]
};
options.chart.renderTo = targetdiv;
//Categories add perfectly here:
$.each(harfile.log.entries, function(i, val) {
options.xAxis.categories.push(val.request.url);
console.log(val.request.url);
});
$.each(harfile.log.entries, function(i, val) {
//need to do some logic to catch "-1" for all these values...
options.series[0].data.push("y:" + val.timings.receive);
});
$.each(harfile.log.entries, function(i, val) {
//need to do some logic to catch "-1" for all these values...
options.series[1].data.push(y:" + val.timings.receive);
});
console.log(options.series[0].data);
This produces a "TypeError: Cannot call method 'push' of undefined"
Just use Highcharts API's series.addPoint().

Parsing ALL Highcharts Options from JSON

I am currently wanting to specify all Highcharts chart options via a JSON file. I've seen plenty of examples on how to pull just the data series from JSON and understand that.
Here is an example of some chart options that I would like to convert to JSON
var optionsChart2 = {
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: 'Year End Rating: Distribution'
},
xAxis: {
categories: [
'Ineffective',
'Inconsistent',
'Proficient',
'Advanced',
'Exceptional'
]
},
yAxis: {
min: 0,
title: {
text: 'Percentage'
}
},
series: [{data: 25,50,65,32,78}]
};
What is the best JSON format for that (for the purpose of pulling in via AJAX and then parsing back into options)?
I've seen the following code for parsing just the data:
$.getJSON('data.json', function(data) {
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
How would I then use the new version of the JSON file (as above)?
I'm sorry if this is too vague. I'm relatively new to this and need some help!
Well, it should be valid json, not valid javascript.
So strip the var and start immediately with the opening brace, remove the ; at the end and add double quotes around each property name.
So it looks like this:
{
"chart" : { ...
...
}
Then do the same as your example, just pass the response as is to the HC constructor:
$.getJSON( 'options.json', function( options ) {
new Highcharts.Chart(options);
});

Resources