最近产品提出一个需求,在我们使用的腾讯地图上为线路polyline添加线路方向。例如下图所示:

查找腾讯地图JS API提供的API,没有找到对应的支持,询问负责腾讯地图的人也得到了同样的答案,即地图JS API不支持线路画方向。于是否就利用地图的Marker类配合旋转来实现这个功能。

实现原理

因为是利用Marker来实现Polyline带方向箭头功能,所以要根据线路不同局部的具体走向来旋转Marker的Icon,从而实现该功能。

另外,我们需要知道:

Marker的旋转方向是跟时针方向保持一致的,角度为正表示顺时针旋转,负表示逆时针旋转。

腾讯地图的JS API虽然没有提供画箭头的支持,但是可喜的是,腾讯地图提供了一个类qq.maps.geometry.spherical,它提供了一些方法用于计算面积、角度和距离,具体可以参考这里

其中,对于我们实现方向箭头有用的是以下两个api:

  • computeHeading(from:LatLng, to:LatLng): 返回从一个坐标到另一个坐标的航向。航向是指从一个坐标指向另一个坐标的向量与正北方向的夹角,范围为[-180,180)。

  • computeDistanceBetween(from:LatLng, to:LatLng, radius?:Number): 返回两坐标点间的距离。

结合上面所描述的,具体的实现原理图如下图展示:

具体实现步骤:

  • 利用computeHeading方法计算航向,然后由其计算Marker旋转的角度。

注意:

由航向计算Marker旋转角度,需要根据具体的Marker的Icon图形来具体分析,不能一概而论。比如本人项目使用的Marker icon图为水平方向的箭头,如下图:

那么,根据该icon图可以计算对应的marker旋转角度,具体计算规则如下图所示。其它方向的Icon可以推算出对应的计算规则。

  • 利用computeDistanceBetween方法计算两坐标点中间位置的经纬度

  • 创建Marker实例,并设置其Icon和用marker实例的setRotation方法来旋转角度

注意:

有官方声明marker实例的setRotation方法的旋转角度范围为0~360,所以根据计算的旋转角度必须为这一范围,否则可能会出现图形走样的情况。

实现代码

正如上面描述的实现原理,下面即是实现为Polyline实例添加方向箭头Marker的实现代码:

function setIcon(marker){
var size = new qq.maps.Size(9, 8); //marker icon图片大小为18px * 16px, 等比例缩放
var anchor = new qq.maps.Point(5, 4); //经纬度点在图标中的位置点
var image = require('imgs/arrow.png');
var icon = new qq.maps.MarkerImage(image, size, undefined, anchor, size);
marker.setIcon(icon);
}
//画marker
function addMarkers(lat, lng, opts){
var position = new qq.maps.LatLng(lat, lng);
var defaultOps = {
map: mapInstance, //mapInstance为对应的qq map实例
position,
zIndex: 8,
visible: true,
draggable: false
}
var options = Object.assign({}, defaultOpts, opts || {});
var marker = new qq.maps.Marker(options);
setIcon(marker);
return marker
}
//计算线路方向箭头旋转的方向,heading为两个经纬度点之间的航向(两点之间与正北方向的夹角),其范围为[-180, 180)
function computeRotaion(heading){
let rotation;
if(heading < 0) {
rotation = 270 + heading;
}else {
rotation = heading - 90;
}
return rotation
}
//为polyline添加方向marker
function addArrowMarkers(polyline){
var defaultOps = {
cursor: 'normal',
zIndex: polyline.getZIndex() + 1,
clickable: false,
draggable: false
}; var linePoint = polyline.getPath();//线的经纬度坐标
var arrowCount= linePoint.length;
for(let i = 1; i < arrowCount; i+=2){//不是每两个点之间都画箭头,而是每隔一个间隔画一个箭头
let pixelStart = linePoint.getAt(i-1);
let pixelEnd = linePoint.getAt(i);
let heading, rotation, arrowLatLng, marker;
let spherical = qq.maps.geometry.spherical;
let distance = spherical.computeDistanceBetween(pixelStart, pixelEnd); //计算两经纬度坐标件的距离 if(distance <= 15) {//距离太近小于15m的两经纬度坐标点间不画方向
continue;
} heading = spherical.computeHeading(pixelStart, pixelEnd);//两经纬度坐标点之间的航向
//计算两经纬度坐标点中间位置的经纬度
arrowLatLng = spherical.computeOffsetOrigin(pixelEnd, distance/2, heading); marker = addMarker(arrowLatLng.lat, arrowLatLng.lng, defaultOps);
rotation = computeRotaion(heading); //由两坐标点之间的航向计算marker要旋转的角度
marker.setRotation(rotation);
}
}

