我喜欢网上购物。我可以在网上找到我需要的东西,而且大多数东西的价格都很合理。我目前是尼日利亚人,在印度工作和学习,网上购物时有两件事让我很头疼
- 填写信用卡表单
- 填写送货和账单地址表单
也许我只是懒惰,但这些事情并非没有挑战!对于第一个问题,由于 PayPal 和电子钱包等支付处理服务的出现,我既不必为我访问的每个新的电子商务网站输入我的 12 位信用卡号码,也不必将我的信用卡详细信息保存在他们那里。
对于第二个问题,大多数购物网站提供的唯一省时选项是保存您的送货地址,但您仍然需要填写表单(啊!)。这就是挑战所在。我的大部分订单都被退回了,因为我的地址(我认为是正确的地址)由于某种原因无法被应用程序定位或确认。
地址输入很困难
通过输入表单获取用户的地址是一个干净的解决方案,但对用户来说也可能是一项艰巨的任务。原因如下
- 如果用户在一个特定城市是新手,他们可能不知道他们的完整地址
- 如果用户想运送到一个未保存的新地址(例如,运送到工作场所或朋友的地址而不是保存的家庭地址)
- 如果用户居住在地址系统非常复杂的城市
- 如果用户像我一样纯粹懒惰
潜在解决方案:自动获取地址
只需点击/点击按钮即可获取用户的地址。是的,这很容易!UX 非常棒,因为它节省了用户填写表单的时间和精力。在某些情况下,它还可以节省商店所有者的时间、精力,甚至金钱,因为错误订单或发货的数量可能会减少。
让我们构建一个小型应用程序,该应用程序获取用户的地址并在 Google 地图界面上显示它,使用原生 JavaScript。概念如下
- 获取 HTML 按钮并侦听点击事件
- 点击按钮时获取用户的地理位置(纬度和经度)
- 在地图上显示用户的地理位置
- 将纬度和经度传递到 Google 地图地理编码 API URL
- 在 UI 上显示返回的地址(或地址列表),供用户选择一个
- 侦听地图事件并重复步骤 4 和 5
- 使用用户选择的地址数据预填充表单
入门和设置
要构建此应用程序,我们将使用 Materialize CSS 框架来节省我们一些时间来处理样式。Materialize 是一个基于 Google 的 Material Design 系统 的现代响应式前端框架。 测试版 可与原生 JavaScript 一起使用。
在文档中使用 Materialize 的 CSS 和 JavaScript 文件的基本设置如下所示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Address Locator</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
我们还将使用 Google 地图 API 来显示地图并获取用户的可读地址。我们需要一个 API 密钥才能执行此操作。以下是如何获取密钥
- 登录您的 Google 开发者控制台帐户
- 创建一个新项目或选择一个现有项目
- 点击“启用 API 和服务”
- 选择“地图 Javascript API”选项
- 在弹出的新页面上点击“启用”。返回上一页,搜索“地理编码 API”,点击并启用它
- 然后,在页面右侧的导航栏中,点击“凭据”,复制页面上的 API 密钥并将其保存到文件中
现在,让我们更新我们的文档以显示地图并让用户知道它可以用来获取他们的当前位置作为地址。此外,我们将添加一个表单,该表单使用用户选择的地址预填充。
...
<body>
<div class="container">
<h3>Shipping Address</h3>
<p>You can click the button below to use your current location as your shipping address</p>
<div id="map">
</div>
<button id="showMe" class="btn">Use My Location</button>
<form id="shippingAddress">
<div id="locationList"></div>
<br>
<div class="input-field">
<textarea class="input_fields materialize-textarea" id="address" type="text"></textarea>
<label class="active" for="address">Address (Area and Street)</label>
</div>
<div class="input-field">
<input class="input_fields" id="locality" type="text">
<label class="active" for="locality">Locality</label>
</div>
<div class="input-field">
<input class="input_fields" id="city" type="text">
<label class="active" for="city">City/District/Town</label>
</div>
<div class="input-field">
<input class="input_fields" id="postal_code" type="text">
<label class="active" for="pin_code">Pin Code</label>
</div>
<div class="input-field">
<input class="input_fields" id="landmark" type="text">
<label class="active" for="landmark">Landmark</label>
</div>
<div class="input-field">
<input class="input_fields" id="state" type="text">
<label class="active" for="State">State</label>
</div>
</form>
<!-- You could add a fallback address gathering form here -->
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
<script src="js/main.js"></script>
</body>
</html>
趁我们在这里,让我们稍微调整一下样式,使它看起来更好看一点
.container {
width: 50%;
max-width: 800px;
}
#map {
height: 50vh;
margin-bottom: 10px;
display: none;
}
#locationList .card {
padding: 10px;
}
#toast-container {
top: 50%;
bottom: unset;
}
.toast {
background-color: rgba(0, 0, 0, 0.8);
}
@media only screen and (max-width: 768px) {
.container {
width: 80%;
}
}
此 CSS 隐藏地图,直到我们准备好查看它。我们的应用程序应该如下所示

