上周,我和法国华纳音乐公司为法国艺术家Ninho推出了一个移动网络应用程序,以支持他的新唱片《德斯汀》。 该应用程序为巴黎的球迷提供了逐步指导,以将其“ NI”徽标重新创建为GPS图纸。 参加这次旅行的人将获得音乐会门票和金唱片(象征着Ninho自己对Destin的金奖。)
实际上,由于我们之间的长期合作关系以及我过去在Greta Van Fleet,Guns N Roses和Huron爵士的技术领域从事音乐工作,Mapbox的好心人向我们介绍了Warner Music France。 请务必查看LoBénichou对此广告系列用户体验的出色概述。
当我最初收到此摘要时,我的第一个念头是:“哦,不。 我们该如何使用街道创建“ N”形?”(这是我担心的事情)事实证明,巴黎的街道系统比我习惯的美国电网宽容得多。 (即使我住在新奥尔良,也就是您在美国最接近法国的地方。)我的下一个担心是确保客户抑制他们的用户体验期望并同意简化的解决方案。 鉴于这将是在各种移动设备上的真实体验,并且蜂窝覆盖范围未知,所以我想确保核心问题已解决并易于测试。 我还想尽量减少体验的总占用空间,以便快速加载。 抱歉,该行没有自定义字体。 幸运的是,我没有得到任何回击,实际上发现华纳是理想的客户:理解,创新和响应。
该Web应用程序是在我当前选择的框架Nuxt.js上使用Vue.js开发的。 我只是喜欢Nuxt处理应用程序从路由到状态管理的许多核心功能的方式。 我还引入了出色的cookie通用插件,以跟踪用户的绘图进度,以防用户信号中断或应用由于某种原因而刷新。 为了跟踪用户的位置,我再次依靠浏览器自己的Geolocation API(以及用户的许可。)我们没有存储他们的位置,而是将其作为传递变量与Turf.js函数一起使用来计算接近停止并解锁进度。 所有这些都使用Mapbox GL及其出色的样式规范进行了可视化。
该应用程序的主要行驶数据是一个JSON对象数组,其中包含停靠点坐标,在停靠点之间绘制视觉上令人愉悦的线所需的坐标,停靠点的当前状态以及用户在体验过程中看到的自定义文本方向。 这是其中之一的示例:
{
坐标:[
2.342188,
48.86357
],
行:[
[
2.340831,
48.860917
],[
2.342188,
48.86357
]
],
状态:“已锁定”,
方向:“ Ton destin est entre tes mains,博讷机会!”
}
随着用户逐步了解我们的经验,这些停靠点的状态从锁定变为下一个,然后变为解锁。 从这里开始,只需使用Mapbox GL及其样式功能即可创建映射的视觉效果。
例如,停靠点由带有稍微透明的蓝色边框的蓝色圆圈表示。 最重要的是,一个数字表示停止位置,根据停止状态对其进行着色。 首先,我们向地图添加新的GeoJSON源,将停止坐标映射为GeoJSON功能的集合。 我们传递给这些功能的属性(索引和状态)将用于动态设置样式。
map.addSource('stops',{
类型:“ geojson”,
数据:{
类型:“ FeatureCollection”,
功能:this.stops.map((stop,i)=> {
返回{
类型:“功能”,
几何:{
类型:“点”,
坐标:stop.coordinates
},
属性:{
指数:i + 1
状态:stop.status
}
}
})
}
})
然后,我们可以为每个停靠点添加一个圆圈层。
map.addLayer({
id:“停止圈”,
类型:“圆圈”,
来源:“停止”,
油漆:{
“圆半径”:15
“圆形”:“#0292CE”,
“ circle-stroke-color”:“ rgba(2,146,206,0.5)”,
“圆行程宽度”:5
}
})
然后,我们可以将数字添加到这些圆圈的顶部。 首先,请注意先前声明的“ index”属性如何用作文本字段本身。 然后,我们使用match决策表达式根据status属性调整文本颜色。 我们只是在探索Mapbox GL JS表达式的功能。
map.addLayer({
id:“停止号”,
类型:“符号”,
来源:“停止”,
布局:{
“ text-field”:“ {index}”,
“文本字体”:[“打开Sans ExtraBold”,“ Arial Unicode MS Bold”],
“文本大小”:14
},
油漆:{
“文字颜色”:[
“比赛”,
[“获取”,“状态”],
'锁定','#000000',
'next','#FFFFFF',
'已解锁','#FABF63',
'灰色'
]
}
})
最后,随着用户到达每个停靠点,我们会更新GeoJSON功能集中的停靠状态以反映停靠点的变化。 为了使地图显示此更改,我们只需要重置站点地图源的数据即可。
this.map.getSource('stops')。setData(stopsGeoJSON)