至此,带方向的polyline线路就带有方向箭头了,可以很清晰的看出线路的走向了。

腾讯地图JS API实现带方向箭头的线路Polyline的更多相关文章

  1. 高德地图 JS API - 根据地名实现标记定位

    德地图 JS API 使用前的准备工作请参考官方网站说明: https://lbs.amap.com/api/javascript-api/guide/abc/prepare 根据地名实现地图标记定位 ...

  2. 高德地图 js api 使用

    使用高德地图js api 制作网页上的地图应用. 1.先申请一个 开发者用的 key . 2. 在页面中引入高德提供的地图js  <script src="http://webapi. ...

  3. 百度地图JS API不能使用position:fixed

    用于放置百度地图的dom元素及其任何一级父元素设置position:fixed属性时,js会报如下错误: Uncaught TypeError: Cannot read property 'offse ...

  4. 百度地图 JS API开发Demo01

    百度地图DEMO     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http: ...

  5. 关于百度地图js api的getCurrentPosition定位不准确的解决方法

    很久之前帮大叔解决了一个gps坐标转换为百度地图坐标的问题.今天大叔又给我讲百度地图定位不准.我查了一下api,用了官方给出的这样一组函数. //创建查询对象 var geolocation = ne ...

  6. 高德地图JS API获取经纬度,根据经纬度获取城市

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...

  7. 高德地图JS API 开发小结

    项目中有一块功能要用到高德地图,所以,想把编码小结一下. 首先是地图的初始化 var map = new AMap.Map("mapDiv", {                  ...

  8. C# 调用腾讯地图WebService API获取距离(一对多)

    官方文档地址:https://lbs.qq.com/webservice_v1/guide-distance.html 代码: /// <summary> /// 获取距离最近的点的经纬度 ...

  9. 高德地图 JS API (jsp + miniui(子页面数据返回父页面并设值) + 单个点标记 + 点标记经纬度 + 回显 + 限制地图显示范围+搜索)

    -*-  父页面js function mapFocus(){ //console.log("-*-"); var longitude = mini.get("jd&qu ...

随机推荐

  1. 记一次亲身踩过的hibernate的bug

    记一次亲身踩过的hibernate的bug 在写实体类时,经常会对域增加校验,例如@NotNull表示哪个字段不能为空,昨天晚上调试代码,就遇到了问题, @Entity public class Ap ...

  2. GRPC在NET上的实践(记录篇)

    GRPC是什么? GRPC是一个开源RPC框架,于2015年3月开源,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于Protobuf 3.0(Protocol Buffer ...

  3. kotlin语言使用初体验(一)

    居说谷歌新认的干儿子kotlin极为受宠,隐隐有替代Java在 android平台老大位置的趋势.kotlin有谷歌撑腰,加上自己的底子也厚,再之与Java无缝兼容,将来在流行的编程语言中占有一席之地 ...

  4. OpenStack命令 创建网络和路由管理

    1.登陆用户 :tdy(前提条件创建了tdy用户) 编写登陆用户tdy用户 脚本文件  user-operc.sh user-operc.sh : 登陆用户tdy: $ source user-ope ...

  5. redis集群搭建实践

    参考 第一个节点 第一个节点为本地的机器 IP:192.168.23.148 检查机器配置 $ uname -a Linux wangya-Lenovo-G480 4.8.0-52-generic # ...

  6. Linux下如果忘记了Mysql的root密码该怎么办?

    下面十分简单的办法用来重置密码: 1.编辑MySQL配置文件my.cnf vi /etc/my.cnf #编辑文件,找到[mysqld],在下面添加一行skip-grant-tables [mysql ...

  7. 【Selenium】idea的selenium环境配置

    1.maven配置 下载地址:http://maven.apache.org/download.cgi# 下载内容:apache-maven-3.5.0-bin.zip 环境变量:M2_HOME:E: ...

  8. 移动平台Unity3D 应用性能优化

    WeTest 导读 做了大概半年多VR应用了,VR由于双眼double渲染的原因,对性能的优化要求比较高,在项目的进展过程中,总结了一些关于移动平台上Unity3D的性能优化经验,供分享. 一.移动平 ...

  9. php实现ppt转图片,php调用com组件问题

    PHP 调用com组件将ppt转为图片. 需要在php.ini中开启 extension=php_com_dotnet.dllcom.allow_dcom = true   测试代码如下:   < ...

  10. windows利用iis配置反向代理实现ECS内网互通oss

    IIS实现反向代理 新建两个站点,端口分别使用 80 和 81,在DNS中新建A记录,指向该计算机(10.4.34.41) 配置过程如下: 1.在Windows Server 2012 R2上 安装A ...