Instantsearch v2 在视图和地图中的不同命中
Instantsearch v2 different hits in view and map
我们使用带有自定义地点小部件的即时搜索 (2.10.4
) 来显示在地图上以及地图下方的结果。
地点小部件代码是这样的:
var placesWidget = {
init: function(opts){
var container = document.querySelector('#IS__radius');
var radius = document.querySelector('#radiusSlider');
var placesAutocomplete = places({
container: container,
templates: {
value: function(suggestion) {
return suggestion.name;
}
}
}).configure({
type: 'city',
aroundLatLngViaIP: false,
useDeviceLocation: false,
});;
placesAutocomplete.on('change', function(e) {
var location = e.suggestion;
var lat = location.latlng['lat'];
var lng = location.latlng['lng'];
opts.helper.setQueryParameter('query', $('#IS__search').val());
opts.helper.setQueryParameter('aroundLatLng', lat + ',' + lng);
opts.helper.setQueryParameter('aroundRadius', parseInt($('#radiusSlider').val()));
opts.helper.search();
});
container.addEventListener("input", onInputChange);
function onInputChange(event) {
if (event.currentTarget.value === "") {
opts.helper.setQueryParameter("aroundLatLng");
opts.helper.search();
}
if (event.currentTarget.value.length >= 2) {
$('.searchbox__distri .rs__container').addClass('visible');
$('.mapsContainer #hits').show();
} else {
$('.mapsContainer #hits').hide();
}
}
$('button.ap-icon-clear').on('click', function(){
$('.searchbox__distri .rs__container').removeClass('visible');
$('.singleResult').slideUp(250).find('.viewer').html('');
opts.helper.setQueryParameter("aroundLatLng");
opts.helper.search();
});
enableRadiusSlider(opts);
}
};
最初,所有标记以及地图下方的文本结果似乎都能正确显示。但是地图结果不正确地尊重地点搜索输入,正如您在这个屏幕截图中看到的那样:
下面的 6 个框是正确的,但地图显示的结果太多(但不是全部)。
我想,地图渲染中的线条(见下文)params.helper.setQueryParameter('query', $('#IS__search').val());
应该可以解决这个问题。调试它给了我应该采用的正确值。
map = {
_mapContainer: document.querySelector('#map-instantsearch-container'),
markers: [],
_hitToMarker: function(hit) {
var icon = {
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin@2x.png',
size: new google.maps.Size(39, 58),
scaledSize: new google.maps.Size(39, 58)
};
var marker = new google.maps.Marker({
position: {
lat: hit._geoloc.lat,
lng: hit._geoloc.lng
},
map: this._map,
icon: icon,
title: hit.company+' / '+hit.zip+' '+hit.city,
});
// trigger custom function on marker click
window.google.maps.event.addListener(marker, 'click', function () {
distriDetail(hit.objectID,this.position.lat(),this.position.lng());
});
return marker;
},
init: function(params) {
radius = document.querySelector('#radius');
this._helper = params.helper;
// init the map
this._map = new google.maps.Map(
this._mapContainer,
{
zoom: 2,
backgroundColor: "#eeeeee",
styles: [{"elementType": "geometry","stylers": [{"color": "#f5f5f5"}]},{"elementType": "labels.icon","stylers": [{"visibility": "off"}]},{"elementType": "labels.text.fill","stylers": [{"color": "#616161"}]},{"elementType": "labels.text.stroke","stylers": [{"color": "#f5f5f5"}]},{"featureType": "administrative.land_parcel","elementType": "labels.text.fill","stylers": [{"color": "#bdbdbd"}]},{"featureType": "poi","elementType": "geometry","stylers": [{"color": "#eeeeee"}]},{"featureType": "poi","elementType": "labels.text.fill","stylers": [{"color": "#757575"}]},{"featureType": "poi.park","elementType": "geometry","stylers": [{"color": "#e5e5e5"}]},{"featureType": "poi.park","elementType": "labels.text.fill","stylers": [{"color": "#9e9e9e"}]},{"featureType": "road","elementType": "geometry","stylers": [{"color": "#ffffff"}]},{"featureType": "road.arterial","elementType": "labels.text.fill","stylers": [{"color": "#757575"}]},{"featureType": "road.highway","elementType": "geometry","stylers": [{"color": "#dadada"}]},{"featureType": "road.highway","elementType": "labels.text.fill","stylers": [{"color": "#616161"}]},{"featureType": "road.local","elementType": "labels.text.fill","stylers": [{"color": "#9e9e9e"}]},{"featureType": "transit.line","elementType": "geometry","stylers": [{"color": "#e5e5e5"}]},{"featureType": "transit.station","elementType": "geometry","stylers": [{"color": "#eeeeee"}]},{"featureType": "water","elementType": "geometry","stylers": [{"color": "#c9c9c9"}]},{"featureType": "water","elementType": "labels.text.fill","stylers": [{"color": "#9e9e9e"}]}],
center: new google.maps.LatLng(51.0964656, 5.9588265),
}
);
},
render: function(params)
{
console.log('render fn');
console.log(params);
params.helper.setQueryParameter('query', $('#IS__search').val());
// clear markers
this.markers.forEach(function (marker) {
marker.setMap(null);
});
// transform hits to Google Maps markers
this.markers = params.results.hits.map(this._hitToMarker.bind(this));
var bounds = new google.maps.LatLngBounds();
// make sure we display the good part of the maps
this.markers.forEach(function(marker) {
bounds.extend(marker.getPosition());
});
var clusterStyles = [
{
textColor: 'white',
textSize: 15,
anchor: [12, 39],
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin.png',
height: 70,
width: 39
},
{
textColor: 'white',
textSize: 15,
anchor: [12, 39],
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin.png',
height: 70,
width: 39
},
{
textColor: 'white',
textSize: 15,
anchor: [12, 39],
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin.png',
height: 70,
width: 39
}
];
var mcOptions = {
gridSize: 58,
styles: clusterStyles,
maxZoom: 15
};
var markerCluster = new MarkerClusterer(this._map, this.markers, mcOptions);
this._map.fitBounds(bounds);
// zoom on results
var zoom = this._map.getZoom();
this._map.setZoom(zoom > 14 ? 14 : zoom);
}
};
为什么地图显示的结果与 hits 模板不同?没有意义。
问题似乎来自 MarkerClusterer
。这是一个有状态的对象,因此它保留了地图上以前的标记。一种可能的解决方案是在 init
步骤创建集群。在 render
步骤中,您可以清除以前的标记并将新标记附加到集群上。 an example 展示了如何操作。
我们使用带有自定义地点小部件的即时搜索 (2.10.4
) 来显示在地图上以及地图下方的结果。
地点小部件代码是这样的:
var placesWidget = {
init: function(opts){
var container = document.querySelector('#IS__radius');
var radius = document.querySelector('#radiusSlider');
var placesAutocomplete = places({
container: container,
templates: {
value: function(suggestion) {
return suggestion.name;
}
}
}).configure({
type: 'city',
aroundLatLngViaIP: false,
useDeviceLocation: false,
});;
placesAutocomplete.on('change', function(e) {
var location = e.suggestion;
var lat = location.latlng['lat'];
var lng = location.latlng['lng'];
opts.helper.setQueryParameter('query', $('#IS__search').val());
opts.helper.setQueryParameter('aroundLatLng', lat + ',' + lng);
opts.helper.setQueryParameter('aroundRadius', parseInt($('#radiusSlider').val()));
opts.helper.search();
});
container.addEventListener("input", onInputChange);
function onInputChange(event) {
if (event.currentTarget.value === "") {
opts.helper.setQueryParameter("aroundLatLng");
opts.helper.search();
}
if (event.currentTarget.value.length >= 2) {
$('.searchbox__distri .rs__container').addClass('visible');
$('.mapsContainer #hits').show();
} else {
$('.mapsContainer #hits').hide();
}
}
$('button.ap-icon-clear').on('click', function(){
$('.searchbox__distri .rs__container').removeClass('visible');
$('.singleResult').slideUp(250).find('.viewer').html('');
opts.helper.setQueryParameter("aroundLatLng");
opts.helper.search();
});
enableRadiusSlider(opts);
}
};
最初,所有标记以及地图下方的文本结果似乎都能正确显示。但是地图结果不正确地尊重地点搜索输入,正如您在这个屏幕截图中看到的那样:
下面的 6 个框是正确的,但地图显示的结果太多(但不是全部)。
我想,地图渲染中的线条(见下文)params.helper.setQueryParameter('query', $('#IS__search').val());
应该可以解决这个问题。调试它给了我应该采用的正确值。
map = {
_mapContainer: document.querySelector('#map-instantsearch-container'),
markers: [],
_hitToMarker: function(hit) {
var icon = {
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin@2x.png',
size: new google.maps.Size(39, 58),
scaledSize: new google.maps.Size(39, 58)
};
var marker = new google.maps.Marker({
position: {
lat: hit._geoloc.lat,
lng: hit._geoloc.lng
},
map: this._map,
icon: icon,
title: hit.company+' / '+hit.zip+' '+hit.city,
});
// trigger custom function on marker click
window.google.maps.event.addListener(marker, 'click', function () {
distriDetail(hit.objectID,this.position.lat(),this.position.lng());
});
return marker;
},
init: function(params) {
radius = document.querySelector('#radius');
this._helper = params.helper;
// init the map
this._map = new google.maps.Map(
this._mapContainer,
{
zoom: 2,
backgroundColor: "#eeeeee",
styles: [{"elementType": "geometry","stylers": [{"color": "#f5f5f5"}]},{"elementType": "labels.icon","stylers": [{"visibility": "off"}]},{"elementType": "labels.text.fill","stylers": [{"color": "#616161"}]},{"elementType": "labels.text.stroke","stylers": [{"color": "#f5f5f5"}]},{"featureType": "administrative.land_parcel","elementType": "labels.text.fill","stylers": [{"color": "#bdbdbd"}]},{"featureType": "poi","elementType": "geometry","stylers": [{"color": "#eeeeee"}]},{"featureType": "poi","elementType": "labels.text.fill","stylers": [{"color": "#757575"}]},{"featureType": "poi.park","elementType": "geometry","stylers": [{"color": "#e5e5e5"}]},{"featureType": "poi.park","elementType": "labels.text.fill","stylers": [{"color": "#9e9e9e"}]},{"featureType": "road","elementType": "geometry","stylers": [{"color": "#ffffff"}]},{"featureType": "road.arterial","elementType": "labels.text.fill","stylers": [{"color": "#757575"}]},{"featureType": "road.highway","elementType": "geometry","stylers": [{"color": "#dadada"}]},{"featureType": "road.highway","elementType": "labels.text.fill","stylers": [{"color": "#616161"}]},{"featureType": "road.local","elementType": "labels.text.fill","stylers": [{"color": "#9e9e9e"}]},{"featureType": "transit.line","elementType": "geometry","stylers": [{"color": "#e5e5e5"}]},{"featureType": "transit.station","elementType": "geometry","stylers": [{"color": "#eeeeee"}]},{"featureType": "water","elementType": "geometry","stylers": [{"color": "#c9c9c9"}]},{"featureType": "water","elementType": "labels.text.fill","stylers": [{"color": "#9e9e9e"}]}],
center: new google.maps.LatLng(51.0964656, 5.9588265),
}
);
},
render: function(params)
{
console.log('render fn');
console.log(params);
params.helper.setQueryParameter('query', $('#IS__search').val());
// clear markers
this.markers.forEach(function (marker) {
marker.setMap(null);
});
// transform hits to Google Maps markers
this.markers = params.results.hits.map(this._hitToMarker.bind(this));
var bounds = new google.maps.LatLngBounds();
// make sure we display the good part of the maps
this.markers.forEach(function(marker) {
bounds.extend(marker.getPosition());
});
var clusterStyles = [
{
textColor: 'white',
textSize: 15,
anchor: [12, 39],
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin.png',
height: 70,
width: 39
},
{
textColor: 'white',
textSize: 15,
anchor: [12, 39],
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin.png',
height: 70,
width: 39
},
{
textColor: 'white',
textSize: 15,
anchor: [12, 39],
url: 'typo3conf/ext/siteway/Resources/Public/Images/markerclusterer/basePin.png',
height: 70,
width: 39
}
];
var mcOptions = {
gridSize: 58,
styles: clusterStyles,
maxZoom: 15
};
var markerCluster = new MarkerClusterer(this._map, this.markers, mcOptions);
this._map.fitBounds(bounds);
// zoom on results
var zoom = this._map.getZoom();
this._map.setZoom(zoom > 14 ? 14 : zoom);
}
};
为什么地图显示的结果与 hits 模板不同?没有意义。
问题似乎来自 MarkerClusterer
。这是一个有状态的对象,因此它保留了地图上以前的标记。一种可能的解决方案是在 init
步骤创建集群。在 render
步骤中,您可以清除以前的标记并将新标记附加到集群上。 an example 展示了如何操作。