Trying to retrieve part of a district, however for some reason cannot see the whole area, even if zoom level is at 0, where (supposedly) we should see the whole world.
I am using L.CRS.Simple because this uses the EPSG:3763 and cannot see that one on the CRS list. I am retrieving the data in JSON cause when tying with geoJSON, was not able to transform the 3D coordinates data into 2D planes ones.
const queryRegionText = "where=OBJECTID > 0"
const geoJsonURL2 = "https://sig.cm-figfoz.pt/arcgis/rest/services/Internet/MunisigWeb_DadosContexto/MapServer/2/query?f=json&returnGeometry=true&geometryType=esriGeometryPolyline&spatialRel=esriSpatialRelIntersects&outFields=*&outSR=3763&" + queryRegionText
var map = L.map('mapid', {
crs: L.CRS.Simple
}).setView([-58216.458338, 42768.347232], 0);
L.control.scale({ metric: true }).addTo(map);
fetch(geoJsonURL2).then(function (response) {
response.json().then(function (data) {
data.features.forEach(element => {
if (element.geometry.rings) {
element.geometry.rings.forEach(point => {
L.polyline(point, { color: 'red' }).addTo(map);
})
}
});
});
});
var popup = L.popup();
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(map);
}
map.on('click', onMapClick);
<html>
<head>
<title>Leaflet - testing</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
</head>
<body>
<div id="mapid" style="width: 600px; height: 400px;"></div>
</body>
</html>
TL;DR: When creating the map, set the minimum zoom below zero. This should work:
var map = L.map('mapid', {
crs: L.CRS.Simple, minZoom: -6
}).setView([-57728, 55296], -6);
Explanation
Normally, Leaflet translates from a latitude/longitude coordinate system to screen pixels using an assumption that the world is 256 pixels high at Zoom level 0. At each higher Zoom Level, the number of pixels doubles (explained nicely in the Zoom levels tutorial). With this assumption, the options for the map default to {minZoom: 0, maxZoom: Infinity} (as you are not adding any Layer that sets these values to anything different).
When you use L.CRS.Simple, at Zoom level 0 it maps 1 coordinate unit to 1 screen pixel. Your data looks like it is about 18000 coordinate units tall, so it doesn't fit in your 400 pixel high map. To make it fit, we need each screen pixel to map to about 45 coordinate units. 2^5 is 32, and 2^6 is 64, so we need to zoom out between 5 and 6 times. Luckily, Leaflet accepts negative Zoom Levels, so setting zoom to -6 does the trick. But to make it work properly, you need to set {minZoom: -6}, so the map doesn't get stuck at zoom level 0. There's a good worked example in the Non-geographical Maps tutorial.
Using L.CRS.Simple should work for you, so long as the approximation holds that each latitude unit is the same length as each longitude unit (a square world). Since this isn't generally true in the real world, using the Simple projection will cause some distortion. If the distortion is significant for the features you are interested in, then you will need to look up how to use EPSG:3763 properly, using L.CRS and Proj4Leaflet, as suggested by #IvanSanchez.
So, after some reading on the proj4leaflet, come up with this code. Thanks in advance for the comments and the reply above.
const queryRegionText = "where=OBJECTID > 0"
const geoJsonURL2 = "https://sig.cm-figfoz.pt/arcgis/rest/services/Internet/MunisigWeb_DadosContexto/MapServer/2/query?f=geojson&returnGeometry=true&geometryType=esriGeometryPolyline&spatialRel=esriSpatialRelIntersects&outFields=*&outSR=3763&" + queryRegionText
const map = L.map('map', {
center: [40.14791, -8.87009],
zoom: 13
});
proj4.defs("EPSG:3763", "+proj=tmerc +lat_0=39.66825833333333 +lon_0=-8.133108333333334 +k=1 +x_0=0 +y_0=0 +ellps=GRS80 +units=m +no_defs");
fetch(geoJsonURL2).then(function (response) {
response.json().then(function (data) {
L.Proj.geoJson(data).addTo(map);
});
});
var popup = L.popup();
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(map);
}
map.on('click', onMapClick);
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<link rel="stylesheet" href="main.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.4/proj4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4leaflet/1.0.2/proj4leaflet.js"></script>
</head>
<body class="">
<div id="map" style="width: 600px; height: 400px;"></div>
</div>
<script src="main.js"></script>
</body>
The content in the popup created through the variable "popupCustom" is displaying string instead of referencing the specified field {IN_COUNTRY}. I followed the ArcGIS JS API Popup Tutorials, & can't see what my error is in failing to grab the attributes associated with that field. Here's the code -- any help is greatly appreciated!
*note: feature layer url within "Cyber_Areas" variable points to REST URL for referenced Feature Class.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Search widget with multiple sources - 4.6</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.6/esri/css/main.css">
<script src="https://js.arcgis.com/4.6/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/BasemapToggle",
"esri/widgets/Legend",
"esri/layers/TileLayer",
"esri/layers/FeatureLayer",
"esri/widgets/Search",
"esri/widgets/LayerList",
"esri/PopupTemplate",
"dojo/on",
"dojo/domReady!"
], function(
Map,
MapView,
BasemapToggle,
Legend,
TileLayer,
FeatureLayer,
Search,
LayerList,
PopupTemplate,
on
) {
var Cyber_Areas = new FeatureLayer({
url: "*inserturl*",
outFields: ["IN_COUNTRY"],
popupTemplate: popupCustom
});
var map = new Map({
basemap: "osm"
});
map.add(Cyber_Areas);
var view = new MapView({
container: "viewDiv",
map: map,
center: [-87.172865, 34.077613], // lon, lat
zoom: 16
});
var searchWidget = new Search({
view: view,
popupOpenOnSelect: false
});
view.ui.add(searchWidget, {
position: "top-left",
index: 0
});
var popupCustom = searchWidget.on('select-result', function(evt){
//console.info(evt);
view.popup.open({
location: evt.result.feature.geometry, // location of the click on the view
title: "Service Availability:", // title displayed in the popup
content: "<p><b>{IN_COUNTRY}"
});
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
From your code you are mixing the popup template value with when to display it. And those are two different things.
First, you are not setting correctly the popup template of the layer. It should be a PopupTemplate.
It seems to me that in you code the layer definition should be something like this,
var Cyber_Areas = new FeatureLayer({
url: "*inserturl*",
popupTemplate: {
outFields: ["IN_COUNTRY"],
title: "Service Availability:",
content: "<p><b>{IN_COUNTRY}</b></p>"
}
});
Now if you don't want the default behavior of the popup (left click on a feature), you cant disable it like this,
view.popup.autoOpenEnabled = false; // <- disable view popup auto open
And then you can open it wherever you want like this,
view.popup.open({ // <- open popup
location: evt.result.feature.geometry, // <- use map point of the event result
fetchFeatures: true // <- fetch the selected features (if any)
});
You have to understand that the fields you use in the content of the popup template are related to the layer. That is why i set in the popup of the view to fetch the results.
I am trying to plot a zing chart in angular2. My chart comes out to be like this.
While I want my chart to look like the one I provided below, so that the min and max values of the x-axis are auto adjusted to fit to the area and horizontal width of the chart.
How can I go about doing this? I followed these links but could not get the desired results. Could you point where am I going wrong ?
https://www.zingchart.com/docs/tutorials/chart-elements/configure-chart-scales/#scale-formatting
The options that I gave to plot the chart as follows:
this.charts = [{
id : 'chart-1',
data : {
'type' : 'area',
'scaleX': {
'label': {'text': 'Price'}
},
'scaleY': {
'label': {'text': 'Cumulative Volume'}
},
'plotarea': {
'adjust-layout': true /* For automatic margin adjustment. */
},
'scale-x': {
'auto-fit': true,
'min-value': minValue,
'max-value': maxValue,
'decimals': 2
},
'series': [
{ 'values': this.bidArray },
{ 'values': this.askArray }
],
},
height: 300,
width: 600
}];
}
Edit 1:
bidArray and askArray are of the format array of arrays.
You do not need to set the attribute auto-fit true. This is for charts that have zooming applied.
You do not need to set the attributes min-value or max-value to get the x-axis to fit automatically. It will do this by default.
The problem might lie in the one part of the chart you didn't give any information about. How is your data plotted? What are the value arrays? Array of Arrays?
Post the full chart JSON and I'll get you a demo working. Since your chart is dynamic you can grab the rendering JSON by right clicking on the chart, clicking the View Source option, then copying the contents from the parsed JSON tab.
EDITED NEW ANSWER IN RESPONSE TO FIRST COMMENT BELOW:
Array of arrays does not automatically fit the graph width on scaleX. The reason for this is you are requesting to plot something much more specific than a single dimensional array. So you are right to set the minValue and maxValue.
The main issue is the step value. Since you have defined a step that is less precise than values in the minvalue or maxvalue you must make it match the same precision. For example you put two decimals, execpt your step is set to step:.2 which is only of precision of one decimal. Change that precision to two. step:.01 || .02 to get the desired results you are looking for.
One quick side note. You have two scale-x objects. They get merged internally, but this is dangerous because the lower one will override the first. If you have a large JSON this becomes harder to debug.
demo link
var myConfig = {
"graphset":[
{
"type":"area",
"title":{
"text":"Market Depth",
"font-size":14,
"offset-x":-200,
"offset-y":-5
},
"scaleY":{
"label":{
"text":"Cumulative Volume"
}
},
"plotarea":{
"adjust-layout":true
},
"scale-x":{
"min-value":10.091,
"max-value":11.308,
"step": .01,
"decimals":2,
"label":{
"text":"Price"
}
},
"series":[
{
"values":[[10.091,23128.285630000002],
[10.092,22272.984500000002],
[10.094,22070.219080000003],
[10.118,21630.372470000002],
[10.145,21278.48053],
[10.169,20438.89872],
[10.209,19798.506260000002],
[10.218,19128.53049],
[10.293,18200.525190000004],
[10.316,17625.84755],
[10.341,16860.282690000004],
[10.352,16752.07929],
[10.363,15806.925830000002],
[10.366,15351.489590000001],
[10.372,15088.74344],
[10.393,14793.26244],
[10.401,13968.11667],
[10.423,13873.98204],
[10.456,13655.87469],
[10.476,12866.84064],
[10.535,12518.24981],
[10.602,12503.24074],
[10.623,11940.5453],
[10.632,11939.08057],
[10.634,11838.884329999999],
[10.663,11074.893349999998],
[10.663,10963.316989999998],
[10.666,10584.14343],
[10.667,10358.20835],
[10.671,9942.126730000002],
[10.672,9265.449410000001],
[10.674,8497.838590000001],
[10.679,7865.162790000001],
[10.694,7349.383660000001],
[10.713,6672.761850000002],
[10.736,6026.31731],
[10.741,5674.348190000001],
[10.752,5186.775390000001],
[10.759,4317.745790000001],
[10.807,3807.78019],
[10.827,3638.4528899999996],
[10.831,2816.4248099999995],
[10.834,2426.4046799999996],
[10.854,2423.4017],
[10.854,2184.2459999999996],
[10.855,1448.32144],
[10.856,481.7664500000001],
[10.865,92.60541],
[10.87,59.9149],
[10.874,10.04495]],
backgroundColor: '#424242',
alphaArea:.56,
lineColor: '#424242',
marker: {
backgroundColor:'#424242',
visible:true
}
},
{
"values":[[11.308,26417.464129999997],
[11.285,26220.324189999996],
[11.208,25644.388599999995],
[11.194,25628.031659999997],
[11.188,25031.713569999996],
[11.182,24205.770269999997],
[11.144,23534.17388],
[11.142,22947.082829999996],
[11.113,22639.772689999994],
[11.105,22536.636229999993],
[11.09,21987.267979999993],
[11.087,21137.004579999997],
[11.084,20341.394259999997],
[11.075,19372.91412],
[11.074,18554.458],
[11.064,17632.22014],
[11.053,17063.184230000003],
[11.05,16285.860740000004],
[11.033,15644.169050000006],
[11.022,15330.170840000004],
[11.018,14424.291480000005],
[11.007,13641.930940000004],
[11.001,12755.045610000003],
[10.999,12266.619580000002],
[10.992,12034.113860000001],
[10.981,11362.05282],
[10.98,10739.11108],
[10.977,9945.179989999999],
[10.976,8958.965719999998],
[10.974,8579.633059999998],
[10.972,8124.936529999999],
[10.966,7918.067119999999],
[10.964,7038.952039999999],
[10.962,6756.983329999999],
[10.96,6028.072429999998],
[10.955,5516.051169999999],
[10.946,4738.703779999999],
[10.943,4436.934409999999],
[10.941,4417.186269999998],
[10.94,4120.44594],
[10.939,3830.56787],
[10.925,3414.84425],
[10.923,3335.96724],
[10.922,3025.91816],
[10.92,2119.4797900000003],
[10.908,1469.96346],
[10.903,1269.4567200000001],
[10.892,630.18796],
[10.891,273.01724],
[10.89,103.07879]],
backgroundColor: '#c62828',
alphaArea:.56,
lineColor: '#c62828',
marker: {
backgroundColor:'#c62828',
visible:true
}
}
]
}
]
};
zingchart.render({
id: 'myChart',
data: myConfig,
height: '100%',
width: '100%'
});
html, body {
height:100%;
width:100%;
margin:0;
padding:0;
}
#myChart {
height:100%;
width:100%;
min-height:150px;
}
.zc-ref {
display:none;
}
<!DOCTYPE html>
<html>
<head>
<script src= "https://cdn.zingchart.com/zingchart.min.js"></script>
</head>
<body>
<div id="myChart"><a class="zc-ref" href="https://www.zingchart.com">Powered by ZingChart</a></div>
</body>
</html>
In my previous post 'Leaflet JS - changing esri shape into marker on certain zoom level
' I was able to resolve an issue which i had with the leaflet JS library and changing the polygon shapes to markers icons when hitting a certain zoom level.
I was advised by 'Ivan Sanchez' to use the 'Leaflet.Deflate' plugin and this works like a charm, so now the various shapes are being transformed into markers after a certain zoomlevel, however now I'm struggling to change the default leaflet marker icon to a custom marker icon, so my question now is:
Is it possible to change the default marker icon to a custom marker icon while using the 'Leaflet.ShapeFile' and 'Leaflet.Deflate' plugin and what would be the best approach to do this?
I wanted to make a JSFiddle, but I don't JSFiddle allows me to attach the zip file contains the shapefiles, so I will post the code I have got so far below here, thanks for your help, advise and support:
<!doctype html>
<html lang="en">
<head>
<meta charset='utf-8' />
<title>v4</title>
<link rel="stylesheet" type="text/css" href="lib/leaflet/leaflet.css" />
<!--[if lte IE 8]> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.4/leaflet.ie.css" /> <![endif]-->
<link rel="stylesheet" type="text/css" href="lib/leaflet/L.Control.Sidebar.css" />
<style>
html { height: 100% }
body { height: 100%; margin: 0; padding: 0; }
#map { height: 100% }
</style>
</head>
<body>
<div id="map"></div>
<script src="lib/jquery/jquery-3.1.1.min.js"></script>
<script src="lib/leaflet/leaflet.js"></script>
<script src="lib/leaflet/catiline.js"></script>
<script src="lib/leaflet/leaflet.shpfile.js"></script>
<script src="lib/leaflet/shp.js"></script>
<script src="lib/leaflet/L.Control.Sidebar.js"></script>
<script src="lib/leaflet/L.Deflate.js"></script>
<script>
// init map
var m = L.map('map').setView([52.472833, 1.749609], 15);
// clicking on the map will hide the sidebar plugin.
m.on('click', function () {
sidebar.hide();
});
// init Deflate plugin
L.Deflate({ minSize: 10 }).addTo(m);
// Init side bar control
var sidebar = L.control.sidebar('sidebar', { closeButton: true, position: 'right' });
m.addControl(sidebar);
// Init esri shape file via leaflet.shapefile, shp.js plugin
var businessProperties = new L.Shapefile('data/businessshapes.zip', { style: propertyStyle, onEachFeature: propertyOnEachFeature }).addTo(m);
// create on-click Feature
function propertyOnEachFeature(feature, layer) {
layer.on( {
mouseover: highlightFeature,
mouseout: resetHighlight,
click: function populate() {
sidebar.toggle();
document.getElementById('pinfoHeader').innerHTML = "<h2>" + feature.properties.Building + " - Detailed Information</h2><br />";
document.getElementById('pTitle').innerHTML = "Name: " + feature.properties.Building
document.getElementById('pDetails').innerHTML = "SHAPE_Leng: " + feature.properties.SHAPE_Leng + "<br/ >SHAPE_Area: " + feature.properties.SHAPE_Area
}, highlightFeature, zoomToFeature
});
}
// style the properties style
function propertyStyle(feature) {
return {
fillColor: getPropertyColor(feature.properties.BusType),
weight: 2,
opacity: 1,
color: 'white',
dashArray: 3,
fillOpacity: 0.7
}
}
// set color per property according to the data table of the Esri Shape file.
function getPropertyColor(propStatus) {
if (propStatus == 'TypeA') {
return 'red';
} else if (propStatus == 'TypeB') {
return 'green';
} else {
return 'yellow';
}
}
// set the highlighted color for polygon
function highlightFeature(e) {
var layer = e.target;
layer.setStyle( {
weight: 2,
color: 'black',
fillColor: 'white',
fillOpacity: 0.2
});
if (!L.Browser.ie && !L.Browser.opera) {
layer.bringToFront();
}
}
// reset the highlighted color for polygon after mouse leave polygon
function resetHighlight(e) {
businessProperties.resetStyle(e.target);
}
//Extend the Default marker class to overwrite the leaflet.deflate marker icon???
var TestIcon = L.Icon.Default.extend({
options: {
iconUrl: 'assets/images/markers/business.png'
}
});
var testIcon = new TestIcon();
businessProperties.addTo(m);
// Init base maps for switch
var grayscale = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', { id: 'MapID', attribution: 'Map maintained by Demo LTD, — Map data © OpenStreetMap,' }).addTo(m);
var streets = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { id: 'MapID', attribution: 'Map maintained by Demo LTD, — Map data © OpenStreetMap,' });
var baseMaps = {
"Streets": streets,
"Grayscale": grayscale
};
// Init overlay map switch
var overlayMaps = {
"Bussines Properties": businessProperties
};
// Add switches to map control
L.control.layers(baseMaps, overlayMaps).addTo(m);
</script>
</body>
</html>
Is it possible to change the default marker icon to a custom marker icon while using the 'Leaflet.Deflate' plugin?
The answer is: No.
The current code for Leaflet.Deflate uses a default marker and a default marker only, see https://github.com/oliverroick/Leaflet.Deflate/blob/991f51ca82e7bb14a17c8d769b4c378c4ebaf700/src/L.Deflate.js#L42
You could hack your way around it, but I would rather recommend filing a feature request in the Leaflet.Deflate repo. It should be possible to modify the Leaflet.Deflate repo to allow line/polygon features to have some extra properties to be used as marker options.
If we specify the content of crosshairX in the 'plotarea' attribute, by default the color of whole text becomes black. I want to represent this text of crosshair in two different colors. For example, suppose my text is "2016 : 0.07 M", then '2016' should appear in blue color and '0.07 M' in red.
How can we achieve this?
Full Disclosure, I'm a member of the ZingChart team.
I would need to know how you are displaying your text to have a more specific solution. Are you using the default plotLabel.text or do you have a user defined plotLabel.text? If so what is it set to?
Without knowing what you have defined for text I have taking the liberty to put together a demo of the different combinations of applying colors and text to a plotLabel.
There are a couple things happening here:
headerText is defining its text color as grey
the first span tag in text is inheriting the plot color with %color
the second span tag in text is defining its text color as black
the plotLable.color attribute is red making all other text outside of the span tags red
var myConfig = {
type: "line",
scaleX:{
values:['Mon','Tue','Wed','Th','Fri','Sat','Sun']
},
crosshairX:{
plotLabel:{
headerText:'<span style="color:#777">Header Text</span>',
text:'<span style="color:%color">%kv</span>: <span style="color:black">%v</span> Extra Text...',
color:'red'
}
},
series : [
{
values : [35,42,67,89,25,34,67]
},
{
values : [35,42,67,89,25,34,67].sort()
}
]
};
zingchart.render({
id : 'myChart',
data : myConfig,
height: 350,
width: '100%'
});
<!DOCTYPE html>
<html>
<head>
<!--Assets will be injected here on compile. Use the assets button above-->
<script src= "https://cdn.zingchart.com/zingchart.min.js"></script>
<script> zingchart.MODULESDIR = "https://cdn.zingchart.com/modules/";</script>
<!--Inject End-->
</head>
<body>
<div id='myChart'></div>
</body>
</html>