让我们计划一下
我们的应用程序将使用 HTML5 地理位置 API 来确定我们用户的当前位置,以及 Google 的地理编码 API,使用一种称为反向地理编码的技术。地理编码 API 获取可读地址并将其转换为地理(纬度和经度)坐标,并在地图上标记该点。
反向地理编码则相反。它获取纬度和经度,并将它们转换为可读地址。 地理编码和反向地理编码都有很好的文档记录。
以下是我们的应用程序的工作原理
- 用户点击“使用我的位置”按钮
- 使用 HTML5 地理位置 API (
navigator.geolocation
) 定位用户 - 我们获取用户的地理坐标
- 我们将坐标传递到地理编码请求 API
- 我们将结果地址显示给用户
大多数情况下,地理编码会返回多个地址,因此我们必须向用户显示所有返回的地址,并让他们选择最准确的地址。
呼!最后,我们可以进入实际编写 JavaScript 的有趣部分了。让我们回顾一下我们概述的每个步骤。
步骤 1:点击按钮
在我们的main.js
文件中,让我们获取对 HTML 按钮的引用。同时,我们将设置一些我们需要的其他变量,例如我们的 API 密钥。
//This div will display Google map
const mapArea = document.getElementById('map');
//This button will set everything into motion when clicked
const actionBtn = document.getElementById('showMe');
//This will display all the available addresses returned by Google's Geocode Api
const locationsAvailable = document.getElementById('locationList');
//Let's bring in our API_KEY
const __KEY = 'YOUR_API_KEY';
//Let's declare our Gmap and Gmarker variables that will hold the Map and Marker Objects later on
let Gmap;
let Gmarker;
//Now we listen for a click event on our button
actionBtn.addEventListener('click', e => {
// hide the button
actionBtn.style.display = "none";
// call Materialize toast to update user
M.toast({ html: 'fetching your current location', classes: 'rounded' });
// get the user's position
getLocation();
});
当我们按钮的点击处理程序运行时,它会
- 隐藏按钮
- 提醒用户我们正在获取他们的当前位置(Materialize 中的“Toast”就像一个弹出通知)
- 调用
getLocation
函数
步骤 2:获取用户的地理位置(纬度和经度)
当我们的getLocation
函数被调用时,我们需要做更多工作。首先,让我们检查我们是否可以使用地理位置 API
getLocation = () => {
// check if user's browser supports Navigator.geolocation
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(displayLocation, showError, options);
} else {
M.toast({ html: "Sorry, your browser does not support this feature... Please Update your Browser to enjoy it", classes: "rounded" });
}
}
当我们有支持时,它会调用地理位置的getCurrentPosition
方法。如果没有支持,则会提醒用户浏览器不支持。
如果有支持,则使用getCurrentLocation
方法获取设备的当前位置。语法如下
navigator.geolocation.getCurrentPosition(*success, error, [options]*)
success
:这是一个回调函数,它将位置作为其唯一参数。对我们来说,我们的成功回调函数是displayLocation
函数。error
:[可选]这是一个回调函数,它将PositionError
作为其唯一的输入参数。您可以在这里了解更多信息 这里。我们的错误回调函数是showError
函数。options
:[可选]这是一个对象,它描述了要传递给getCurrentPosition
方法的options
属性。您可以在这里了解更多信息 这里。我们的选项参数是options
对象。
在编写我们的displayLocation
函数之前,让我们处理showError
函数和options
对象
// Displays the different error messages
showError = (error) => {
mapArea.style.display = "block"
switch (error.code) {
case error.PERMISSION_DENIED:
mapArea.innerHTML = "You denied the request for your location."
break;
case error.POSITION_UNAVAILABLE:
mapArea.innerHTML = "Your Location information is unavailable."
break;
case error.TIMEOUT:
mapArea.innerHTML = "Your request timed out. Please try again"
break;
case error.UNKNOWN_ERROR:
mapArea.innerHTML = "An unknown error occurred please try again after some time."
break;
}
}
//Makes sure location accuracy is high
const options = {
enableHighAccuracy: true
}
现在,让我们在main.js
文件中编写displayLocation
函数的代码
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
}
现在我们有了用户的纬度和经度,我们可以在控制台中通过在displayLocation
内部编写以下代码来查看它们
console.log( `Current Latitude is ${lat} and your longitude is ${lng}` );
步骤 3:在 Google 地图上显示用户的当前位置
为此,我们将把以下代码行添加到我们的 displayLocation
函数中。
const latlng = {lat, lng}
showMap(latlng);
createMarker(latlng);
mapArea.style.display = "block";
第一行获取我们的 lat
和 lng
值,并将其封装在 latlng
对象字面量中。这使得我们在应用程序中更容易使用它。
第二行代码调用一个 showMap
函数,该函数接受一个 latlng
参数。在这里,我们可以实例化我们的 Google 地图并在 UI 中呈现它。
第三行调用一个 createMarker
函数,该函数也接受我们的对象字面量 (latlng
) 作为其参数,并使用它为我们创建一个 Google 地图标记。
第四行使 mapArea
可见,以便我们的用户现在可以看到该位置。
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const latlng = { lat, lng }
showMap(latlng);
createMarker(latlng);
mapArea.style.display = "block";
}
现在,让我们开始创建我们的函数。我们将从 showMap
函数开始。
showMap = (latlng) => {
let mapOptions = {
center: latlng,
zoom: 17
};
Gmap = new google.maps.Map(mapArea, mapOptions);
}
showMap
函数创建一个 mapOptions
对象,其中包含地图中心(即我们从 displayLocation
获取的 lat
和 lng
坐标)和地图的缩放级别。最后,我们创建 Google Maps 类的实例并将其传递到我们的地图中。简单来说,我们实例化了 Google Maps 类。
要创建地图实例,我们在构造函数中指定两个参数:地图将显示的 div
和 mapOptions
。在我们的例子中,我们的 div 被称为 mapArea
,我们的 mapOptions
被称为 mapOptions
。在此之后,我们创建的地图将显示出来,但没有标记。我们需要一个标记,以便用户可以在地图上识别其当前位置。
让我们使用 createMarker
函数创建我们的标记
createMarker = (latlng) => {
let markerOptions = {
position: latlng,
map: Gmap,
animation: google.maps.Animation.BOUNCE,
clickable: true
};
Gmarker = new google.maps.Marker(markerOptions);
}
在此代码中需要注意一些事项
position
属性将标记定位在指定的latlng
位置map
属性指定应渲染标记的地图实例(在我们的例子中,它是Gmap
)animation
属性为我们的标记添加了一些BOUNCE
效果clickable
属性设置为true
表示我们的标记可以被点击- 最后,我们在
Gmarker
实例变量中实例化 Marker 类
到目前为止,我们已经获取了用户的位置,渲染了地图,并且用户可以在地图上看到其当前位置。一切看起来都很不错!🕺

