一、找到Leaflet.Autocomplete搜索框在左边的例子的css和js代码
leaflet是一个开源并且对移动端友好的交互式地图 JavaScript 库,它的访问地址:Plugins - Leaflet - 一个交互式地图 JavaScript 库
leaflet里面有很多的插件,其中搜索功能比较好的就是Leaflet.Autocomplete。
我的项目是用angular框架,逻辑是在component.ts中完成的。需要做的效果就是在地图网页上加一个搜索地址的功能,这里我引用leaflet插件库里的Leaflet.Autocomplete,这个插件搜索功能比较好用,但是呢它没有封装到npm,所以只能把它的js和css代码都下载下来。
先访问leaflet的网址然后跟着下面两张图操作就可以去到Leaflet.Autocomplete的GitHub页面
leaflet.Autocomplete的默认样式是这样的,
如果需要像我那样的搜索框在左边的话,就继续往下滑,找到下面这个
然后就可以进到在线预览界面,点击右上角,就可以进到这例子的GitHub页面
找到你要的效果的例子的序号,我要的效果是第50个例子
二、开始将第三方的插件用到自己的项目中
先进到插件的index.html页面中可以看到它引用了的css和js
我们公司的项目是用的angular框架,我在最外层的index.html页面也跟着引入了相关的css和js
其中,这两个css和js是引用的本地的,所以需要将这两个文件拷贝下来
我把这两个文件另取名字分别放到了项目中
接着需要到angular.json全局引用一下这两个文件
然后需要用到这个插件的js文件的ts文件中引用一下,但是ts不能直接用import来引入js(我也不明白为啥不行,我百度有些说可以,但是我直接import会报错),所以需要给整个js取个函数名,然后function来包装一下。原本下载下来的js如下
/* eslint-disable no-undef */
/**
* autocomplete on map
* https://github.com/tomickigrzegorz/autocomplete
*
*/
// config map
let config = {
minZoom: 7,
maxZoom: 18,
};
// magnification with which the map will start
const zoom = 18;
// co-ordinates
const lat = 52.22977;
const lng = 21.01178;
// calling map
const map = L.map("map", config).setView([lat, lng], zoom);
// Used to load and display tile layers on the map
// Most tile servers require attribution, which you can set under `Layer`
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution:
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(map);
// --------------------------------------------------------------
// create seearch button
// add "random" button
const buttonTemplate = `<div class="leaflet-search"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M31.008 27.231l-7.58-6.447c-0.784-0.705-1.622-1.029-2.299-0.998 1.789-2.096 2.87-4.815 2.87-7.787 0-6.627-5.373-12-12-12s-12 5.373-12 12 5.373 12 12 12c2.972 0 5.691-1.081 7.787-2.87-0.031 0.677 0.293 1.515 0.998 2.299l6.447 7.58c1.104 1.226 2.907 1.33 4.007 0.23s0.997-2.903-0.23-4.007zM12 20c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8z"></path></svg></div><div class="auto-search-wrapper max-height"><input type="text" id="marker" autocomplete="off" aria-describedby="instruction" aria-label="Search ..." /><div id="instruction" class="hidden">When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.</div></div>`;
// create custom button
const customControl = L.Control.extend({
// button position
options: {
position: "topleft",
className: "leaflet-autocomplete",
},
// method
onAdd: function () {
return this._initialLayout();
},
_initialLayout: function () {
// create button
const container = L.DomUtil.create(
"div",
"leaflet-bar " + this.options.className
);
L.DomEvent.disableClickPropagation(container);
container.innerHTML = buttonTemplate;
return container;
},
});
// adding new button to map controll
map.addControl(new customControl());
// --------------------------------------------------------------
// input element
const root = document.getElementById("marker");
function addClassToParent() {
const searchBtn = document.querySelector(".leaflet-search");
searchBtn.addEventListener("click", (e) => {
// toggle class
e.target
.closest(".leaflet-autocomplete")
.classList.toggle("active-autocomplete");
// add placeholder
root.placeholder = "Search ...";
// focus on input
root.focus();
// use destroy method
autocomplete.destroy();
});
}
addClassToParent();
// function clear input
map.on("click", () => {
document
.querySelector(".leaflet-autocomplete")
.classList.remove("active-autocomplete");
clickOnClearButton();
});
// autocomplete section
// more config find in https://github.com/tomickigrzegorz/autocomplete
// --------------------------------------------------------------
const autocomplete = new Autocomplete("marker", {
delay: 1000,
selectFirst: true,
howManyCharacters: 2,
onSearch: function ({ currentValue }) {
const api = `https://nominatim.openstreetmap.org/search?format=geojson&limit=5&q=${encodeURI(
currentValue
)}`;
/**
* Promise
*/
return new Promise((resolve) => {
fetch(api)
.then((response) => response.json())
.then((data) => {
resolve(data.features);
})
.catch((error) => {
console.error(error);
});
});
},
onResults: ({ currentValue, matches, template }) => {
const regex = new RegExp(currentValue, "i");
// checking if we have results if we don't
// take data from the noResults method
return matches === 0
? template
: matches
.map((element) => {
return `
<li role="option">
<p>${element.properties.display_name.replace(
regex,
(str) => `<b>${str}</b>`
)}</p>
</li> `;
})
.join("");
},
onSubmit: ({ object }) => {
const { display_name } = object.properties;
const cord = object.geometry.coordinates;
// custom id for marker
// const customId = Math.random();
// remove last marker
map.eachLayer(function (layer) {
if (layer.options && layer.options.pane === "markerPane") {
if (layer._icon.classList.contains("leaflet-marker-locate")) {
map.removeLayer(layer);
}
}
});
// add marker
const marker = L.marker([cord[1], cord[0]], {
title: display_name,
});
// add marker to map
marker.addTo(map).bindPopup(display_name);
// set marker to coordinates
map.setView([cord[1], cord[0]], 8);
// add class to marker
L.DomUtil.addClass(marker._icon, "leaflet-marker-locate");
},
// the method presents no results
noResults: ({ currentValue, template }) =>
template(`<li>No results found: "${currentValue}"</li>`),
});
我修改后的js如下:
function leafletSearch(map) {
/* eslint-disable no-undef */
/**
* autocomplete on map
* https://github.com/tomickigrzegorz/autocomplete
*
*/
// config map
let config = {
minZoom: 7,
maxZoom: 18,
};
// magnification with which the map will start
const zoom = 18;
// co-ordinates
const lat = 52.22977;
const lng = 21.01178;
// calling map
const map = L.map("map", config).setView([lat, lng], zoom);
// Used to load and display tile layers on the map
// Most tile servers require attribution, which you can set under `Layer`
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution:
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(map);
// --------------------------------------------------------------
// create seearch button
// add "random" button
const buttonTemplate = `<div class="leaflet-search"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M31.008 27.231l-7.58-6.447c-0.784-0.705-1.622-1.029-2.299-0.998 1.789-2.096 2.87-4.815 2.87-7.787 0-6.627-5.373-12-12-12s-12 5.373-12 12 5.373 12 12 12c2.972 0 5.691-1.081 7.787-2.87-0.031 0.677 0.293 1.515 0.998 2.299l6.447 7.58c1.104 1.226 2.907 1.33 4.007 0.23s0.997-2.903-0.23-4.007zM12 20c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8z"></path></svg></div><div class="auto-search-wrapper max-height"><input type="text" id="marker" autocomplete="off" aria-describedby="instruction" aria-label="Search ..." /><div id="instruction" class="hidden">When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.</div></div>`;
// create custom button
const customControl = L.Control.extend({
// button position
options: {
position: "topleft",
className: "leaflet-autocomplete",
},
// method
onAdd: function () {
return this._initialLayout();
},
_initialLayout: function () {
// create button
const container = L.DomUtil.create(
"div",
"leaflet-bar " + this.options.className
);
L.DomEvent.disableClickPropagation(container);
container.innerHTML = buttonTemplate;
return container;
},
});
// adding new button to map controll
map.addControl(new customControl());
// --------------------------------------------------------------
// input element
const root = document.getElementById("marker");
function addClassToParent() {
const searchBtn = document.querySelector(".leaflet-search");
searchBtn.addEventListener("click", (e) => {
// toggle class
e.target
.closest(".leaflet-autocomplete")
.classList.toggle("active-autocomplete");
// add placeholder
root.placeholder = "Search ...";
// focus on input
root.focus();
// use destroy method
autocomplete.destroy();
});
}
addClassToParent();
// function clear input
map.on("click", () => {
document
.querySelector(".leaflet-autocomplete")
.classList.remove("active-autocomplete");
clickOnClearButton();
});
// autocomplete section
// more config find in https://github.com/tomickigrzegorz/autocomplete
// --------------------------------------------------------------
const autocomplete = new Autocomplete("marker", {
delay: 1000,
selectFirst: true,
howManyCharacters: 2,
onSearch: function ({ currentValue }) {
const api = `https://nominatim.openstreetmap.org/search?format=geojson&limit=5&q=${encodeURI(
currentValue
)}`;
/**
* Promise
*/
return new Promise((resolve) => {
fetch(api)
.then((response) => response.json())
.then((data) => {
resolve(data.features);
})
.catch((error) => {
console.error(error);
});
});
},
onResults: ({ currentValue, matches, template }) => {
const regex = new RegExp(currentValue, "i");
// checking if we have results if we don't
// take data from the noResults method
return matches === 0
? template
: matches
.map((element) => {
return `
<li role="option">
<p>${element.properties.display_name.replace(
regex,
(str) => `<b>${str}</b>`
)}</p>
</li> `;
})
.join("");
},
onSubmit: ({ object }) => {
const { display_name } = object.properties;
const cord = object.geometry.coordinates;
// custom id for marker
// const customId = Math.random();
// remove last marker
map.eachLayer(function (layer) {
if (layer.options && layer.options.pane === "markerPane") {
if (layer._icon.classList.contains("leaflet-marker-locate")) {
map.removeLayer(layer);
}
}
});
// add marker
const marker = L.marker([cord[1], cord[0]], {
title: display_name,
});
// add marker to map
marker.addTo(map).bindPopup(display_name);
// set marker to coordinates
map.setView([cord[1], cord[0]], 8);
// add class to marker
L.DomUtil.addClass(marker._icon, "leaflet-marker-locate");
},
// the method presents no results
noResults: ({ currentValue, template }) =>
template(`<li>No results found: "${currentValue}"</li>`),
});
}
其实就是在最外面套了一个function leafletSearch(map) {}
然后就到ts中引用一下它,写法如下
declare function leafletSearch(map): any
然后,地图上就能使用搜索地址的功能了 。
以上就是这次的小总结~