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);
}
Related
enter image description here
The splitter can be moved in only one direction, but if remove the last var cyR works just fine
Code
<!doctype html>
<html>
<head>
<title>Introduction to cytoscape.js</title>
<script src='https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.9.4/cytoscape.min.js'></script>
<style>
.container {
display: flex;
height: 600px;
width: 100%;
}
#cyL {
width: 50%;
display: flex;
}
.splitter {
background-color: black;
cursor: ew-resize;
height: 100%;
width: 4px;
}
#cyR {
flex: 1;
display: flex;
background-color: gold;
}
</style>
</head>
<body>
<div class="container">
<div id="cyL"></div>
<div id="splitter" class="splitter"></div>
<div id="cyR"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const splitter = document.getElementById('splitter');
let L = splitter.previousElementSibling;
let R = splitter.nextElementSibling;
let x = 0;
let w = 0;
const onMouseDown = function (e) {
L = splitter.previousElementSibling;
R = splitter.nextElementSibling;
x = e.clientX;
w = L.getBoundingClientRect().width;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
};
const onMouseMove = function (e) {
const dx = e.clientX - x;
const width = ((w + dx) * 100) / splitter.parentElement.getBoundingClientRect().width;
L.style.width = `${width}%`;
splitter.style.cursor = 'col-resize';
document.body.style.cursor = 'col-resize';
L.style.userSelect = 'none';
L.style.pointerEvents = 'none';
R.style.userSelect = 'none';
R.style.pointerEvents = 'none';
};
const onMouseUp = function () {
splitter.style.removeProperty('cursor');
document.body.style.removeProperty('cursor');
L.style.removeProperty('user-select');
L.style.removeProperty('pointer-events');
R.style.removeProperty('user-select');
R.style.removeProperty('pointer-events');
// Remove the handlers of `mousemove` and `mouseup`
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
splitter.addEventListener('mousedown', onMouseDown);
});
var cyL = cytoscape({
container: document.getElementById('cyL'),
elements: [
{ data: { id: 'node_1' } },
{ data: { id: 'node_2' } },
{
data: {
id: 'edge',
source: 'node_1',
target: 'node_2'
}
}]
});
var cyR = cytoscape({
container: document.getElementById('cyR'),
elements: [
{ data: { id: 'node_1' } },
{ data: { id: 'node_2' } },
{
data: {
id: 'edge',
source: 'node_1',
target: 'node_2'
}
}]
});
</script>
</body>
</html>
Yes, cytoscape.js replace the div place holder with its canvas...
Have no idea how to make it work.
Thanks in advance
Based on found a sample.
<!DOCTYPE html>
<!-- This code is for demonstration purposes only. You should not hotlink to Github, Rawgit, or files from the Cytoscape.js documentation in your production apps. -->
<html>
<head>
<style>
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cyL {
height: 100%;
width: 50%;
position: absolute;
left: 0;
top: 0;
background-color: #FAEDEF;
}
#splitter {
height: 100%;
width: 5px;
position: absolute;
left: 50%;
top: 0;
cursor: ew-resize;
background-color: gold;
}
#cyR {
height: 100%;
width: 50%;
position: absolute;
left: 50%;
top: 0;
background-color: #EDF1FA;
border-top: 1px solid #ccc;
}
</style>
<meta charset=utf-8/>
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<title>Multiple instances</title>
<script src='https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.9.4/cytoscape.min.js'></script>
</head>
<body>
<div id="cyL"></div>
<div id="cyR"></div>
<div id="splitter"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const splitter = document.getElementById('splitter');
let L, R;
let x = 0;
let w = 0;
const onMouseDown = function (e) {
L = splitter.previousElementSibling.previousElementSibling;
R = splitter.previousElementSibling;
x = e.clientX;
w = L.getBoundingClientRect().width;
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
};
const onMouseMove = function (e) {
const dx = x - e.clientX ;
const X = ((w - dx) * 100) / splitter.parentElement.getBoundingClientRect().width;
splitter.style.left = `${X}%`;
R.style.left = `${X}%`;
R.style.width = `${100 - X}%`;
L.style.width = `${X}%`;
splitter.style.cursor = 'col-resize';
document.body.style.cursor = 'col-resize';
L.style.userSelect = 'none';
L.style.pointerEvents = 'none';
R.style.userSelect = 'none';
R.style.pointerEvents = 'none';
};
const onMouseUp = function () {
splitter.style.removeProperty('cursor');
document.body.style.removeProperty('cursor');
L.style.removeProperty('user-select');
L.style.removeProperty('pointer-events');
R.style.removeProperty('user-select');
R.style.removeProperty('pointer-events');
// Remove the handlers of `mousemove` and `mouseup`
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
splitter.addEventListener('mousedown', onMouseDown);
});
var cyL = cytoscape({
container: document.getElementById('cyL'),
elements: [
{ data: { id: 'node_1' } },
{ data: { id: 'node_2' } },
{
data: {
id: 'edge',
source: 'node_1',
target: 'node_2'
}
}]
});
var cyR = cytoscape({
container: document.getElementById('cyR'),
elements: [
{ data: { id: 'node_1' } },
{ data: { id: 'node_2' } },
{
data: {
id: 'edge',
source: 'node_1',
target: 'node_2'
}
}]
});
</script>
</body>
</html>
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 12 months ago.
Here I cannot change the long and lat values in the constructor in the setcurrentposition function. When I call this in this function, it returns undefined. How can I change the values in the constructor within that function? When I want to set lan long values in the constructor in my showPosition method, this method does not show the constructor. How can I set this? When I press this to console it comes undefined
const geojson = {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'properties': {
'message': 'Foo',
'iconSize': [60, 60]
},
'geometry': {
'type': 'Point',
'coordinates': [-66.324462, -16.024695]
}
},
{
'type': 'Feature',
'properties': {
'message': 'Bar',
'iconSize': [50, 50]
},
'geometry': {
'type': 'Point',
'coordinates': [-61.21582, -15.971891]
}
},
{
'type': 'Feature',
'properties': {
'message': 'Baz',
'iconSize': [40, 40]
},
'geometry': {
'type': 'Point',
'coordinates': [-63.292236, -18.281518]
}
}
]
};
class MapboxClass {
constructor({
token = token,
long = long,
lat = lat,
mapCanvas = mapCanvas,
mapStyle = mapStyle,
geojson = geojson,
} = {}) {
this.mapCanvas = mapCanvas
this.token = token;
this.long = long;
this.lat = lat;
this.geojson = geojson
this.mapStyle = mapStyle
}
currentLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.setCurrentPosition, this.showError)
}
}
setCurrentPosition(position) {
this.lat = position.coords.latitude;
this.long = position.coords.longitude;
}
showError(error) {
switch (error.code) {
case error.PERMISSION_DENIED:
x.innerHTML = "User denied the request for Geolocation."
break;
case error.POSITION_UNAVAILABLE:
x.innerHTML = "Location information is unavailable."
break;
case error.TIMEOUT:
x.innerHTML = "The request to get user location timed out."
break;
case error.UNKNOWN_ERROR:
x.innerHTML = "An unknown error occurred."
break;
}
}
// Method
createMap() {
mapboxgl.accessToken = this.token
const mapCanvas = new mapboxgl.Map({
container: 'map',
style: this.mapStyle,
center: [27.144623192174567, 38.428404055417225],
zoom: 6
});
this.mapCanvas = mapCanvas
}
addMarkersToMap() {
for (const marker of this.geojson.features) {
// Create a DOM element for each marker.
const el = document.createElement('div');
const width = marker.properties.iconSize[0];
const height = marker.properties.iconSize[1];
el.className = 'marker';
el.style.backgroundImage = `url(https://placekitten.com/g/${width}/${height}/)`;
el.style.width = `${width}px`;
el.style.height = `${height}px`;
el.style.backgroundSize = 'cover';
el.style.backgroundPosition = 'center';
// Add markers to the map.
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.addTo(this.mapCanvas);
el.addEventListener('click', () => {
window.alert(marker.properties.message);
});
}
}
}
const mapp = new MapboxClass({
token: "pk.eyJ1IjoiemdubXVzdGFmYSIsImEiOiJja2ZmZzF1ZzgwZWhxMnlvM2V4cWh0c3ZrIn0.5U4S5f2PwICD0MainYx_OQ",
mapStyle: 'mapbox://styles/mapbox/streets-v11',
mapCanvas: '',
lat: 'x',
long: 'x',
geojson: {
'features': [{
'type': 'Feature',
'properties': {
'message': 'Foo',
'iconSize': [60, 60]
},
'geometry': {
'type': 'Point',
'coordinates': [27.13652687626378, 38.41263764981549]
}
},
{
'type': 'Feature',
'properties': {
'message': 'Bar',
'iconSize': [50, 50]
},
'geometry': {
'type': 'Point',
'coordinates': [27.13652687626378, 39.41263764981549]
}
},
{
'type': 'Feature',
'properties': {
'message': 'Baz',
'iconSize': [40, 40]
},
'geometry': {
'type': 'Point',
'coordinates': [29.13652687626378, 38.41263764981549]
}
}
]
}
});
mapp.createMap();
mapp.addMarkersToMap();
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
.marker {
display: block;
border: none;
border-radius: 50%;
cursor: pointer;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Add custom icons with Markers</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.7.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.7.0/mapbox-gl.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<style>
.marker {
display: block;
border: none;
border-radius: 50%;
cursor: pointer;
padding: 0;
}
</style>
<div id="map"></div>
<div id="demo"></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
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 have a structure of chart like this:-
data: {
cols: [
{
id: 'Type',
type: 'string'
},
{
id: 'percentage',
type: 'number'
},
{
id: 'tooltip',
role: 'tooltip',
type: 'string',
p: { html: true }
}
],
rows: [
{
c: [
{
v: typeA
},
{
v: 20
},
{
v: 'my Tooltip content'
}
]
},
{
c: [
{
v: 'typeB'
},
{
v: 80
}
]
}
]
},
I want to disable the tooptip only for typeB and but should work with typeA. Is this possible in google charts? (tooptip trigger:none option disable it for whole chart)
when using custom tooltips, if the tooltip column is null or ''
the chart will replace with the default tooltip
to avoid, provide a custom tooltip that is hidden with css
see following working snippet...
google.charts.load('current', {
callback: function () {
var data = google.visualization.arrayToDataTable([
['Type', 'Percent'],
['typeA', 20],
['typeB', 80]
]);
// add tooltip column
data.addColumn({type: 'string', role: 'tooltip', p: {html: true}});
// build tooltip
for (var i = 0; i < data.getNumberOfRows(); i++) {
switch (data.getValue(i, 0)) {
// set visible tooltip
case 'typeA':
data.setValue(i, 2,
'<div class="ggl-tooltip"><div><span>' +
data.getValue(i, 0) + '</span></div><div>' +
data.getValue(i, 1) + '</div></div>'
);
break;
// set hidden tooltip
case 'typeB':
data.setValue(i, 2, '<div class="hdn-tooltip"><div>');
break;
}
}
var container = document.getElementById('chart_div');
var pieChart = new google.visualization.PieChart(container);
pieChart.draw(data, {
tooltip: {
isHtml: true
}
});
},
packages: ['corechart']
});
.hdn-tooltip {
display: none;
visibility: hidden;
}
.ggl-tooltip {
border: 1px solid #E0E0E0;
font-family: Arial, Helvetica;
font-size: 10pt;
padding: 12px 12px 12px 12px;
}
.ggl-tooltip div {
padding-top: 6px;
}
.ggl-tooltip span {
font-weight: bold;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>