步骤 4:将经纬度传递到地理编码 API
Google 的地理编码 API 将用于将用户的数字地理坐标转换为格式化、人类可读的地址,使用我们之前介绍的**反向****地理编码**过程。
URL 采用以下形式
https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters
…其中 outputFormat
可以是 json
或 xml
,它决定了用于传递数据的数据格式。parameters
部分是请求所需的参数列表。
我们的请求 URL 将如下所示
https://maps.googleapis.com/maps/api/geocode/json?latlng=${latlng}&key=${__KEY}
让我们继续连接到 API。我们将在名为 getGeolocation
的函数中执行此操作。
getGeolocation = (lat, lng) => {
const latlng = lat + "," + lng;
fetch( `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latlng}&key=${__KEY}` )
.then(res => res.json())
.then(data => console.log(data.results));
}
getGeolocation
函数接受两个参数 (lat
和 lng
),将它们连接起来形成一个新的 latlng
变量,并将其传递到 URL 中。
使用 Fetch API(此处了解更多信息),我们将新的 latlng
和 __KEY
添加到 Geocode 请求 URL 中。然后,在我们收到的响应对象上,我们传递 .json
方法来使用 JSON 解析 Promise。最后,我们在控制台中记录响应。
为了利用我们新创建的函数,我们必须在 displayLocation
函数中调用它。因此,让我们更新 displayLocation
函数以包含 getGeolocation
函数调用
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const latlng = { lat, lng }
showMap(latlng);
createMarker(latlng);
mapArea.style.display = "block";
getGeolocation(lat, lng)// our new function call
}
返回的数据应如下所示
{
"results" :
{
"address_components":
{
"long_name": "1600",
"short_name": "1600",
"types": ["street_number"]
},
{
"long_name": "Amphitheatre Pkwy",
"short_name": "Amphitheatre Pkwy",
"types": ["route"]
},
{
"long_name": "Mountain View",
"short_name": "Mountain View",
"types": ["locality", "political"]
},
{
"long_name": "Santa Clara County",
"short_name": "Santa Clara County",
"types": ["administrative_area_level_2", "political"]
},
{
"long_name": "California",
"short_name": "CA",
"types": ["administrative_area_level_1", "political"]
},
{
"long_name": "United States",
"short_name": "US",
"types": ["country", "political"]
},
{
"long_name": "94043",
"short_name": "94043",
"types": ["postal_code"]
}
],
"formatted_address": "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
"geometry": {
"location": {
"lat": 37.4224764,
"lng": -122.0842499
},
"location_type": "ROOFTOP",
"viewport": {
"northeast": {
"lat": 37.4238253802915,
"lng": -122.0829009197085
},
"southwest": {
"lat": 37.4211274197085,
"lng": -122.0855988802915
}
}
},
"place_id": "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"types": ["street_address"]
}
],
"status" : "OK"
}
步骤 5:显示返回的地址(供用户选择)
在此阶段,我们已经向 Google 的地理编码 API 发出了请求,并将结果记录在控制台中。现在,我们必须在 UI 中显示结果以供用户使用。这需要两件事
- 创建一个处理创建 HTML 元素的新函数
- 更新我们的
getGeolocation
函数以进行函数调用
让我们创建负责创建 HTML 元素和更新 DOM 的函数。
populateCard = (geoResults) => {
geoResults.map(geoResult => {
// first create the input div container
const addressCard = document.createElement('div');
// then create the input and label elements
const input = document.createElement('input');
const label = document.createElement('label');
// then add materialize classes to the div and input
addressCard.classList.add("card");
input.classList.add("with-gap");
// add attributes to them
label.setAttribute("for", geoResult.place_id);
label.innerHTML = geoResult.formatted_address;
input.setAttribute("name", "address");
input.setAttribute("type", "radio");
input.setAttribute("value", geoResult.formatted_address);
input.setAttribute("id", geoResult.place_id);
addressCard.appendChild(input);
addressCard.appendChild(label)
return (
// append the created div to the locationsAvailable div
locationsAvailable.appendChild(addressCard)
);
})
}
在此函数中,我们遍历结果并创建一些 HTML 元素(div
、input
和 label
),将 input
和 label
附加到 div
,最后将新的 div
附加到父 div
(即 locationsAvailable
)。一旦我们从 API 调用中获取结果,我们的 DOM 将被创建并显示给用户。
接下来,我们更新 getGeolocation
函数以调用我们的 populateCard
函数,方法是用以下内容替换 getGeolocation
的最后一行
.then(data => populateCard(data.results));
…这意味着我们更新后的函数应如下所示
getGeolocation = (lat, lng) => {
const latlng = lat + "," + lng;
fetch( `https://maps.googleapis.com/maps/api/geocode/json?latlng=${latlng}&key=${__KEY}` )
.then(res => res.json())
.then(data => populateCard(data.results));
}
此时,一切应该都能正常工作。我们的用户点击一个按钮,在地图上显示一个位置,以及与当前位置匹配的地址列表。

