Fun with MVC Objects(玩转 MVC 对象)

来源:互联网 发布:买淘宝店铺被找回再卖 编辑:程序博客网 时间:2024/06/05 03:43

Objective

目标

Google Maps Javascript API V3 has introduced the implementation of MVC objects that allow map objects to store state and update their presentation automatically, which are awesome, but what can you do with them?

 

Google Maps JavaScript API V3 引入了 MVC 对象的实现,从而允许地图对象存储状态信息并自动更新其显示内容,这很神奇,但是您能用它们做些什么呢?

 

This article presents a basic introduction to using MVC objects within V3. You will learn how to use the Maps Javascript API V3 MVC framework to create objects that automatically respond to state changes. You will build a resizable distance widget and by the end, you'll have a greater understanding on what MVC objects are, how to use them, and why they're just so "awesome".

 

本文简要介绍了如何在 V3 中使用 MVC 对象。您将了解如何使用 Google Maps JavaScript API V3 MVC 框架创建可自动响应状态变化的对象。您将构建一个可调整大小的距离窗口小部件;最终,您可以籍此深入了解 MVC 对象是什么、如何使用它们以及它们为何如此“神奇”。

 

Before you begin, look over the API reference, and in particular the MVCObject class.

 

在开始之前,请参阅 API 参考,尤其是 MVCObject 类。

 

The tutorial is broken up into the following steps:

  1. Getting Started
  2. Creating the Distance Widget
  3. Binding Properties
  4. Add a Resizing Marker
  5. Making It Work
  6. Outputting Information
  7. What Can Be Done With It?

 

 

本辅导手册分为以下几个步骤:

  1. 使用入门
  2. 创建距离窗口小部件
  3. 绑定属性
  4. 添加调整大小标记
  5. 使其发挥作用
  6. 输出信息
  7. 用它可以做什么?

    Getting Started 

      使用入门

Start off by creating an HTML page that loads a map.

首先,让我们创建一个要载入地图的 HTML 网页。

 

A brief explanation of the code above (step1).

  1. Add a DOCTYPE at the top of the page, in this case a HTML5 DOCTYPE. This instruction tells the browser how to render the page
  2. Create a style section and set the height of the map to '500px'. It is not necessary to include a width because default display property of a <div> element is 'block' which means it will take up as much room that is available
  3. Add a script tag to include the google maps api code
  4. Add another script tag that contains the basics of loading a map. The key part here is the event listener that calls the function init() once the page has loaded. This is a nice habit to get into rather than using techniques like onload because it allows the separation of Javascript and HTML code and also allows other functions to attach to the same event.

上述代码(步骤 1)的简单说明。

  1. 在该网页顶部添加一个 DOCTYPE,本例中是 HTML5 DOCTYPE。该说明可告诉浏览器如何渲染网页。
  2. 创建一个样式部分,并将地图的高度设为“500px”。这里不需要包含宽度,因为 <div> 元素的默认显示属性是“block”,这意味着它将获取所有可能的空间。
  3. 添加一个 script 标记以包含 Google Maps API 代码。
  4. 添加另一个 script 标记,其中包含用于载入地图的基本代码。这里的关键部分是事件侦听器,它将在网页完成载入后调用函数 init()。与使用 onload 等技术相比,这是一种更好的习惯做法,因为它允许将 JavaScript 和 HTML 代码分开,还允许其他函数附加至相同的事件。

 Creating the Distance Widget

 创建距离窗口小部件

The next step is to create the Distance widget. This widget is essentially a circle, a marker in the center of the circle and another marker on the circumference. When the center marker is dragged, it will also move the circle and the circumference marker. When the circumference marker is dragged, the circle's radius either grows or shrinks based on whether the marker is pulled away or towards the center. Simple!

下一步是创建距离窗口小部件。该窗口小部件实质上是一个圆,圆心处有一个标记,另一个标记在圆周上。当您拖动圆心标记时,会同时移动圆和圆周标记。当您拖动圆周标记时,根据该标记是远离还是逼近圆心,圆的半径将相应增加或缩小。非常简单!

 

