Languages: English • 简体中文 • 繁體中文
SensorThings API - 数据驱动样式设计
在第一部分中, 我们:
- 使用Leaflet制作了一个简单地图
- 使用多伦多自行车共享站点的位置信息
Locations
填充了这张地图
首先,调整地图
在我们深入了解数据驱动样式设计的细节之前,让我们对地图进行一些微调。
- 把标记改成圆圈
- 为了使用户了解数据来源,增加一行代码来注明地图中所提供的开放数据属于自于多伦多市
pointToLayer
现在引入了一个函数,它回传了圆形标记(circleMarker)来替代预设的标记图案。
var geoJsonLayerGroup = L.geoJSON(geoJsonFeatures, {
// Change the default marker to a circle
pointToLayer: function(geoJsonPoint, latlng) {
return L.circleMarker(latlng);
}
});
map.attributionControl.addAttribution("Contains information licensed under the Open Government Licence – Toronto.");
自行车的去向?
现在,我们已经在地图上放置了很多点,它们看起来还不错,但不够特别。因为虽然我们知道了自行车共享站点的位置,但如果能进一步知道每个共享站点有多少自行车将会更好。现在我们就来做这件事。
在SensorThings中,例如“可用的自行车(available bikes)”这样的信息,可称为观测属性ObservedProperty
。
此次教程中的使用的SensorThings服务器包含了两个观测属性ObservedProperties
- 可用的自行车(Available bikes)
- 可用的站点(Available docks)
请参考以下代码
虽然对我们而言,可用的自行车和可用的站点都是重要的信息。但依需要,这部分教程将只关注可用的自行车数量。
现在我们要做的,是找到在特定的Location
中可用自行车的数量。在SensorThings中,这类的信息被存储在观测值Observation
中。我们必须通过SensorThings中多个其他的实体(entities)来获取观测值Observation
。具体来说,我们需要先获取在这个位置Location
的Things
,以及Things
对应的数据流Datastreams
(因为只有Datastream
包含可用自行车的信息),然后我们再获取每个数据流Datastream
中的观测值Observations
(我们只要最新的一份数据)。这些虽然看起来繁琐,但这些实体可支持您进行复杂特定的查询。
以上这个查询看起来似乎有些难度,但实际上并不复杂。
-
/Locations
: 对Locations
的端点进行请求,与之前的请求相同。 -
$expand=Things/Datastreams($filter=ObservedProperty/name eq 'available_bikes')
: 通过扩展这个Location
来获取Things
以及它对应的多个Datastreams
,然后在结果中过滤其他Datastreams
,仅保留ObservedProperty
中属性名为'available_bikes'
的结果。 -
Things/Datastreams/Observations($orderby=phenomenonTime desc;$top=1)
: 这是扩展$expand
参数的第二部分。这部分对于剩下未被过滤的Datastreams
扩展获得观测值Observations
,并且获取根据phenomenonTime
排序后的最新一份数据。因此只会传回最新的观测值Observation
。
这些响应包括:
Location
的经度和纬度座标(之前取回过)Location
最新一些的可用自行车数量(本次新增)
整合到地图
现在我们知道如何从每个站点取回可用自行车的数量,接下来就准备建立我们的地图了。
Features
里增加了一行properties: location
,以便LeaFlet来访问SensorThings响应中的Things
,Datastreams
, 和Observations
。
var geoJsonFeatures = success.data.value.map(function(location) {
return {
type: 'Feature',
geometry: location.location,
properties: location
};
});
#38f
)和"不足的"的自行车(显示为红色)。我们姑且设定了一个值(5),超过五辆自行车即为“足够的”,小于则为“不足的”。
pointToLayer: function(geoJsonPoint, latlng) {
var enoughBikeColor = "#38f";
var fewBikesColor = "red";
var availableBikes = geoJsonPoint.properties.Things[0].Datastreams[0].Observations[0].result;
return L.circleMarker(latlng, {
color: availableBikes > 5 ? enoughBikeColor : fewBikesColor
});
}
下一步?
您是那种会告诉老师他们错了的学生吗?如果您是,此刻您肯定会举手,事实上,也许此刻您会疯狂地挥舞手臂引起老师注意。
那是因为您可能发现了,/Locations
的响应中"@iot.count": 199
,但其实只有100个 Locations
被传回来。您也许还会注意到这里暗藏了一个@iot.nextLink
属性。
我们还没有显示所有的自行车分享站点。
所以,接下来请继续第三部分。