Once a cluster is created and added to a map with this:
let layer = new H.map.layer.ObjectLayer(clusteredDataProvider);
map.addLayer(layer);
How can one change the layer visibility (show/hide) ?
You can use the removeLayer() method for that. For example:
var handleClusterLayer = function(cb)
{
if(cb.checked)
map.addLayer( clusterOverlayLayer );
else
map.removeLayer( clusterOverlayLayer );
};
Related
I add DataPoints into Provider then into Layer which is bundled into the map.
Later I want to edit some of DataPoints, to do this I need to retrieve layer then provider from the map.
I try it by getting an array of layers but I won't know which one is a layer with my dataPoints.
let clusterDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
eps: 16,
minWeight: 2,
strategy: H.clustering.Provider.Strategy.GRID
},
theme: {
getClusterPresentation: this.getClusterPresentation,
getNoisePresentation: this.getNoisePresentation
}
})
}),
let layer = hereMap.getLayers().asArray().find(layer => layer instanceof H.map.layer.ObjectLayer)
if(!layer) {
layer = new H.map.layer.ObjectLayer(clusterDataProvider)
hereMap.addLayer(layer, 0);
}
layer.getProvider()
But ofc there can be a lot of ObjectLayers in my map, so how can I recognize which one is that with clusterDataProvider.
Or anyone has a better idea of how to edit a specific layer or cluster provider?
You can retrieve the layer by utilize this code:
function findClusterLayer(hereMap){
let layer = hereMap.getLayers().asArray().find(layer => {
let isObjLayer = layer instanceof H.map.layer.ObjectLayer;
return isObjLayer && (layer.getProvider() instanceof H.clustering.Provider);
});
return layer;
}
Unfortunately, you can't get dataPoints nor from layer nor from cluster provider, use please workaround like this:
var clusteringLayer = new H.map.layer.ObjectLayer(clusteredDataProvider);
clusteringLayer.$data = dataPoints;
later you can get datapoints like this:
var layer = findClusterLayer(map);
var dataPoints = layer.$data;
after changing some datapoints save it to cluster:
clusteredDataProvider.setDataPoints(dataPoints);
See please complete example
BTW: you can save some object into every datapoint see please documentation on https://developer.here.com/documentation/maps/3.1.20.0/api_reference/H.clustering.DataPoint.html#data
On map using cluster layer to display the marker , on API call loading the data on reload i need to clear clustered marker in the map please help on this issue,normal marker to clear using current method (map.removeObjects(map.getObjects()) it working as excepted but i need remove default cluster marker
Please find the below code :
startClustering(map, data) {
// First we need to create an array of DataPoint objects,
// for the ClusterProvider
// tslint:disable-next-line:ter-prefer-arrow-callback
const dataPoints = data.map(function (item) {
console.log('item>>>>', item);
return new H.clustering.DataPoint(item.y, item.x);
});
const clusteredDataProvider = new H.clustering.Provider(dataPoints, {
clusteringOptions: {
// Maximum radius of the neighbourhood
eps: 1,
// minimum weight of points required to form a cluster
minWeight: 2,
},
});
// Create a layer tha will consume objects from our clustering provider
const clusteringLayer = new H.map.layer.ObjectLayer(clusteredDataProvider);
// To make objects from clustering provder visible,
// we need to add our layer to the map
map.addLayer(clusteringLayer);
}
i need to remove this cluster marker before call this funcation
The easiest approach will be to keep a reference to the cluster layer you wish to remove and then remove it by:
Given a reference called clusteringLayer:
map.removeLayer(clusteringLayer);
The other alternative of using map.getLayers() to retrieve all map layers and removing each layer via map.removerLayer(<layerRef>) might remove layers you do not wish to remove.
failed attempts
here are some forced attempts to do it, inside BABYLON.SceneLoader.ImportMesh...{ newMeshes[0].position.x=10; } it works using the local item newMeshes[0], but out of this nothing works.
This is because the variable newMeshes is only defined inside the callback function. If you want to get the variable outside of the function you need it to be defined in the global scope. To do this simply declare a variable before ImportMesh is called and inside of ImportMesh's callback function set that variable to newMeshes[0] like this:
var meshisin = BABYLON.AbstractMesh;
// Define the variable in the global scope.
var skullMesh;
meshisin = BABYLON.SceneLoader.ImportMesh("", "scenes/", "skull.babylon", scene, function (newMeshes) {
skullMesh = newMeshes[0];
});
Then you can change the position of the mesh with: skullMesh.position.x = 10;.
But since it takes say 1 second to load the mesh you delay using the mesh until it's loaded with a setTimeout like this:
setTimeout(function() {
skullMesh.position.x = 10;
}, 1000);
All in all your code would become:
var meshisin = BABYLON.AbstractMesh;
// Define the variable in the global scope.
var skullMesh;
meshisin = BABYLON.SceneLoader.ImportMesh("", "scenes/", "skull.babylon", scene, function (newMeshes) {
skullMesh = newMeshes[0];
});
setTimeout(function() {
skullMesh.position.x = 10;
}, 1000);
PS: It's generally not a good idea to post code in images.
I'm using Rangy for highlighting text and stumbled upon a problem when calling the highlightSelection function.
highlightSelection: function(className, options) {
var converter = this.converter;
var classApplier = className ? this.classAppliers[className] : false;
options = createOptions(options, {
containerElementId: null,
selection: api.getSelection(this.doc),
exclusive: true
});
var containerElementId = options.containerElementId;
var exclusive = options.exclusive;
var selection = selection || options.selection;
var doc = selection.win.document;
var containerElement = getContainerElement(doc, containerElementId);
if (!classApplier && className !== false) {
throw new Error("No class applier found for class '" + className + "'");
}
// Store the existing selection as character ranges
var serializedSelection = converter.serializeSelection(selection, containerElement);
// Create an array of selected character ranges
var selCharRanges = [];
forEach(serializedSelection, function(rangeInfo) {
selCharRanges.push( CharacterRange.fromCharacterRange(rangeInfo.characterRange) );
});
var newHighlights = this.highlightCharacterRanges(className, selCharRanges, {
containerElementId: containerElementId,
exclusive: exclusive
});
// Restore selection
converter.restoreSelection(selection, serializedSelection, containerElement);
return newHighlights;
},
It looks like the selection object is being overridden with another call to getSelection().
What's the best way to stop it from doing that?
After doing further research, I came a cross an update by the creator of Rangy, to specifically address this issue. So,
Download the latest version of the files and make sure this is what you have in rangy-highlighter.js file under highlightSelection: function:
options = createOptions(options, {
containerElementId: null,
exclusive: true
});
var containerElementId = options.containerElementId;
var exclusive = options.exclusive;
var selection = options.selection || api.getSelection(this.doc);
var doc = selection.win.document;
var containerElement = getContainerElement(doc, containerElementId);
call the highlightSelection function like:
'highlighter.highlightSelection("highlight", {selection: sel});'
So you're setting your selection key with the value sel. 'selection' is just the name of the key expected by this function (read the github docs for more options and information) and sel should be the object your are trying to highlight and be called prior like:
'sel = rangy.getSelection();'
I am building a custom tool tip when someone highlights text, and I came across this issue. The way I solved it, was by creating a global variable range, and setting it to rangy.getSelection().getRangeAt(0). This will get you the range object for the selection, afterwards you can set the selection back to your saved value like this: rangy.getSelection().addRange(this.range)
I use Places library to autocomplete address input. Search is limited to only one city, and I get output like this:
"Rossiya, Moskva, Leninskiy prospekt 28"
How to hide "Rossiya, Moskva"? ...
My query:
function() {
// Search bounds
var p1 = new google.maps.LatLng(54.686534, 35.463867);
var p2 = new google.maps.LatLng(56.926993, 39.506836);
self.options = {
bounds : new google.maps.LatLngBounds(p1, p2),
componentRestrictions: {country: 'ru'},
};
var elements = document.querySelectorAll('.address');
for ( var i = 0; i < elements.length; i++) {
var autocomplete = new google.maps.places.Autocomplete(elements[i],
self.options);
}
You can but you have to replace the value of the input field in two places.
Example:
var autocomplete = new google.maps.places.Autocomplete(input, placesOptions);
var input = document.getElementById('searchTextField');
inside the 'place_changed' event you need to do the following:
placeResult = autocomplete.getPlace();
//This will get only the address
input.value = placeResult.name;
This will change the value in the searchtextfield to the street address.
The second place is a bit tricky:
input.addEventListener('blur', function(){
// timeoutfunction allows to force the autocomplete field to only display the street name.
if(placeResult){ setTimeout(function(){ input.value = placeResult.name; }, 1); } });
The reason why we have to do this is because if you only add the event listener for blur, google places will populate the input field with the full address, so you have to 'wait' for google to update and then force your change by waiting some miliseconds.
Try it without the setTimeout function and you will see what I mean.
EDIT
You can't. I had it the other way around, that you were just looking for a city. There is no way to only print out the street name (I'm assuming that's a street name) from the address component.
OPPOSITE OF WHAT WAS ASKED
From the docs:
the (cities) type collection instructs the Place service to return results that match either locality or administrative_area3.
var input = document.getElementById('searchTextField');
var options = {
bounds: defaultBounds,
types: ['(cities)']
};
autocomplete = new google.maps.places.Autocomplete(input, options);
in result u have hash and from it u can get part what u want:
google.maps.event.addListener(autocomplete, 'place_changed', function() {
var place = autocomplete.getPlace();
now from "place" u can get it
place.geometry.location.lat()
and for address
place.address_components[0] or place.address_components[1] ...
depends on what u want to get
I had a very similar problem which indeed was solvable. This in an Angular 2 project but it should be applicable elsewhere as well. I filter my results for establishments, and wanted to show only the name and hide the address part of the result. This did the trick for me, a function executing once you select a suggestion:
getAddress(place: Object) {
this.zone.run(() => {
this.establishment = place['name'];
});
where zone is an NgZone component injected in the constructor and this.establishment is the variable tied to [(NgModel)] in the input field.
Inside place_changed set a timeout function:
var streetString = place.address_components[0] or place.address_components[1];
window.setTimeout(function() {
$('input').val(streetString);
}, 200);
This solution worked for me.