案例背景:
最近在开发城市地铁图项目,具体功能有规划路线、定位最近地铁站、以及显示整个城市的地铁网状图等功能。根据需求,在实现的时候在地铁线路图上需要添加定位按钮及线路弹框来展示位置信息以及地铁站详情信息。
遇到的问题:
在地铁图调研初期,原计划实现渲染方案是采用svg来绘制,但是调研后发现小程序原生API不支持svg。同时,我们在开源中找到一个svg的框架库来实现绘制,但是开发初期发现遇到很多无法实现的需求和性能问题。在对开源库的代码跟踪后,发现绘制方案也是canvas的方式,于是我们决定使用原生canvas的方案来支持地铁图。但是呢,又遇到一些问题,那么我们来看看几个具体的点:
1) view在canvas上无法正常显示。
在canvas上使用view来添加图片和弹框时,发现图片以及弹框在canvas的下面,不能正常显示图片。
查看文档发现canvas、map、video等原生组件使用的是native实现的,默认显示在小程序的最上层,所以就把view换成cover-view或者cover-image。
使用view效果:
<!-- 线路 --> < view class = "sublines sublines-icon" > < image class = 'sublinesIcon' src = "/static/img/ic_sublines.png" bindtap = 'clickSublines' wx-if = "{{lineIconShow}}" ></ image > </ view > |
替换成cover-view效果:
<!-- 线路 --> < cover-view class = "sublines sublines-icon" > < cover-image class = 'sublinesIcon' src = "/static/img/ic_sublines.png" bindtap = 'clickSublines' wx-if = "{{lineIconShow}}" ></ cover-image > </ cover-view > |
但是使用cover-view又遇到了层级和样式的问题。
2)canvas上使用cover-image添加图片,图片设置position:absolute;页面上的图片显示在canvas画线的下方,导致定位按钮不能正常使用。后来把position该换成fixed解决来层级的问题。效果如下所示:
.locationIcon { width: 3rem; height: 3rem; position: fixed; bottom: 3rem; left: 0.7rem; } |
3)在页面上实现一个弹框时,根据UI图需要实现一个底边线和底边小三角形。通过border给块级元素设置底边线或者css实现三角箭头,单边border设置无效。最终采用了height为1px的cover-view或者图片来代替。
设置单边border效果:
<!-- 起终点设置弹框 --> < cover-view class = "sdMark" style = 'top:{{tapClient.y}}px;left:{{tapClient.x}}px;' wx-if = "{{sdMarkShow}}" > < cover-view class = 'sdMarkContent' > < cover-view class = 'sdMarkItem' bindtap = 'clickStart' >设为起点</ cover-view > < cover-view class = 'sdMarkItem' bindtap = 'clickEnd' >设为终点</ cover-view > < cover-view class = 'sdMarkItem' bindtap = 'clickStationDetail' >站点详情</ cover-view > </ cover-view > </ cover-view > |
修改后的代码:
<!-- 起终点设置弹框 --> < cover-view class = "sdMark" style = 'top:{{tapClient.y}}px;left:{{tapClient.x}}px;' wx-if = "{{sdMarkShow}}" > < cover-view class = 'sdMarkContent' > < cover-view class = 'sdMarkItem' bindtap = 'clickStart' >设为起点</ cover-view > < cover-view class = 'line' ></ cover-view > < cover-view class = 'sdMarkItem' bindtap = 'clickEnd' >设为终点</ cover-view > < cover-view class = 'line' ></ cover-view > < cover-view class = 'sdMarkItem' bindtap = 'clickStationDetail' >站点详情</ cover-view > </ cover-view > < cover-view class = "icon" > < cover-image class = 'icArrow' src = '/static/img/ic_arrow.png' ></ cover-image > </ cover-view > </ cover-view > |
最终的效果:
踩坑总结:canvas层级较高,使用cover-view或者cover-image在canvas做操作。单边border相关的操作使用图片或者块级元素来代替。
查看相关API文档:
cover-view相关文档:https://developers.weixin.qq.com/miniprogram/dev/component/cover-view.html
欢迎体验和吐槽:"腾讯位置服务-地铁图"插件:https://developers.weixin.qq.com/community/servicemarket/sq_ocVuQ4joORnwn_bzpxTd8Mq8wZ3g/service/detail/0008cc3058c5c8042dc89d7db54415
<
cover-view
class
=
"sdMark"
style
=
'top:{{tapClient.y}}px;left:{{tapClient.x}}px;'
wx-if
=
"{{sdMarkShow}}"
> 这样的方式控制显示与隐藏做不到吧?官方说不支持wx:if的
线路规划是你们写的吗?老闪退!
video早就实现同层了
view的使用确实很受限制,赞解决方案
位置服务官方太到位,顶~