Related
I’m working with Arcgis version 4.25 (javascript) and using cluster. I used the sample https://developers.arcgis.com/javascript/latest/sample-code/sandbox/?sample=featurereduction-cluster and want to show Browse Features content window on opening popup instead of showing summary.
How can I do that programmatically?
enter image description here
Basically, you have to query the layer view with the aggregatedId. The aggregated id is the objectId of the selected cluster feature.
Here I put an example for you using the esri sample you use as base. The key part, is when the CustomContent is render (the creator method).
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>
Point clustering - basic configuration | Sample | ArcGIS Maps SDK for
JavaScript 4.25
</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
background: rgba(50, 50, 50);
}
#infoDiv {
padding: 10px;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.25/esri/themes/dark/main.css" />
<script src="https://js.arcgis.com/4.25/"></script>
<script>
require([
"esri/Map",
"esri/layers/FeatureLayer",
"esri/layers/GeoJSONLayer",
"esri/views/MapView",
"esri/widgets/Legend",
"esri/widgets/Expand",
"esri/widgets/Home",
"esri/popup/content/CustomContent"
], (Map, FeatureLayer, GeoJSONLayer, MapView, Legend, Expand, Home, CustomContent) => {
const layer = new GeoJSONLayer({
title: "Earthquakes from the last month",
url: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson",
copyright: "USGS Earthquakes",
outFields: ["*"],
popupTemplate: {
title: "Magnitude {mag} {type}",
content: "Magnitude {mag} {type} hit {place} on {time}"
},
renderer: {
type: "simple",
field: "mag",
symbol: {
type: "simple-marker",
size: 4,
color: "#69dcff",
outline: {
color: "rgba(0, 139, 174, 0.5)",
width: 5
}
}
}
});
const baseLayer = new FeatureLayer({
portalItem: {
id: "2b93b06dc0dc4e809d3c8db5cb96ba69"
},
legendEnabled: false,
popupEnabled: false,
renderer: {
type: "simple",
symbol: {
type: "simple-fill",
color: [65, 65, 65, 1],
outline: {
color: [50, 50, 50, 0.75],
width: 0.5
}
}
},
spatialReference: {
wkid: 5936
}
});
const map = new Map({
layers: [baseLayer, layer]
});
const view = new MapView({
container: "viewDiv",
extent: {
spatialReference: {
wkid: 5936
},
xmin: 1270382,
ymin: -1729511,
xmax: 2461436,
ymax: -953893
},
spatialReference: {
// WGS_1984_EPSG_Alaska_Polar_Stereographic
wkid: 5936
},
constraints: {
minScale: 15469455
},
map: map
});
view.popup.viewModel.includeDefaultActions = false;
view.whenLayerView(layer).then(lv => {
const layerView = lv;
const customContentPromise = new CustomContent({
outFields: ["*"],
creator: (event) => {
const query = layerView.createQuery();
query.aggregateIds = [event.graphic.getObjectId()];
console.log(query);
return layerView.queryFeatures(query).then(result => {
console.log(result.features);
const contentDiv = document.createElement("div");
const featuresUl = document.createElement("ul");
let featureLi;
for (const feature of result.features) {
featureLi = document.createElement("li");
featureLi.innerText = `Magnitude ${feature.attributes.mag} ${feature.attributes.type} hit ${feature.attributes.place} on ${feature.attributes.time}`;
featuresUl.appendChild(featureLi);
}
contentDiv.appendChild(featuresUl);
return contentDiv
});
}
});
const clusterConfig = {
type: "cluster",
clusterRadius: "100px",
popupTemplate: {
title: "Cluster summary",
outFields: ["*"],
content: [customContentPromise],
actions: []
},
clusterMinSize: "24px",
clusterMaxSize: "60px",
labelingInfo: [
{
deconflictionStrategy: "none",
labelExpressionInfo: {
expression: "Text($feature.cluster_count, '#,###')"
},
symbol: {
type: "text",
color: "#004a5d",
font: {
weight: "bold",
family: "Noto Sans",
size: "12px"
}
},
labelPlacement: "center-center"
}
]
};
layer.featureReduction = clusterConfig;
const toggleButton = document.getElementById("cluster");
toggleButton.addEventListener("click", () => {
let fr = layer.featureReduction;
layer.featureReduction =
fr && fr.type === "cluster" ? null : clusterConfig;
toggleButton.innerText =
toggleButton.innerText === "Enable Clustering"
? "Disable Clustering"
: "Enable Clustering";
});
});
view.ui.add(
new Home({
view: view
}),
"top-left"
);
const legend = new Legend({
view: view,
container: "legendDiv"
});
const infoDiv = document.getElementById("infoDiv");
view.ui.add(
new Expand({
view: view,
content: infoDiv,
expandIconClass: "esri-icon-layer-list",
expanded: false
}),
"top-left"
);
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="infoDiv" class="esri-widget">
<button id="cluster" class="esri-button">Disable Clustering</button>
<div id="legendDiv"></div>
</div>
</body>
</html>
How can i modify the popupTemplate in esri? is it possible for me to modify the popupTemplate according to my design?
I have a popupTemplate
popupTemplate: {
content: [{
type: "fields",
fieldInfos: [{
fieldName: "Name"
}, {
fieldName: "Owner"
}, {
fieldName: "Length"
}]
}]
}
this is the result
what i want design
resource https://totalapis.github.io/sample-code/popup-custom-action/index.html
Update, I am having trouble on my react , when i clicked the icon there is no popup template show
useEffect(() => {
if (mapDiv.current) {
esriConfig.apiKey = process.env.ARCGIS_API;
const map = new Map({
basemap: 'arcgis-light-gray'
});
const view = new MapView({
center: [123.5504, 12.3574], // Longitude, latitude
container: mapDiv.current,
map: map,
zoom: 13, // Zoom level
});
view
.when((r) => {})
.then(() => {
mapDiv.current = view;
setMapView(view);
});
var list= [{
type: "fields",
fieldInfos: [{
fieldName: "Name "
}, {
fieldName: "Owner"
}, {
fieldName: "Length"
}]
},
{
type: "text",
text: "<div class=\"icontain\"></><a class=\"ic\"><i class=\"bi bi-star\"></i></a><a class=\"ic\"><i class=\"bi bi-geo-alt-fill\"></i></a></div>"
}]
var Stack= {
content: list
}
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/Beverly%20Hills%20Trees%20By%20Block/FeatureServer/0",
popupTemplate: Stack,
outFields: ["*"]
});
map.add(featureLayer);
}
}, []);
const displayLocation = (locations) => {
mapView.center = [
locations.data[0].geoCode.longitude,
locations.data[0].geoCode.latitude,
];
locations.data.map((location) => {
const point = new Graphic({
geometry: {
latitude: location.geoCode.latitude,
longitude: location.geoCode.longitude,
type: 'point',
},
symbol: LocationPin,
});
mapView.graphics.add(point);
});
};
return <div className="mapDiv layers" ref={mapDiv}></div>;
}
Hello, a quick solution to modify the Popup template is to add another object with text and text type properties to the template array. the text value will be html code where we will create a div that will show the icons, these with their respective css classes. The most is CSS. Here is an example of the Popup template:
popupTemplate: {[{
type: "fields",
fieldInfos: [{
fieldName: "Name "
}, {
fieldName: "Owner"
}, {
fieldName: "Length"
}]
},
{
type: "text",
text: "<div class=\"icontain\"></><a class=\"ic\"><i class=\"bi bi-star\"></i></a><a class=\"ic\"><i class=\"bi bi-geo-alt-fill\"></i></a></div>"
}]
}
I put an example of this code in operation already with the css, for a better compression. Your remaining task is to play with CSS to make the icon div responsive. For a better visualization of the example, run it in full screen. Another detail is that the example takes time to load due to the multiple CDNs that it needs
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"dojo/domReady!"
], function(Map, MapView, FeatureLayer) {
// Create the Map
var map = new Map({
basemap: "streets-navigation-vector"
});
var view = new MapView({
container: "mapDiv",
map: map,
center: [-118.399400711028, 34.08713590709093],
zoom: 16,
// Since there are many elements, it is best to dock the popup so
// the elements display better rather than have to scroll through them all.
popup: {
dockEnabled: true,
dockOptions: {
buttonEnabled: false,
breakpoint: false
}
}
});
var list= [{
type: "fields",
fieldInfos: [{
fieldName: "Name "
}, {
fieldName: "Owner"
}, {
fieldName: "Length"
}]
},
{
type: "text",
text: "<div class=\"icontain\"></><a class=\"ic\"><i class=\"bi bi-star\"></i></a><a class=\"ic\"><i class=\"bi bi-geo-alt-fill\"></i></a></div>"
}]
var Stack= {
content: list
}
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/Beverly%20Hills%20Trees%20By%20Block/FeatureServer/0",
popupTemplate: Stack,
outFields: ["*"]
});
map.add(featureLayer);
});
html,
body,
#mapDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.esri-popup__main-container{
border: solid 1px gray;
border-radius: 10px;
}
.icontain{
position: absolute;
top: 0;
height: 100%;
left: -17px;
display: flex;
flex-direction: column;
/* margin-top: auto; */
/* margin-bottom: auto; */
/* align-items: center; */
justify-content: center;
}
.ic{
border: solid 1px gray;
border-radius: 50%;
width: 33px;
height: 33px;
display: flex;
justify-content: center;
align-items: center;
background: white;
margin-top: 4px;
margin-bottom: 4px;
}
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"
/><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons#1.7.2/font/bootstrap-icons.css">
<title>Multiple popup elements - 4.4</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.4/esri/css/main.css">
<link rel="stylesheet" href="https://js.arcgis.com/4.4/dijit/themes/claro/claro.css">
<script src="https://js.arcgis.com/4.4/"></script></head>
<body>
<div id="mapDiv"></div>
</body>
</html>
Update
run this code in your environment. The popup should appear, you should only add the styles
useEffect(() => {
if (mapDiv.current) {
esriConfig.apiKey = process.env.ARCGIS_API_KEY;
const map = new Map({
basemap: 'arcgis-light-gray', // Basemap layer service
// portalItem:{
// id: "2d11c8164ce04843a38bfde68e00e6e7"
// }
});
const view = new MapView({
center: [123.5504, 12.3574], // Longitude, latitude
container: mapDiv.current,
map: map,
zoom: 13, // Zoom level
});
view
.when((r) => {})
.then(() => {
mapDiv.current = view;
setMapView(view);
});
}
}, []);
const displayLocation = (locations) => {
mapView.center = [
locations.data[0].geoCode.longitude,
locations.data[0].geoCode.latitude,
];
locations.data.map((location) => {
const point = new Graphic({
geometry: {
latitude: location.geoCode.latitude,
longitude: location.geoCode.longitude,
type: 'point',
},
symbol: LocationPin,
popupTemplate: {
title: "Sample",
content: [{
type: "fields",
fieldInfos: [{
fieldName: "Name"
}, {
fieldName: "Owner"
}, {
fieldName: "Length"
}]
},{
type: "text",
text: "<div class=\"icontain\"></><a class=\"ic\"><i class=\"bi bi-star\"></i></a><a class=\"ic\"><i class=\"bi bi-geo-alt-fill\"></i></a></div>"
}]
}
});
mapView.graphics.add(point);
});
};
update css for button close
.esri-popup__header-buttons{
position: absolute;
top: 100px;
margin: 0;
left: -17px;
padding: 0;
background: white;
border-radius: 50%;
border: solid 1px;
width: 32px;
height: 32px;
display: flex;
justify-content: center;
align-items: center;
}
.esri-popup__button {
z-index: 10;
}
try with this class and styles, to customize the close button
my problem is that I have some markers that needs to toggle when I click on the button, How can I add the id and the visiblity property to these markers ? I tried adding the id directly to the markers but that didn't work and also I don't know how to add the "visibility" to the markers geojson (only for the mapboxmarker the other one is just for some testig there)
Here is the code and the js fiddle link https://jsfiddle.net/foyb96zq/
HTML
<script src="https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.11.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://kit.fontawesome.com/7134867017.js" crossorigin="anonymous"></script>
<div id="menu">
</div>
<div id="map"></div>
CSS
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
.marker {
background-image: url('https://f.hubspotusercontent20.net/hubfs/6957522/mapbox-icon.png');
background-size: cover;
width: 50px;
height: 50px;
cursor: pointer;
}
#menu {
background: #773dbd;
position: absolute;
z-index: 1;
top: 50px;
right: 10px;
margin-bottom: 5%;
border-radius: 3px;
width: 120px;
border: 1px solid rgba(0, 0, 0, 0.4);
font-family: 'Open Sans', sans-serif;
}
#menu a {
font-size: 13px;
color: #ffffff;
display: block;
margin: 0;
padding: 0;
padding: 10px;
text-decoration: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
text-align: center;
}
#menu a:last-child {
border: none;
}
#menu a:hover {
background-color: #966acc;
color: #ffffff;
}
#menu a.active {
background-color: #773dbd;
color: #ffffff;
}
#menu a.active:hover {
background: #966acc;
}
.clicked {
text-align: right !important;
}
.clicked::before {
content:"\f058";
font-family: "Font Awesome 5 Free";
font-style: normal;
font-weight: normal;
text-decoration: inherit;
/*--adjust as necessary--*/
color: #ffffff;
font-size: 18px;
padding-right: 0.5em;
position: absolute;
top:9px;
left:10px;
}
JS
mapboxgl.accessToken = 'pk.eyJ1IjoiYW5kcnJlIiwiYSI6ImNrYndjMm0yZzBjMHIyeW1zN3EyNWY4ODcifQ.G4ThulNR7Vi_u6zrdJ5V1w';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/andrre/ckbwd976y10g91iqmo7s17jcz',
center: [-41.014594, 38.320168],
zoom: 3
});
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
-73.985148,
40.732454
]
},
properties: {
title: 'New York',
description: 'undefined'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
-0.128754,
51.507662
]
},
properties: {
title: 'London',
description: 'undefined'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
2.352028,
48.857033
]
},
properties: {
title: 'Paris',
description: 'undefined'
}
}
]};
//
geojson.features.forEach(function(marker) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.addTo(map);
});
//code for toogle
//
// enumerate ids of the layers
var toggleableLayerIds = ['contours', 'museums'];
// set up the corresponding toggle button for each layer
for (var i = 0; i < toggleableLayerIds.length; i++) {
var id = toggleableLayerIds[i];
var link = document.createElement('a');
link.href = '#';
link.className = 'active';
link.textContent = id;
link.onclick = function(e) {
var clickedLayer = this.textContent;
e.preventDefault();
e.stopPropagation();
var visibility = map.getLayoutProperty(clickedLayer, 'visibility');
// toggle layer visibility by changing the layout object's visibility property
if (visibility === 'visible') {
map.setLayoutProperty(clickedLayer, 'visibility', 'none');
this.className = '';
} else {
this.className = 'active';
map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
}
};
var layers = document.getElementById('menu');
layers.appendChild(link);
}
You need to add the markers as new feature layers, not just add them one-by-one in a for loop. The above code is erroring as you have not added any layers, and mapbox doesn't know how it is mean to group your markers.
See the docs here for info.
I found a way of doing it, here is the code if anyone wants to use it, this needs to be placed instead of geojson
map.on('load', function() {
// Add an image to use as a custom marker
map.loadImage(
'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png',
function(error, image) {
if (error) throw error;
map.addImage('custom-marker', image);
// Add a GeoJSON source with 2 points
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
// feature for Mapbox DC
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [
-77.03238901390978,
38.913188059745586
]
},
'properties': {
'title': 'New York',
'description':'undefined'
}
},
{
// feature for Mapbox SF
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-122.414, 37.776]
},
'properties': {
'title': 'Mapbox SF',
'description': 'description sf'
}
}
]
}
});
// Add a symbol layer
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': 'custom-marker',
// get the title name from the source's "title" property
}
});
}
);
});
map.on('click', 'points', function(e) {
var coordinates = e.features[0].geometry.coordinates.slice();
var description = e.features[0].properties.description;
var title = e.features[0].properties.title;
// Ensure that if the map is zoomed out such that multiple
// copies of the feature are visible, the popup appears
// over the copy being pointed to.
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML('<h3>' + title + '</h3><p>' + description + '</p>')
.addTo(map);
});
//code for toogle
//
// enumerate ids of the layers
var toggleableLayerIds = ['points', 'museums'];
// set up the corresponding toggle button for each layer
for (var i = 0; i < toggleableLayerIds.length; i++) {
var id = toggleableLayerIds[i];
var link = document.createElement('a');
link.href = '#';
link.className = 'active';
link.textContent = id;
link.onclick = function(e) {
var clickedLayer = this.textContent;
e.preventDefault();
e.stopPropagation();
var visibility = map.getLayoutProperty(clickedLayer, 'visibility');
// toggle layer visibility by changing the layout object's visibility property
if (visibility === 'visible') {
map.setLayoutProperty(clickedLayer, 'visibility', 'none');
this.className = '';
} else {
this.className = 'active';
map.setLayoutProperty(clickedLayer, 'visibility', 'visible');
}
};
var layers = document.getElementById('menu');
layers.appendChild(link);
}
I want to edit polygon which i have added using map.addLayer() on mapbox.
the code:
map.addLayer({
'id': 'maine'+id,
'type': 'fill',
'source': {
'type': 'geojson',
'data': {
'type': 'Feature',
'geometry': {
'type': 'Polygon',
'coordinates': coords
}
}
},
'layout': {},
'paint': {
'fill-color': '#088',
'fill-opacity': 0.8
}
});
Mapbox GL Drawing Library is used to draw/edit the shapes.
You have added the polygon as a map layer. Editing the layer in drawing mode directly seems not possible. Here is a possible way
You need to hide the layer first.
Get the Polygon data from layer source
Init the drawing mode and add a new polygon to drawing manager with the polygon data
Once the editing finished, update the layer source with the edited polygon data from drawing manager
Remove the polygon from the drawing manager
Show the updated layer
You need to use the add method to draw an existing shape.
draw.add({
'id': 'polygon-3355',
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Polygon',
'coordinates': [[[-67.13734351262877, 45.137451890638886],
[-66.96466, 44.8097],
[-68.03252, 44.3252],
[-69.06, 43.98],
[-70.11617, 43.68405],
[-70.64573401557249, 43.090083319667144],
[-70.75102474636725, 43.08003225358635],
[-70.79761105007827, 43.21973948828747],
[-70.98176001655037, 43.36789581966826],
[-70.94416541205806, 43.46633942318431],
[-71.08482, 45.3052400000002],
[-70.6600225491012, 45.46022288673396],
[-70.30495378282376, 45.914794623389355],
[-70.00014034695016, 46.69317088478567],
[-69.23708614772835, 47.44777598732787],
[-68.90478084987546, 47.184794623394396],
[-68.23430497910454, 47.35462921812177],
[-67.79035274928509, 47.066248887716995],
[-67.79141211614706, 45.702585354182816],
[-67.13734351262877, 45.137451890638886]]]
}
});
Library Link:
https://github.com/mapbox/mapbox-gl-draw
API Methods Reference:
https://github.com/mapbox/mapbox-gl-draw/blob/master/docs/API.md
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Show drawn polygon area</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
.calculation-box {
height: 75px;
width: 150px;
position: absolute;
bottom: 40px;
left: 10px;
background-color: rgba(255, 255, 255, .9);
padding: 15px;
text-align: center;
}
p {
font-family: 'Open Sans';
margin: 0;
font-size: 13px;
}
</style>
<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/turf/v3.0.11/turf.min.js'></script>
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.0.9/mapbox-gl-draw.js'></script>
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.0.9/mapbox-gl-draw.css' type='text/css'/>
<div id='map'></div>
<div class='calculation-box'>
<p>Draw a polygon using the draw tools.</p>
<div id='calculated-area'></div>
</div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiZWRlbnJheWdhcmRuZXIiLCJhIjoiRlZRVlhqOCJ9.tDrWaeNRbMCtXAovQLYuzA';
/* eslint-disable */
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/streets-v8',
center: [-70.11617, 43.68405],
zoom: 5
});
var draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
polygon: true,
trash: true
}
});
map.addControl(draw);
map.on('draw.create', updateArea);
map.on('draw.delete', updateArea);
map.on('draw.update', updateArea);
draw.add({
'id': 'polygon-3355',
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'Polygon',
'coordinates': [[[-67.13734351262877, 45.137451890638886],
[-66.96466, 44.8097],
[-68.03252, 44.3252],
[-69.06, 43.98],
[-70.11617, 43.68405],
[-70.64573401557249, 43.090083319667144],
[-70.75102474636725, 43.08003225358635],
[-70.79761105007827, 43.21973948828747],
[-70.98176001655037, 43.36789581966826],
[-70.94416541205806, 43.46633942318431],
[-71.08482, 45.3052400000002],
[-70.6600225491012, 45.46022288673396],
[-70.30495378282376, 45.914794623389355],
[-70.00014034695016, 46.69317088478567],
[-69.23708614772835, 47.44777598732787],
[-68.90478084987546, 47.184794623394396],
[-68.23430497910454, 47.35462921812177],
[-67.79035274928509, 47.066248887716995],
[-67.79141211614706, 45.702585354182816],
[-67.13734351262877, 45.137451890638886]]]
}
});
function updateArea(e) {
var data = draw.getAll();
var answer = document.getElementById('calculated-area');
if (data.features.length > 0) {
var area = turf.area(data);
// restrict to area to 2 decimal points
var rounded_area = Math.round(area*100)/100;
answer.innerHTML = '<p><strong>' + rounded_area + '</strong></p><p>square meters</p>';
} else {
answer.innerHTML = '';
if (e.type !== 'draw.delete') alert("Use the draw tools to draw a polygon!");
}
}
</script>
</body>
</html>
I currently have some problems with the google pie charts. I have a pie chart which is finally working and showing me the data in the pie chart.
The problem what i have now is that when there is no data to show in the Pie chart then nothing will come up. I would like to show an empty pie chart if there is no data to show.
As an alternative, i also would like to always show an empty pie chart and then let the pie chart load dynamically the data in the pie chart, so i can see it happen.
Hopefully you guys can help me! I really appreciate it.
I currently have the following javascript:
(UPDATED VERSION)
<div style="border: 0px solid rgb(201, 0, 1); overflow: hidden; margin: 15px auto; max-width: 100%;">
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {packages: ['corechart']});
google.charts.setOnLoadCallback(drawChart);
</script>
<script type="text/javascript">
var highRiskCategory1 = 0;
var mediumHighRiskCategory1 = 0;
var mediumRiskCategory1 = 0;
var mediumLowRiskCategory1 = 0;
var lowRiskCategory1 = 0;
var xmlURL = "";
var xml;
var firstDraw = true;
// load google first
google.charts.load('current', {
callback: function () {
// draw "no data" chart
drawPiechartblank();
},
packages: ['corechart']
});
function loadData() {
$j.ajax({
url: xmlURL,
dataType: 'xml',
beforeSend: function() {
$j('#loader').show();
},
success: function(data) {
xml = data;
$j('#loader').hide();
createPiechartthree();
},
error: function(jqXHR, text) {
console.log(text);
drawPiechartblank();
return;
}
});
}
function createPiechartthree(){
var columns = {};
var xmlColumns = $j('head', xml);
xmlColumns.find('headColumn').each(function() {
var columnName = $j(this).find('columnValue').text();
var columnID = $j(this).attr('columnid');
columns[columnName] = (columnID);
});
var xmlData = $j('data', xml);
xmlData.find('item').each(function() {
$j(this).find('column').each(function() {
var colID = $j(this).attr("columnid");
var value = $j(this).find('displayData').text();
if(colID == columns["Risk category"]){
if(value === "5. High Risk"){
highRiskCategory1++;
}
else if(value === "4. Medium High Risk"){
mediumHighRiskCategory1++;
}
else if(value === "3. Medium Risk"){
mediumRiskCategory1++;
}
else if(value === "2. Medium Low Risk"){
mediumLowRiskCategory1++;
}
else if(value === "1. Low Risk"){
lowRiskCategory1++;
}
}
});
});
// check for data
if ((highRiskCategory1 + mediumHighRiskCategory1 + mediumRiskCategory1 + mediumLowRiskCategory1 + lowRiskCategory1) === 0) {
drawPiechartblank();
} else {
drawPiechartthree(highRiskCategory1, mediumHighRiskCategory1, mediumRiskCategory1, mediumLowRiskCategory1, lowRiskCategory1);
}
}
function drawPiechartthree(highRiskCategory1, mediumHighRiskCategory1, mediumRiskCategory1, mediumLowRiskCategory1, lowRiskCategory1) {
var data = google.visualization.arrayToDataTable([
['Is the counterparty a PEP?', 'Amount'],
['Very low', 0],
['High Risk', highRiskCategory1],
['Medium High Risk', mediumHighRiskCategory1],
['Medium Risk', mediumRiskCategory1],
['Medium Low Risk', mediumLowRiskCategory1],
['Low Risk', lowRiskCategory1],
['Very high', 0]
]);
var options = {
chartArea: {
// allow room for selection highlight
bottom: 12,
left: 12,
right: 12,
top: 12,
height: '100%',
width: '100%'
},
pieHole: 0.5,
colors: ['#25b578', '#f05023', '#FF944A', '#F6BD53', '#FFE158', '#6FC968', '#8C8886'],
slices: {
2: {offset: 0.02},
3: {offset: 0.02},
4: {offset: 0.02},
5: {offset: 0.02},
},
};
var chart = new google.visualization.PieChart(
document.getElementById('Piechartthree_div'));
chart.draw(data, options);
var selectHandler = function(e) {
var selectedItem = chart.getSelection()[0];
if (selectedItem) {
var topping = data.getValue(selectedItem.row, 0);
console.log(topping);
if(topping === 'High Risk'){
window.location.href = '';
}
else if(topping === 'Medium High Risk'){
window.location.href = '';
}
else if(topping === 'Medium Risk'){
window.location.href = '';
}
else if(topping === 'Medium Low Risk'){
window.location.href = '';
}
else if(topping === 'Low Risk'){
window.location.href = '';
}
}
}
google.visualization.events.addListener(chart, 'select', selectHandler);
}
function drawPiechartblank() {
var data = google.visualization.arrayToDataTable([
['Is the counterparty a PEP?', 'Amount'],
// blank first column removes legend,
// use object notation for formatted value (f:)
['', {v: 1, f: 'No Data'}]
]);
var options = {
chartArea: {
bottom: 12,
left: 12,
right: 12,
top: 12,
height: '100%',
width: '100%'
},
pieHole: 0.5,
colors: ['transparent'],
pieSliceBorderColor: '#9e9e9e',
// show formatted value from the data
pieSliceText: 'value',
// default text style is white
// won't show in center unless change color
pieSliceTextStyle: {
color: '#9e9e9e'
},
tooltip: {
trigger: 'none'
}
};
var chart = new google.visualization.PieChart(
document.getElementById('Piechartthree_div')
);
google.visualization.events.addListener(chart, 'ready', function () {
// load data on first draw
if (firstDraw) {
firstDraw = false;
loadData();
}
});
chart.draw(data, options);
}
</script>
<div id="Piechartthree_div" style="width: 100%; height: ; position:relative;"><img alt="" id="" src="./attachment_dw.action?attachmentId=2233" style="width: 80px; height: 80px; display: inline-block; position:absolute; right:50%; top: 50%;" /></div>
</div>
in order to draw a pie chart, google requires at least one row, with a value greater than zero
so just hard-code the needed data...
var data = google.visualization.arrayToDataTable([
['Is the counterparty a PEP?', 'Amount'],
['', {v: 1, f: 'No Data'}]
]);
using a blank string '' for the row label will prevent the legend from showing
use the formatted value f: to display text in the center of the pie chart
which requires the following options...
// show formatted value from the data
pieSliceText: 'value',
// default text style is white
// won't show in center unless change color
pieSliceTextStyle: {
color: '#9e9e9e'
},
to make the chart look empty, use transparent as the color and add a border...
colors: ['transparent'],
pieSliceBorderColor: '#9e9e9e',
see following working snippet...
google.charts.load('current', {
callback: drawPiechartblank,
packages: ['corechart']
});
function drawPiechartblank() {
var data = google.visualization.arrayToDataTable([
['Is the counterparty a PEP?', 'Amount'],
// blank first column removes legend,
// use object notation for formatted value (f:)
['', {v: 1, f: 'No Data'}]
]);
var options = {
chartArea: {
bottom: 12,
left: 12,
right: 12,
top: 12,
height: '100%',
width: '100%'
},
pieHole: 0.5,
colors: ['transparent'],
pieSliceBorderColor: '#9e9e9e',
// show formatted value from the data
pieSliceText: 'value',
// default text style is white
// won't show in center unless change color
pieSliceTextStyle: {
color: '#9e9e9e'
},
tooltip: {
trigger: 'none'
}
};
var chart = new google.visualization.PieChart(
document.getElementById('Piechartthree_div')
);
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="Piechartthree_div"></div>
to start with an empty chart, load google first, draw the blank chart
// load google first
google.charts.load('current', {
callback: function () {
// draw "no data" chart
drawPiechartblank();
},
packages: ['corechart']
});
then wait for the 'ready' event before sending the first request for data...
google.visualization.events.addListener(chart, 'ready', function () {
if (firstDraw) {
firstDraw = false;
loadData();
}
});
see following snippet, with notes in comments...
<div style="border: 0px solid rgb(201, 0, 1); overflow: hidden; margin: 15px auto; max-width: 100%;">
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script>
var highRiskCategory1 = 0;
var mediumHighRiskCategory1 = 0;
var mediumRiskCategory1 = 0;
var mediumLowRiskCategory1 = 0;
var lowRiskCategory1 = 0;
var xmlURL = "XMLLINK";
var xml;
var firstDraw = true;
// load google first
google.charts.load('current', {
callback: function () {
// draw "no data" chart
drawPiechartblank();
},
packages: ['corechart']
});
function loadData() {
$j.ajax({
url: xmlURL,
dataType: 'xml',
beforeSend: function() {
$j('#loader').show();
},
success: function(data) {
xml = data;
$j('#loader').hide();
createPiechartthree();
},
error: function(jqXHR, text) {
drawPiechartblank();
return;
}
});
}
function createPiechartthree(){
var columns = {};
var xmlColumns = $j('head', xml);
xmlColumns.find('headColumn').each(function() {
var columnName = $j(this).find('columnValue').text();
var columnID = $j(this).attr('columnid');
columns[columnName] = (columnID);
});
var xmlData = $j('data', xml);
xmlData.find('item').each(function() {
$j(this).find('column').each(function() {
var colID = $j(this).attr("columnid");
var value = $j(this).find('displayData').text();
if(colID == columns["Risk category"]){
if(value === "5. High Risk"){
highRiskCategory1++;
}
else if(value === "4. Medium High Risk"){
mediumHighRiskCategory1++;
}
else if(value === "3. Medium Risk"){
mediumRiskCategory1++;
}
else if(value === "2. Medium Low Risk"){
mediumLowRiskCategory1++;
}
else if(value === "1. Low Risk"){
lowRiskCategory1++;
}
}
});
});
// check for data
if ((highRiskCategory1 + mediumHighRiskCategory1 + mediumRiskCategory1 + mediumLowRiskCategory1 + lowRiskCategory1) === 0) {
drawPiechartblank();
} else {
drawPiechartthree(highRiskCategory1, mediumHighRiskCategory1, mediumRiskCategory1, mediumLowRiskCategory1, lowRiskCategory1);
}
}
function drawPiechartthree(highRiskCategory1, mediumHighRiskCategory1, mediumRiskCategory1, mediumLowRiskCategory1, lowRiskCategory1) {
var data = google.visualization.arrayToDataTable([
['Is the counterparty a PEP?', 'Amount'],
['Very low', 0],
['High Risk', highRiskCategory1],
['Medium High Risk', mediumHighRiskCategory1],
['Medium Risk', mediumRiskCategory1],
['Medium Low Risk', mediumLowRiskCategory1],
['Low Risk', lowRiskCategory1],
['Very high', 0]
]);
var options = {
chartArea: {
// allow room for selection highlight
bottom: 12,
left: 12,
right: 12,
top: 12,
height: '100%',
width: '100%'
},
pieHole: 0.5,
colors: ['#25b578', '#f05023', '#FF944A', '#F6BD53', '#FFE158', '#6FC968', '#8C8886'],
slices: {
2: {offset: 0.02},
3: {offset: 0.02},
4: {offset: 0.02},
5: {offset: 0.02},
},
};
var chart = new google.visualization.PieChart(
document.getElementById('Piechartthree_div'));
chart.draw(data, options);
var selectHandler = function(e) {
var selectedItem = chart.getSelection()[0];
if (selectedItem) {
var topping = data.getValue(selectedItem.row, 0);
console.log(topping);
if(topping === 'High Risk'){
window.location.href = '';
}
else if(topping === 'Medium High Risk'){
window.location.href = '';
}
else if(topping === 'Medium Risk'){
window.location.href = '';
}
else if(topping === 'Medium Low Risk'){
window.location.href = '';
}
else if(topping === 'Low Risk'){
window.location.href = '';
}
}
}
google.visualization.events.addListener(chart, 'select', selectHandler);
}
function drawPiechartblank() {
var data = google.visualization.arrayToDataTable([
['Is the counterparty a PEP?', 'Amount'],
// blank first column removes legend,
// use object notation for formatted value (f:)
['', {v: 1, f: 'No Data'}]
]);
var options = {
chartArea: {
bottom: 12,
left: 12,
right: 12,
top: 12,
height: '100%',
width: '100%'
},
pieHole: 0.5,
colors: ['transparent'],
pieSliceBorderColor: '#9e9e9e',
// show formatted value from the data
pieSliceText: 'value',
// default text style is white
// won't show in center unless change color
pieSliceTextStyle: {
color: '#9e9e9e'
},
tooltip: {
trigger: 'none'
}
};
var chart = new google.visualization.PieChart(
document.getElementById('Piechartthree_div')
);
google.visualization.events.addListener(chart, 'ready', function () {
// load data on first draw
if (firstDraw) {
firstDraw = false;
loadData();
}
});
chart.draw(data, options);
}
</script>
<div id="Piechartthree_div" style="width: 100%; height: ; position:relative;"><img alt="" id="" src="./attachment_dw.action?attachmentId=2233" style="width: 80px; height: 80px; display: inline-block; position:absolute; right:50%; top: 50%;" /></div>
</div>
note: recommend using the newer library loader.js vs. the older jsapi
according to the release notes...
The version of Google Charts that remains available via the jsapi loader is no longer being updated consistently. Please use the new gstatic loader from now on.
<script src="https://www.gstatic.com/charts/loader.js"></script>
this only changes the load statement...