Firstly create the Distance widget contructor that will take one parameter 'map' which is a google.maps.Map class. The widget will also subclass the google.maps.MVCObject instance and that is done by setting the object's prototype to MVCObject.

首先我们创建距离窗口小部件构造器,它将获取一个参数“map”,该参数是一个 google.maps.Map 类。该窗口小部件还将设置一个 google.maps.MVCObject 子类实例,这是通过将该对象的原型设置为 MVCObject 实现的。

 

Then create a draggable marker, put it on the center of the map and use MVC techniques to bind properties.

然后我们创建一个可拖动的标记,将其放在地图的中心,并使用 MVC 技术绑定属性。

Add to the init() function some code to create a new DistanceWidget.

init() 函数添加一些代码以创建一个新 DistanceWidget

  

The important part to take away is the two bindTo() methods that were used. By binding the marker's map property to the DistanceWidget, it means that the values are tied together. So if the map is changed by using distanceWidget.set('map', myOtherMap); then the DistanceWidget will change to the new map without having to add any extra code. Pretty cool isn't it?

其中值得注意的重要部分是所使用的两个 bindTo() 方法。通过将标记的 map 属性绑定到 DistanceWidget,这意味着我们将值绑在了一起。因此,如果我们通过使用 distanceWidget.set('map', myOtherMap); 更改了地图,DistanceWidget 将更改为新地图而无需额外添加任何代码。是不是很酷?

 

This might be confusing at the start, but the simplest way to think about it is this. Given there are two objects, A and B, bound on the same property, if object A updates the bound property, then object B's property will be updated to reflect the new value of object A and vice versa.

开始时这可能会令人感到有些困惑,不过我们可以用这样一种最简单的方式来理解它。假设有两个对象 A 和 B 绑定在相同的属性上,如果对象 A 更新了所绑定的属性,则对象 B 的属性也将更新以反映对象 A 的新值,反之亦然。

 

Now you should have a map with a marker that you can drag around (step2). While dragging, the MVC object is updating the DistanceWidget's position property with the marker's position property. It may not seem like much, but it's a start! In the next section you will create a RadiusWidget which will display a circle.

现在,您应当有了一个地图,其中还有一个可以拖动的标记(步骤 2)。拖动时,MVC 对象会根据标记的位置属性更新 DistanceWidget 的位置属性。这看起来似乎没什么,但确实是一个开始!在下一部分中,您将创建一个 RadiusWidget,它将显示为一个圆。 

Binding Properties

绑定属性

Create another widget called RadiusWidget that will be responsible for displaying a circle and eventually will be resizeable. This step is quite similar to the one above but instead of creating a marker, create a circle.

创建另一个名为 RadiusWidget 的窗口小部件,它将负责显示一个圆,最后还应将其设置为可调整大小。此步骤与前一步骤非常类似,但不是创建一个标记,而是创建一个圆。

 

Add the follow code to your javascript section. 

在您的 JavaScript 部分中添加以下代码。

Then add this code to the DistanceWidget constructor to create the RadiusWidget.

然后将此代码添加到 DistanceWidget 构造器中以创建 RadiusWidget

By looking at the code you can see a few things going on:

  1. The RadiusWidget is bound to the DistanceWidget's map property
  2. The RadiusWidget has bound it's center property to the DistanceWidget's position property
  3. The RadiusWidget sets a property distance on itself
  4. The circle is bound to the the RadiusWidget's center, map and radius properties

 

通过查看代码,您会发现事情有了新变化:

  1. RadiusWidget 绑定到 DistanceWidget 的 map 属性。
  2. RadiusWidget 将其 center 属性绑定到 DistanceWidgetposition 属性。
  3. RadiusWidget 为自己设置了一个 distance 属性。
  4. 圆绑定到 RadiusWidgetcentermapradius 属性。

