I'm using an Azure map in react-typescript, where I show the provinces of Belgium by adding a polygon layer. The country borders from my polygon-provinces are more detailed than the default country borders drawn by Azure maps. How can I remove the 'Azure borders' from my map?
Custom styling isn't currently supported, however here is an undocumented/unsupported way to achieve this today.
map.events.add('ready', function () {
//Remove borders on initial load.
removeBorders();
});
//Remove borders when the map style changes.
map.events.add('styledata', removeBorders);
function removeBorders() {
var layers = map.map.getStyle().layers;
for (var i = 0; i < layers.length; i++) {
switch (layers[i]['source-layer']) {
//Country borders
case 'Country border':
case 'Disputed country border':
//State/province borders
case 'State border':
map.map.setLayoutProperty(layers[i].id, 'visibility', 'none');
break;
}
}
}
Related
I have a set of markers which I want to have visible or not on a React Google map.
In ESRI/ArcGIS maps you can create layers which can be turned on or off, but it does not seem any equivalent features exist in Google maps.
I suppose can give the markers a specific class and turn their visibility on or off, but I am concerned this may impact performance.
Any suggestions on a way forward?
Google Maps API does not support this kind of custom layers (refer official docs for a supported list of layers).
The following custom component demonstrates how to group markers and toggle its visibility
function MarkersGroup(props, context) {
const layersRef = useRef(null);
useEffect(() => {
const map = context[MAP];
let layers = null;
if (!layersRef.current) {
layers = new window.google.maps.MVCObject();
for (let name in props.groupData) {
for (let item of props.groupData[name].items) {
const markerProps = { position: { lat: item.lat, lng: item.lng } };
const marker = new window.google.maps.Marker(markerProps);
marker.bindTo("map", layers, name);
}
}
layersRef.current = layers;
} else layers = layersRef.current;
for (let name in props.groupData) {
if (props.groupData[name].visible) {
layers.set(name, map);
} else {
layers.set(name, null);
}
}
});
return null;
}
Notes:
google.maps.MVCObject class - is used to store layer(markers) group
layer visibility is toggled via MVCObject.set method
Here is a demo
I am using Amcharts in my AngularJS Application to create a simple bar chart.The following is my code in the controller:
let empChart;
let empBarGraph;
let empLine;
const writeemp = data => {
const {
total,
employees,
} = data;
empChart.dataProvider = e;
empChart.write('emp');
empChart.validateData();
};
AmCharts.handleLoad();
var configChart = function () {
empChart = new AmCharts.AmSerialChart();
empChart.categoryField = "state";
empChart.labelRotation = 90;
var yAxis = new AmCharts.ValueAxis();
yAxis.position = "left";
empChart.addValueAxis(yAxis);
empBarGraph = new AmCharts.AmGraph();
empBarGraph.valueField = "count";
empBarGraph.type = "column";
empBarGraph.fillAlphas = 1;
empBarGraph.lineColor = "#f0ab00";
empBarGraph.valueAxis = yAxis;
empChart.addGraph(empBarGraph);
empChart.write('empChart');
$http.get(hostNameService.getHostName()+"/dashboard/employees/statecount")
.then(response => writeemp(response.data));
}
Code in html:
<div class='panel-body'>
<div id="empChart"></div>
</div>
This would return me the values of State on x-axis and count on y-axis. I wanted to filter the chart based on the value of state and was not sure how to create the legends for this chart. could anyone suggest me on how to use legends. I want to create legends for the state value that is being returned.
You can add a legend using the OO-based syntax by creating a legend object through new AmCharts.AmLegend() and adding it to the class by calling the chart's addLegend method:
var legend = new AmCharts.AmLegend();
empChart.addLegend(legend);
If you want the legend to show values upon hovering over a column, you need to add a ChartCursor to your chart:
var cursor = new AmCharts.ChartCursor();
empChart.addChartCursor(cursor);
You can change what the legend displays upon column rollover by setting the valueText property. It allows for the same [shortcodes] used in fields like balloonText and labelText, e.g. legend.valueText = "[[category]]: [[value]]". You can also use set its valueFunction if you need to customize the text it returns dynamically like in your previous questions. All of the properties available in the legend object can be found in the AmLegend API documentation.
Updated:
Legends work off of graph objects only, so there isn't an out of the box method that allows you to represent each column as a legend item that toggles the other columns' visibility unless you're willing to reorganize your dataset and use different graph objects for each state. A workaround for this is to use the the legend's custom data array and add some event handling so that clicking on the custom data items adds/removes a toggle by unsetting your count valueField in the dataProvider.
The following annotated code accomplishes what you're trying to do:
//create the legend but disable it until the dataProvider is populated,
//since you're retrieving your data using AJAX
var legend = new AmCharts.AmLegend();
legend.enabled = false;
chart.addLegend(legend);
chart.toggleLegend = false;
// Callback that handles clicks on the custom data entry markers and labels
var handleLegendClick = function(legendEvent) {
//Set a custom flag so that the dataUpdated event doesn't fire infinitely
legendEvent.chart.toggleLegend = true;
// The following toggles the markers on and off.
// The only way to "hide" a column is to unset the valueField at the data index,
// so a temporary "storedCount" property is added to the dataProvider that stores the
// original value so that the value can be restored when the legend marker is toggled
// back on
if (undefined !== legendEvent.dataItem.hidden && legendEvent.dataItem.hidden) {
legendEvent.dataItem.hidden = false;
legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].count = legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].storedCount; //restore the value
} else {
// toggle the marker off
legendEvent.dataItem.hidden = true;
legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].storedCount = legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].count; //store the value
legendEvent.chart.dataProvider[legendEvent.dataItem.stateIdx].count = undefined; //set to undefined to hide the column
}
legendEvent.chart.validateData(); //redraw the chart
}
chart.addListener('dataUpdated', function(e) {
var legendDataItems; //used to store the legend's custom data array.
if (e.chart.toggleLegend === true) {
//is the user toggling a legend marker? stop here as the dataProvider will get updated in handleLegendClick
e.chart.toggleLegend = false;
return;
}
// if we're at this point, the data provider was updated.
// reconstruct the data array.
// initialize by grabbing the state, setting a color and stoing the index
// for toggline the columns later
legendDataItems = e.chart.dataProvider.map(function(dataElement, idx) {
return {
'title': dataElement.state,
'color': graph.lineColor,
'stateIdx': idx //used in toggling
}
});
// if the legend is not enabled, then we're setting this up for the first time.
// turn it on and attach the event handlers
if (e.chart.legend.enabled === false) {
e.chart.legend.enabled = true;
e.chart.legend.switchable = true;
e.chart.legend.addListener('clickMarker', handleLegendClick);
e.chart.legend.addListener('clickLabel', handleLegendClick);
}
// update the legend custom data and redraw the chart
e.chart.legend.data = legendDataItems;
e.chart.validateNow();
});
Here's a fiddle that illustrates this: http://jsfiddle.net/g254sdq5/1/
How to hide selection panel when I will maximize my graph panel. My selection Panel is on West region, Control Panel on north & GraphPanel at center. I am new to extjs please help me by answering this.
.on("click", function() {
var el = d3.select(this),
cPanel = pnl.up('mgoPanel').down('mgoControlPanel'), // control Panel
sPanel = Ext.ComponentQuery.query('panel[name=selectpanel]');
/selection
if (el.attr('state') == 'min') {
if (cPanel) {
cPanel.setHidden(true);
}
if (sPanel) {
sPanel.setHidden(true);
}
el.attr('src', 'resources/images/minimize.png');
el.attr('state', 'max');
} else {
if (cPanel) {
cPanel.setHidden(false);
}
if (sPanel) {
sPanel.setHidden(false);
}
el.attr('src', 'resources/images/maximize.png');
el.attr('state', 'min');
}
mgoPanel.fireEvent('onchartresize', el.attr('state'), mgoPanel);
});
Also setHidden(true); for sPanel is not working.
Please open your browser console, and find the following error message:
Uncaught TypeError: sPanel.setHidden is not a function
The reason being that
Ext.ComponentQuery.query
is not returning a component. If you check the docs or try it in browser console, you will see that it returns an array. An array does not have the function setHidden, only a component does.
So the solution is to take the first item from the query result:
sPanel = Ext.ComponentQuery.query('panel[name=selectpanel]')[0];
I have developed a simple google map web page. I need help form anyone who has experience in google maps. In right panel of my web page I add some checkboxes and I want to link different kml with these checkboxes. When I check all layer all kml are show in google maps and when I uncheck any layer checkbox then kml related to that checkbox will disappear. Please guide me how I can do this.
Please check the page from this link
http://toptrippk.com/webgis/kml%20layers.html
I suggest you the following structure. Using this method you don't have to write seperate functions for every layer but only this one. Note that 'id' of 'input' tags here is used as KML filename. You probably want to see this question. If looking forward then geoxml3 may be an option for you.
var G = google.maps;
function toggle() {
if (!this.kml)
{this.kml = new G.KmlLayer('http://toptrippk.com/webgis/uploadfiles/kml/' + this.id + '.kml', {preserveViewport:true}); this.on = false};
if (this.on)
{this.kml.setMap(null); this.on = false} else {this.kml.setMap(map); this.on = true};
};
function initialize() {
var layers = document.getElementsByTagName('input');
var options = {};
map = new G.Map(document.getElementById('map_canvas'), options);
for (var i=0; i<layers.length; i++) {G.event.addDomListener(layers[i], 'click', toggle)};};
G.event.addDomListener(window, 'load', initialize);
Looking through the Google Maps Javascript v3 API it looks like if I want to group together markers and add or remove them as groups, I need to roll my own code based on the sample below.
// Removes the overlays from the map, but keeps them in the array
function clearOverlays() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
}
}
// Shows any overlays currently in the array
function showOverlays() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(map);
}
}
}
// Deletes all markers in the array by removing references to them
function deleteOverlays() {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
}
}
Is there a more elegant solution to grouping markers and infowindows besides arrays?
Depending on what it is you want to do, MarkerClusterer might be helpful: http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/docs/reference.html