让我们创建一个表单,在 地图中使用当前位置!

Avatar of Eugene Ambass
Eugene Ambass

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

我喜欢网上购物。我可以在网上找到我需要的东西,而且大多数东西的价格都很合理。我目前是尼日利亚人,在印度工作和学习,网上购物时有两件事让我很头疼

  1. 填写信用卡表单
  2. 填写送货和账单地址表单

也许我只是懒惰,但这些事情并非没有挑战!对于第一个问题,由于 PayPal 和电子钱包等支付处理服务的出现,我既不必为我访问的每个新的电子商务网站输入我的 12 位信用卡号码,也不必将我的信用卡详细信息保存在他们那里。

对于第二个问题,大多数购物网站提供的唯一省时选项是保存您的送货地址,但您仍然需要填写表单(啊!)。这就是挑战所在。我的大部分订单都被退回了,因为我的地址(我认为是正确的地址)由于某种原因无法被应用程序定位或确认。

地址输入很困难

通过输入表单获取用户的地址是一个干净的解决方案,但对用户来说也可能是一项艰巨的任务。原因如下

  • 如果用户在一个特定城市是新手,他们可能不知道他们的完整地址
  • 如果用户想运送到一个未保存的新地址(例如,运送到工作场所或朋友的地址而不是保存的家庭地址)
  • 如果用户居住在地址系统非常复杂的城市
  • 如果用户像我一样纯粹懒惰

潜在解决方案:自动获取地址

只需点击/点击按钮即可获取用户的地址。是的,这很容易!UX 非常棒,因为它节省了用户填写表单的时间和精力。在某些情况下,它还可以节省商店所有者的时间、精力,甚至金钱,因为错误订单或发货的数量可能会减少。

让我们构建一个小型应用程序,该应用程序获取用户的地址并在 Google 地图界面上显示它,使用原生 JavaScript。概念如下

  1. 获取 HTML 按钮并侦听点击事件
  2. 点击按钮时获取用户的地理位置(纬度和经度)
  3. 在地图上显示用户的地理位置
  4. 将纬度和经度传递到 Google 地图地理编码 API URL
  5. 在 UI 上显示返回的地址(或地址列表),供用户选择一个
  6. 侦听地图事件并重复步骤 4 和 5
  7. 使用用户选择的地址数据预填充表单

入门和设置

要构建此应用程序,我们将使用 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 密钥才能执行此操作。以下是如何获取密钥

  1. 登录您的 Google 开发者控制台帐户
  2. 创建一个新项目或选择一个现有项目
  3. 点击“启用 API 和服务”
  4. 选择“地图 Javascript API”选项
  5. 在弹出的新页面上点击“启用”。返回上一页,搜索“地理编码 API”,点击并启用它
  6. 然后,在页面右侧的导航栏中,点击“凭据”,复制页面上的 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 获取可读地址并将其转换为地理(纬度和经度)坐标,并在地图上标记该点。

反向地理编码则相反。它获取纬度和经度,并将它们转换为可读地址。 地理编码和反向地理编码都有很好的文档记录。

以下是我们的应用程序的工作原理

  1. 用户点击“使用我的位置”按钮
  2. 使用 HTML5 地理位置 API (navigator.geolocation) 定位用户
  3. 我们获取用户的地理坐标
  4. 我们将坐标传递到地理编码请求 API
  5. 我们将结果地址显示给用户

大多数情况下,地理编码会返回多个地址,因此我们必须向用户显示所有返回的地址,并让他们选择最准确的地址。

呼!最后,我们可以进入实际编写 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();
});

当我们按钮的点击处理程序运行时,它会

  1. 隐藏按钮
  2. 提醒用户我们正在获取他们的当前位置(Materialize 中的“Toast”就像一个弹出通知)
  3. 调用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";

第一行获取我们的 latlng 值,并将其封装在 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 获取的 latlng 坐标)和地图的缩放级别。最后,我们创建 Google Maps 类的实例并将其传递到我们的地图中。简单来说,我们实例化了 Google Maps 类。

要创建地图实例,我们在构造函数中指定两个参数:地图将显示的 divmapOptions。在我们的例子中,我们的 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);
}

在此代码中需要注意一些事项

  1. position 属性将标记定位在指定的 latlng 位置
  2. map 属性指定应渲染标记的地图实例(在我们的例子中,它是 Gmap
  3. animation 属性为我们的标记添加了一些 BOUNCE 效果
  4. clickable 属性设置为 true 表示我们的标记可以被点击
  5. 最后,我们在 Gmarker 实例变量中实例化 Marker 类

到目前为止,我们已经获取了用户的位置,渲染了地图,并且用户可以在地图上看到其当前位置。一切看起来都很不错!🕺

步骤 4:将经纬度传递到地理编码 API

Google 的地理编码 API 将用于将用户的数字地理坐标转换为格式化、人类可读的地址,使用我们之前介绍的**反向****地理编码**过程。

URL 采用以下形式

https://maps.googleapis.com/maps/api/geocode/outputFormat?parameters

…其中 outputFormat 可以是 jsonxml,它决定了用于传递数据的数据格式。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 函数接受两个参数 (latlng),将它们连接起来形成一个新的 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 中显示结果以供用户使用。这需要两件事

  1. 创建一个处理创建 HTML 元素的新函数
  2. 更新我们的 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 元素(divinputlabel),将 inputlabel 附加到 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 地图事件的所有信息。

我们想要侦听三个事件

  1. drag:当用户开始拖动并继续拖动地图时触发
  2. dragend:当用户停止拖动地图时触发
  3. 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 函数接收到的 latlng 值相同。如果不相同,则在空闲两秒后调用 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 函数。此函数目前仅执行一项操作,即将新的 latlng 值传递给 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) 创建。