This step introduces using the MVC property changed methodology, in this case the distance_changed() function. This is a magic function that will be called whenever the distance property is set(). The distance_changed() function is updating the circle's radius property.

此步骤使用了 MVC 属性的 changed 方法,在本例中是 distance_changed() 函数。这是一个神奇的函数,只要 distance 属性为 set(),就会调用该函数。distance_changed() 函数将更新圆的 radius 属性。

 

Because the widget is using kilometers as its measurement but the circle uses meters, this function will convert and set the radius property of the circle. If you always wanted to work in meters you could bind the radius directly to the distance property and not have the distance_changed() function at all.

由于该窗口小部件使用公里作为其度量单位,而圆使用的单位是米,因此,此函数会转换并设置圆的 radius 属性。如果您始终希望使用米为单位,则可以将 radius 直接绑定到 distance 属性,而完全不使用 distance_changed() 函数。

 

At this point you have a marker and a circle and when you move the marker the circle moves with it (step3). Isn't this fun?

至此,您有了一个标记和一个圆,并且当您移动该标记时,圆将随之移动(步骤 3)。这是不是很有趣?

Add a Resizing Marker

添加调整大小标记

Time to add another marker into the mix. This time add a marker to the RadiusWidget that will be used to adjust the radius of the circle. This second marker will be refered to as the 'sizer' marker.

现在该向我们的组合中添加另一个标记了。这次我们要向 RadiusWidget 中添加一个标记,用于调整圆的半径。我们将这第二个标记称为“sizer”标记。

 

This steps involves:

  1. Add a marker to the RadiusWidget
  2. Bind the marker's map to the RadiusWidget's map property
  3. Bind the marker's position property to a new property on the RadiusWidget called sizer_position
  4. Add a center_changed() function that will put the marker on the circle's circumference

此步骤涉及以下内容:

  1. RadiusWidget 添加一个标记。
  2. 将该标记的 map 绑定到 RadiusWidgetmap 属性。
  3. 将该标记的 position 属性绑定到 RadiusWidget 上的一个名为 sizer_position 的新属性。
  4. 添加一个 center_changed() 函数,它将标记放在圆周上。

Create a function called addSizer_() which will create a marker and bind that to the RadiusWidget's map. Add another bindTo() so that the sizer's position property and the RadiusWidget's sizer_position property are bound together. This brings up another interesting point to note about MVC. You can bind a property to any other property, if it doesn't already exist it will automatically be created. 

创建一个名为 addSizer_() 的函数,它将创建一个标记并将其绑定至 RadiusWidgetmap。添加另一个 bindTo(),以便将 sizer 的 position 属性和 RadiusWidgetsizer_position 属性绑定在一起。这是 MVC 的另一个值得关注的地方。您可以将一个属性绑定至任何其他属性,如果该属性尚不存在,则会自动创建它。

Add this.addSizer_(); to the end of the RadiusWidget's constructor.

this.addSizer_(); 添加到 RadiusWidget 的构造器的最后。

Create a function on RadiusWidget called center_changed(). This function is going to be called every time the center value is updated and will position the sizer to be on the right edge of the circle.

RadiusWidget 上创建一个名为 center_changed() 的函数。每次中心值更新时都将调用此函数,它会将 sizer 置于圆的右边缘。

 

Check out the example (step4) and drag around the center marker. Notice how the sizer marker is now sitting on the edge of the circle and moving when you drag? Pretty fancy isn't it?

查看该示例(步骤 4)并拖动中心标记。注意观察当您拖动时 sizer 标记怎样置于圆的边缘并移动。是不是很神奇?

 

 

Making It Work

使其发挥作用

In the next section you will determine the distance between the center marker and the sizer marker whenever the sizer marker is dragged, then set the circle's radius to this distance between the two markers. This technique involves the following:

  1. Add a function that calculates the distance between two google.maps.LatLng locations
  2. Add a function that sets the distance of the circle based on the distance between the two markers
  3. Add an event listener to the sizer marker's drag event to set the radius of the circle
  4. Bind the DistanceWidget to the RadiusWidget's distance and bounds properties