步骤 6:侦听地图事件并重复步骤 4 和 5
如果我们的用户决定移动地图或标记,UI 不会发生任何变化——不会显示新的地址,并且所有内容都保持静态。我们必须修复此问题,因此让我们通过侦听地图事件来使我们的应用程序变得动态。您可以在此处阅读有关Google 地图事件的所有信息。
我们想要侦听三个事件
drag
:当用户开始拖动并继续拖动地图时触发dragend
:当用户停止拖动地图时触发idle
:当每个事件都触发并且地图处于空闲状态时触发
**快速问题:**为什么这些事件最适合我们的应用程序?
**快速回答:**前两个事件将确保我们的地图标记在拖动事件期间保持在地图的中心,而空闲事件将使用新的坐标发出地理编码请求。
要侦听这些事件,我们必须使用以下内容更新 showMap
函数
Gmap.addListener('drag', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('dragend', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('idle', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
if (Gmarker.getPosition().lat() !== lat || Gmarker.getPosition().lng() !== lng) {
setTimeout(() => {
updatePosition(this.getCenter().lat(), this.getCenter().lng()); // update position display
}, 2000);
}
});
如上所述,前两个事件侦听器只是确保标记保持在地图的中心。请密切注意 idle
事件侦听器,因为那里是关键所在。
一旦触发空闲事件,标记将移动到中心,然后进行检查以确定标记的当前位置是否与 displayLocation
函数接收到的 lat
或 lng
值相同。如果不相同,则在空闲两秒后调用 updatePosition
函数。
话虽如此,我们必须对 showMap
函数进行一些更新。首先,在函数头部,我们必须包含更多参数,并在 showMap
函数调用中包含更多参数。我们还需要在那里添加新的参数。我们的 showMap
函数应如下所示
showMap = (latlng, lat, lng) => {
let mapOptions = {
center: latlng,
zoom: 17
};
Gmap = new google.maps.Map(mapArea, mapOptions);
Gmap.addListener('drag', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('dragend', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
});
Gmap.addListener('idle', function () {
Gmarker.setPosition(this.getCenter()); // set marker position to map center
if (Gmarker.getPosition().lat() !== lat || Gmarker.getPosition().lng() !== lng) {
setTimeout(() => {
updatePosition(this.getCenter().lat(), this.getCenter().lng()); // update position display
}, 2000);
}
});
}
而我们的 displayLocation
函数应如下所示
displayLocation = (position) => {
const lat = position.coords.latitude;
const lng = position.coords.longitude;
const latlng = { lat, lng }
showMap(latlng, lat, lng); //passed lat and lng as the new arguments to the function
createMarker(latlng);
mapArea.style.display = "block";
getGeolocation(lat, lng);
}
在侦听地图事件后,让我们重复步骤 4 和步骤 5。
我们首先编写 updatePosition
函数。此函数目前仅执行一项操作,即将新的 lat
和 lng
值传递给 getGeolocation
函数
updatePosition = (lat, lng) => {
getGeolocation(lat, lng);
}
获取新位置并获取地址后,我们的 DOM 应该为用户重新渲染,对吧?嗯,它没有。为了解决这个问题,我们创建一个函数来强制 DOM 重新渲染
// check if the container has a child node to force re-render of dom
function removeAddressCards(){
if (locationsAvailable.hasChildNodes()) {
while (locationsAvailable.firstChild) {
locationsAvailable.removeChild(locationsAvailable.firstChild);
}
}
}
它检查 locationsAvailable
div
是否有任何 childNode
,如果有,则在创建新的地址卡片之前删除它们。populateCard
函数现在更新为以下内容
populateCard = (geoResults) => {
// check if a the container has a child node to force re-render of dom
removeAddressCards();
geoResults.map(geoResult => {
// first create the input div container
const addressCard = document.createElement('div');
// then create the input and label elements
const input = document.createElement('input');
const label = document.createElement('label');
// then add materialize classes to the div and input
addressCard.classList.add("card");
input.classList.add("with-gap");
// add attributes to them
label.setAttribute("for", geoResult.place_id);
label.innerHTML = geoResult.formatted_address;
input.setAttribute("name", "address");
input.setAttribute("type", "radio");
input.setAttribute("value", geoResult.formatted_address);
input.setAttribute("id", geoResult.place_id);
addressCard.appendChild(input);
addressCard.appendChild(label);
return (
locationsAvailable.appendChild(addressCard);
);
})
}
我们完成了,现在能够完全获取和显示用户地址了!
步骤 7:使用用户选择的地址数据预填充表单
最后一步是使用用户选择的地址填充表单。我们需要向地址卡片添加一个点击事件侦听器,并将地址作为参数传递给回调函数。
以下是在 populateCard
函数中添加事件侦听器的方法
input.addEventListener('click', () => inputClicked(geoResult));
您应该注意,上面回调函数中的 geoResult
参数是来自 results
数组的选定地址对象。也就是说,更新 populateCard
函数以适应我们的新代码行。
inputClicked
函数使用一系列 if
语句为我们的表单元素赋值。因此,在处理它之前,让我们将表单元素引入等式
const inputAddress = document.getElementById('address'),
inputLocality = document.getElementById('locality'),
inputPostalCode = document.getElementById('postal_code'),
inputLandmark = document.getElementById('landmark'),
inputCity = document.getElementById('city'),
inputState = document.getElementById('state');
完成此操作后,让我们现在开始使用 inputClicked
函数中的 address_components
预填充表单。
inputClicked = result => {
result.address_components.map(component => {
const types = component.types
if (types.includes('postal_code')) {
inputPostalCode.value = component.long_name
}
if (types.includes('locality')) {
inputLocality.value = component.long_name
}
if (types.includes('administrative_area_level_2')) {
inputCity.value = component.long_name
}
if (types.includes('administrative_area_level_1')) {
inputState.value = component.long_name
}
if (types.includes('point_of_interest')) {
inputLandmark.value = component.long_name
}
});
inputAddress.value = result.formatted_address;
// to avoid labels overlapping pre-filled input contents
M.updateTextFields();
// removes the address cards from the UI
removeAddressCards();
}
以上代码块遍历所点击(或选择的)地址组件,检查组件的类型,最后如果匹配则将其分配给输入字段。

M.updateTextFields()
函数来自 Materialize,它确保标签不会与输入字段值重叠,而 removeAddressCards()
函数则从 UI 中删除地址卡片。
至此,我们的应用程序开发完成,为用户节省了大量的输入和烦恼!他们一定会感谢我们实施了如此轻松便捷的解决方案。
整个用户体验实验可以看作是一个捷径,帮助用户预先填写送货地址表单。我们应该在此明确说明,**返回的地址并非总是100%准确**。但这就是为什么我们允许在UI中手动编辑地址的原因。
演示!
查看CodePen上的示例 使用地理位置和Google Maps预填充地址表单,由CSS-Tricks (@css-tricks) 创建。
好主意,但需要注意:如果您在欧盟拥有客户,那么由于GDPR,您可能需要放弃这种方法,因为将用户位置数据传输到Google Maps很难证明其必要性,因为它不是提供服务所必需的。(您可以征求用户的同意,但这会引发一系列其他问题,因为同意可以撤回,这将要求您确保Google删除您传输的这些位置数据。)
数据是匿名的和临时的。几句措辞恰当的句子就足够了。您唯一存储的信息是他们的地址,这属于履行合同的范畴。
当我在此页面上运行演示时,它返回“您拒绝了访问您位置的请求”。我的浏览器(Chrome)位置权限设置为“访问前询问”,但它从未提示任何权限。当我直接在CodePen上尝试演示时,它不会显示该消息,但它也不会显示地图界面。
这是因为它位于iframe内……在新标签页中打开
https://codepen.io/team/css-tricks/full/XBmazq/
这很有趣——当我取消最大化浏览器窗口时,它弹出了“codepen.io想要了解您的位置”,然后它正常工作了。有趣。
getLocation、displayLocation和showMap似乎是隐式的全局变量。
看起来不错,但只有在您在家购物时才有效,但大多数人在工作时购物。:-p
喜欢这个主意。但请记住,地理位置可能非常不可靠,具体取决于网络和设备类型,如果定位不准确,可能会让用户更加困惑。我刚刚测试了CodePen演示,即使我身处一个人口稠密的城市,位置也偏离了大约半英里。这在支持GPS的设备上可能效果很好。但网络地理定位,效果不佳。
我在Windows 10 64位上测试了CodePen演示。我住在比利时鲁汶市。
IE11:CodePen不支持IE11。HTML可以在“调试”模式下呈现,但效果不大。
Chrome:非常好!Chrome询问我是否要允许位置查找。当我同意后,它返回了邻居的地址(大约50英尺远)。
Edge:我放弃了测试。似乎授予Edge使用位置服务的权限需要通过Windows设置进行繁琐的操作。