在下一部分中,您将确定当拖动 sizer 标记时中心标记与 sizer 标记之间的距离,并将圆的半径设置为两个标记之间的这一距离。此技术涉及以下内容:

  1. 添加一个函数,它将计算两个 google.maps.LatLng 位置之间的距离。
  2. 添加一个函数,它将基于两个标记之间的距离设置圆的 distance
  3. 向 sizer 标记的 drag 事件添加事件侦听器,从而设置该圆的半径。
  4. DistanceWidget 绑定到 RadiusWidgetdistancebounds 属性。

 Add the following code:

 添加以下代码:

 

The function distanceBetweenPoints_() was added which will return in kilometers the distance between two google.maps.LatLng locations. For more information on this function and others like it, check out http://www.movable-type.co.uk/scripts/latlong.html. Next create a function called setDistance_ which sets the distance property of the RadiusWidget based on the distance between the two markers.

所添加的函数 distanceBetweenPoints_() 将以公里为单位传回两个 google.maps.LatLng 位置之间的距离。有关此函数和其他类似函数的详细信息,请访问 http://www.movable-type.co.uk/scripts/latlong.html。接下来,我们创建一个名为 setDistance_ 的函数,它将基于两个标记之间的距离设置 RadiusWidgetdistance 属性。

 

Then in the addSizer_ function attach a listener to the sizer marker's drag event.

然后在 addSizer_ 函数中,向 sizer 标记的 drag 事件附加一个侦听器。

Lastly in the DistanceWidget's constructor, bind to the RadiusWidget's distance and bounds properties.

最后,在 DistanceWidget 的构造器中,绑定到 RadiusWidgetdistancebounds 属性。

Now you have a center marker that when dragged also moves the circle and the sizer marker. You also have a sizer marker that when dragged resizes the circle (step5).

现在您有了一个中心标记,当您拖动它时,将同时移动圆和 sizer 标记。您还有一个 sizer 标记,当您拖动它时,可调整圆的大小(步骤 5)。

Outputting Information

输出信息

The last part demonstrates how MVC properties also act like events. In the context of the DistanceWidget, you can add event listeners to the properties that you care about. In this case, add a listener to the distance_changed and position_changed events which will call a function that will display the values.

最后我们将揭示 MVC 属性如何还能发挥类似事件的作用。在 DistanceWidget 的上下文中,您可以为所关注的属性添加事件侦听器。在本例中,我们为 distance_changedposition_changed 事件添加一个侦听器,它将调用一个可显示值的函数。

 

At the end of the init function add:

init 函数的最后,添加:

Also add a new function displayInfo()

此外再添加一个新函数 displayInfo()

Finally add a <div> with the id 'info' after the map <div> so you have a place to display the info.

最后,在地图 <div> 之后使用 id“info”添加一个 <div>,这样就有了一个显示信息的位置。

Now as you drag around the center marker (step6), you'll see the position value change and as you resize the circle, you'll see the distance change.

现在当您拖动中心标记时(步骤 6),您会看到位置值的变化,当您调整圆的大小时,您会看到距离的变化。

What Can Be Done With It? 

用它可以做什么?

If you wanted to, you could hook it up to your store locator from the Creating a Store Locator with PHP, MySQL & Google Maps article or you can connect it to another service like Twitter who has a nice api that will let you search for tweets within a given distance of a LatLng location (read more). You can see the finished result of connecting to the Twitter API.

如果愿意,您可以将其与使用 PHP、MySQL 和 Google Maps 创建商店定位器一文中的商店定位器关联起来,或者将其连接到另一个服务,如 Twitter,后者有一个非常优秀的 API,可让您搜索某个 LatLng 位置的给定范围内的 tweet(了解详情)。您可以查看连接到 Twitter API 时的最终结果。

 

If you have any issues or questions about this tutorial, please post them in the Maps v3 API forum.

如果您有关于本辅导手册的任何问题,请在Maps V3 API 论坛中发帖。