123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- /**
- * @fileoverview 百度地图的轨迹跟随类,对外开放。
- * 用户可以在地图上自定义轨迹运动
- * 可以自定义路过某个点的图片,文字介绍等。
- * 主入口类是<a href="examples/index.html">LuShu</a>,
- * 基于Baidu Map API GL 1.0
- *
- * @author Baidu Map Api Group
- * @version 1.0
- */
- /**
- * @namespace BMapGL的所有library类均放在BMapGLLib命名空间下
- */
- var BMapGLLib = (window.BMapGLLib = BMapGLLib || {});
- (function () {
- var T;
- var baidu = (T = baidu || { version: "gl 1.0" });
- baidu.guid = "$BAIDU$";
- (function () {
- window[baidu.guid] = window[baidu.guid] || {};
- baidu.dom = baidu.dom || {};
- baidu.dom.g = function (id) {
- if ("string" == typeof id || id instanceof String) {
- return document.getElementById(id);
- } else if (id && id.nodeName && (id.nodeType == 1 || id.nodeType == 9)) {
- return id;
- }
- return null;
- };
- baidu.g = baidu.G = baidu.dom.g;
- baidu.lang = baidu.lang || {};
- baidu.lang.isString = function (source) {
- return "[object String]" == Object.prototype.toString.call(source);
- };
- baidu.isString = baidu.lang.isString;
- baidu.dom._g = function (id) {
- if (baidu.lang.isString(id)) {
- return document.getElementById(id);
- }
- return id;
- };
- baidu._g = baidu.dom._g;
- baidu.dom.getDocument = function (element) {
- element = baidu.dom.g(element);
- return element.nodeType == 9
- ? element
- : element.ownerDocument || element.document;
- };
- baidu.browser = baidu.browser || {};
- baidu.browser.ie = baidu.ie = /msie (\d+\.\d+)/i.test(navigator.userAgent)
- ? document.documentMode || +RegExp["\x241"]
- : undefined;
- baidu.dom.getComputedStyle = function (element, key) {
- element = baidu.dom._g(element);
- var doc = baidu.dom.getDocument(element),
- styles;
- if (doc.defaultView && doc.defaultView.getComputedStyle) {
- styles = doc.defaultView.getComputedStyle(element, null);
- if (styles) {
- return styles[key] || styles.getPropertyValue(key);
- }
- }
- return "";
- };
- baidu.dom._styleFixer = baidu.dom._styleFixer || {};
- baidu.dom._styleFilter = baidu.dom._styleFilter || [];
- baidu.dom._styleFilter.filter = function (key, value, method) {
- var filters = baidu.dom._styleFilter;
- var filter;
- for (var i = 0; (filter = filters[i]); i++) {
- if ((filter = filter[method])) {
- value = filter(key, value);
- }
- }
- return value;
- };
- baidu.string = baidu.string || {};
- baidu.string.toCamelCase = function (source) {
- if (source.indexOf("-") < 0 && source.indexOf("_") < 0) {
- return source;
- }
- return source.replace(/[-_][^-_]/g, function (match) {
- return match.charAt(1).toUpperCase();
- });
- };
- baidu.dom.getStyle = function (element, key) {
- var dom = baidu.dom;
- element = dom.g(element);
- key = baidu.string.toCamelCase(key);
- var value =
- element.style[key] ||
- (element.currentStyle ? element.currentStyle[key] : "") ||
- dom.getComputedStyle(element, key);
- if (!value) {
- var fixer = dom._styleFixer[key];
- if (fixer) {
- value = fixer.get
- ? fixer.get(element)
- : baidu.dom.getStyle(element, fixer);
- }
- }
- if ((fixer = dom._styleFilter)) {
- value = fixer.filter(key, value, "get");
- }
- return value;
- };
- baidu.getStyle = baidu.dom.getStyle;
- baidu.dom._NAME_ATTRS = (function () {
- var result = {
- cellpadding: "cellPadding",
- cellspacing: "cellSpacing",
- colspan: "colSpan",
- rowspan: "rowSpan",
- valign: "vAlign",
- usemap: "useMap",
- frameborder: "frameBorder",
- };
- if (baidu.browser.ie < 8) {
- result["for"] = "htmlFor";
- result["class"] = "className";
- } else {
- result["htmlFor"] = "for";
- result["className"] = "class";
- }
- return result;
- })();
- baidu.dom.setAttr = function (element, key, value) {
- element = baidu.dom.g(element);
- if ("style" == key) {
- element.style.cssText = value;
- } else {
- key = baidu.dom._NAME_ATTRS[key] || key;
- element.setAttribute(key, value);
- }
- return element;
- };
- baidu.setAttr = baidu.dom.setAttr;
- baidu.dom.setAttrs = function (element, attributes) {
- element = baidu.dom.g(element);
- for (var key in attributes) {
- baidu.dom.setAttr(element, key, attributes[key]);
- }
- return element;
- };
- baidu.setAttrs = baidu.dom.setAttrs;
- baidu.dom.create = function (tagName, opt_attributes) {
- var el = document.createElement(tagName),
- attributes = opt_attributes || {};
- return baidu.dom.setAttrs(el, attributes);
- };
- baidu.object = baidu.object || {};
- baidu.extend = baidu.object.extend = function (target, source) {
- for (var p in source) {
- if (source.hasOwnProperty(p)) {
- target[p] = source[p];
- }
- }
- return target;
- };
- })();
- WORLD_SIZE_MC_HALF = 20037726.372307256;
- WORLD_SIZE_MC = WORLD_SIZE_MC_HALF * 2;
- /**
- * @exports LuShu as BMapGLLib.LuShu
- */
- var LuShu =
- /**
- * LuShu类的构造函数
- * @class LuShu <b>入口</b>。
- * 实例化该类后,可调用,start,end,pause等方法控制覆盖物的运动。
-
- * @constructor
- * @param {Map} map Baidu map的实例对象.
- * @param {Array} path 构成路线的point的数组.
- * @param {Json Object} opts 可选的输入参数,非必填项。可输入选项包括:<br />
- * {<br />"<b>landmarkPois</b>" : {Array} 要在覆盖物移动过程中,显示的特殊点。格式如下:landmarkPois:[<br />
- * {lng:116.314782,lat:39.913508,html:'加油站',pauseTime:2},<br />
- * {lng:116.315391,lat:39.964429,html:'高速公路收费站,pauseTime:3}]<br />
- * <br />"<b>icon</b>" : {Icon} 覆盖物的icon,
- * <br />"<b>speed</b>" : {Number} 覆盖物移动速度,单位米/秒 <br />
- * <br />"<b>defaultContent</b>" : {String} 覆盖物中的内容 <br />
- * }<br />.
- * @example <b>参考示例:</b><br />
- * var lushu = new BMapGLLib.LuShu(map,arrPois,{defaultContent:"从北京到天津",landmarkPois:[]});
- */
- (BMapGLLib.LuShu = function (map, path, opts) {
- if (!path || path.length < 1) {
- return;
- }
- this._map = map;
- //存储一条路线
- if (opts["geodesic"]) {
- this.path = getGeodesicPath(path);
- } else {
- this.path = path;
- }
- //移动到当前点的索引
- this.i = 0;
- //控制暂停后开始移动的队列的数组
- this._setTimeoutQuene = [];
- //进行坐标转换的类
- // this._projection = this._map.getMapType().getProjection();
- this._opts = {
- icon: null,
- //默认速度 米/秒
- speed: 400,
- defaultContent: "",
- };
- if (!opts["landmarkPois"]) {
- opts["landmarkPois"] = [];
- }
- this._setOptions(opts);
- this._rotation = 0; //小车转动的角度
- //如果不是默认实例,则使用默认的icon
- if (!(this._opts.icon instanceof BMapGL.Icon)) {
- this._opts.icon = defaultIcon;
- }
- });
- /**
- * 根据用户输入的opts,修改默认参数_opts
- * @param {Json Object} opts 用户输入的修改参数.
- * @return 无返回值.
- */
- LuShu.prototype._setOptions = function (opts) {
- if (!opts) {
- return;
- }
- for (var p in opts) {
- if (opts.hasOwnProperty(p)) {
- this._opts[p] = opts[p];
- }
- }
- };
- /**
- * @description 开始运动
- * @param none
- * @return 无返回值.
- *
- * @example <b>参考示例:</b><br />
- * lushu.start();
- */
- LuShu.prototype.start = function () {
- var me = this,
- len = me.path.length;
- //不是第一次点击开始,并且小车还没到达终点
- if (me.i && me.i < len - 1) {
- //没按pause再按start不做处理
- if (!me._fromPause) {
- return;
- } else if (!me._fromStop) {
- //按了pause按钮,并且再按start,直接移动到下一点
- //并且此过程中,没有按stop按钮
- //防止先stop,再pause,然后连续不停的start的异常
- me._moveNext(++me.i);
- }
- } else {
- //第一次点击开始,或者点了stop之后点开始
- me._addMarker();
- //等待marker动画完毕再加载infowindow
- me._timeoutFlag = setTimeout(function () {
- me._addInfoWin();
- if (me._opts.defaultContent == "") {
- me.hideInfoWindow();
- }
- me._moveNext(me.i);
- }, 400);
- }
- //重置状态
- this._fromPause = false;
- this._fromStop = false;
- };
- /**
- * 结束运动
- * @return 无返回值.
- *
- * @example <b>参考示例:</b><br />
- * lushu.stop();
- */
- LuShu.prototype.stop = function () {
- this.i = 0;
- this._fromStop = true;
- clearInterval(this._intervalFlag);
- this._clearTimeout();
- //重置landmark里边的poi为未显示状态
- for (var i = 0, t = this._opts.landmarkPois, len = t.length; i < len; i++) {
- t[i].bShow = false;
- }
- };
- /**
- * 暂停运动
- * @return 无返回值.
- */
- LuShu.prototype.pause = function () {
- clearInterval(this._intervalFlag);
- //标识是否是按过pause按钮
- this._fromPause = true;
- this._clearTimeout();
- };
- LuShu.prototype.clear = function () {
- this._clearMark();
- };
- /**
- * 隐藏上方overlay
- * @return 无返回值.
- *
- * @example <b>参考示例:</b><br />
- * lushu.hideInfoWindow();
- */
- LuShu.prototype.hideInfoWindow = function () {
- this._overlay._div.style.visibility = "hidden";
- };
- /**
- * 显示上方overlay
- * @return 无返回值.
- *
- * @example <b>参考示例:</b><br />
- * lushu.showInfoWindow();
- */
- LuShu.prototype.showInfoWindow = function () {
- this._overlay._div.style.visibility = "visible";
- };
- //Lushu私有方法
- baidu.object.extend(LuShu.prototype, {
- /**
- * 添加marker到地图上
- * @param {Function} 回调函数.
- * @return 无返回值.
- */
- _addMarker: function (callback) {
- if (this._marker) {
- this.stop();
- // 变更
- this._map.removeOverlay(this._marker);
- this._map.removeOverlay(this._markerL);
- this._map.removeOverlay(this._markerR);
- clearTimeout(this._timeoutFlag);
- }
- //移除之前的overlay
- this._overlay && this._map.removeOverlay(this._overlay);
- var marker = new BMapGL.Marker(this.path[0]);
- this._opts.icon && marker.setIcon(this._opts.icon);
- this._map.addOverlay(marker);
- marker.setAnimation(BMAP_ANIMATION_DROP);
- this._marker = marker;
- // 变更
- var markerL = new BMapGL.Marker(this.path[0], { left: true });
- this._opts.icon && markerL.setIcon(this._opts.icon);
- this._map.addOverlay(markerL);
- markerL.setAnimation(BMAP_ANIMATION_DROP);
- this._markerL = markerL;
- var markerR = new BMapGL.Marker(this.path[0], { right: true });
- this._opts.icon && markerR.setIcon(this._opts.icon);
- this._map.addOverlay(markerR);
- markerR.setAnimation(BMAP_ANIMATION_DROP);
- this._markerR = markerR;
- },
- /**
- * 销毁--(用户自定义)
- * @param f
- * @private
- */
- _clearMark: function (f) {
- this.stop();
- this._map.removeOverlay(this._marker);
- this._map.removeOverlay(this._markerL);
- this._map.removeOverlay(this._markerR);
- clearTimeout(this._timeoutFlag);
- this._overlay && this._map.removeOverlay(this._overlay);
- },
- /**
- * 添加上方overlay
- * @return 无返回值.
- */
- _addInfoWin: function () {
- var me = this;
- var overlay = new CustomOverlay(
- me._marker.getPosition(),
- me._opts.defaultContent
- );
- //将当前类的引用传给overlay。
- overlay.setRelatedClass(this);
- this._overlay = overlay;
- this._map.addOverlay(overlay);
- },
- /**
- * 获取墨卡托坐标
- * @param {Point} poi 经纬度坐标.
- * @return 无返回值.
- */
- _getMercator: function (poi) {
- return this._map.getMapType().getProjection().lngLatToPoint(poi);
- },
- /**
- * 计算两点间的距离
- * @param {Point} poi 经纬度坐标A点.
- * @param {Point} poi 经纬度坐标B点.
- * @return 无返回值.
- */
- _getDistance: function (pxA, pxB) {
- return Math.sqrt(Math.pow(pxA.x - pxB.x, 2) + Math.pow(pxA.y - pxB.y, 2));
- },
- //目标点的 当前的步长,position,总的步长,动画效果,回调
- /**
- * 移动小车
- * @param {Number} poi 当前的步长.
- * @param {Point} initPos 经纬度坐标初始点.
- * @param {Point} targetPos 经纬度坐标目标点.
- * @param {Function} effect 缓动效果.
- * @return 无返回值.
- */
- _move: function (initPos, targetPos, effect) {
- var me = this,
- //当前的帧数
- currentCount = 0,
- //步长,米/秒
- timer = 10,
- step = this._opts.speed / (1000 / timer),
- //初始坐标
- init_pos = BMapGL.Projection.convertLL2MC(initPos),
- //获取结束点的(x,y)坐标
- target_pos = BMapGL.Projection.convertLL2MC(targetPos);
- init_pos = new BMapGL.Pixel(init_pos.lng, init_pos.lat);
- target_pos = new BMapGL.Pixel(target_pos.lng, target_pos.lat);
- // 变更
- var mcDis = me._getDistance(init_pos, target_pos);
- var direction = null;
- if (mcDis > 30037726) {
- if (target_pos.x < init_pos.x) {
- target_pos.x += WORLD_SIZE_MC;
- direction = "right";
- } else {
- target_pos.x -= WORLD_SIZE_MC;
- direction = "left";
- }
- }
- //总的步长
- var count = Math.round(me._getDistance(init_pos, target_pos) / step);
- //如果小于1直接移动到下一点
- if (count < 1) {
- me._moveNext(++me.i);
- return;
- }
- //两点之间匀速移动
- me._intervalFlag = setInterval(function () {
- //两点之间当前帧数大于总帧数的时候,则说明已经完成移动
- if (currentCount >= count) {
- clearInterval(me._intervalFlag);
- //移动的点已经超过总的长度
- if (me.i > me.path.length) {
- return;
- }
- //运行下一个点
- me._moveNext(++me.i);
- } else {
- currentCount++;
- var x = effect(init_pos.x, target_pos.x, currentCount, count),
- y = effect(init_pos.y, target_pos.y, currentCount, count),
- pos = BMapGL.Projection.convertMC2LL(new BMapGL.Point(x, y));
- if (pos.lng > 180) {
- pos.lng = pos.lng - 360;
- }
- if (pos.lng < -180) {
- pos.lng = pos.lng + 360;
- }
- //设置marker
- if (currentCount == 1) {
- var proPos = null;
- if (me.i - 1 >= 0) {
- proPos = me.path[me.i - 1];
- }
- if (me._opts.enableRotation == true) {
- me.setRotation(proPos, initPos, targetPos, direction);
- }
- if (me._opts.autoView) {
- if (!me._map.getBounds().containsPoint(pos)) {
- me._map.setCenter(pos);
- }
- }
- }
- // 变更
- //正在移动
- me._marker.setPosition(pos);
- me._markerL.setPosition(pos);
- me._markerR.setPosition(pos);
- //设置自定义overlay的位置
- me._setInfoWin(pos);
- }
- }, timer);
- },
- /**
- * 在每个点的真实步骤中设置小车转动的角度
- */
- setRotation: function (prePos, curPos, targetPos, direction) {
- var me = this;
- var deg = 0;
- //start!
- curPos = me._map.pointToPixel(curPos);
- targetPos = me._map.pointToPixel(targetPos);
- if (targetPos.x != curPos.x) {
- var tan = (targetPos.y - curPos.y) / (targetPos.x - curPos.x),
- atan = Math.atan(tan);
- deg = (atan * 360) / (2 * Math.PI);
- //degree correction;
- if ((!direction && targetPos.x < curPos.x) || direction === "left") {
- deg = -deg + 90 + 90;
- } else {
- deg = -deg;
- }
- // 变更
- me._marker.setRotation(-deg);
- me._markerL.setRotation(-deg);
- me._markerR.setRotation(-deg);
- } else {
- var disy = targetPos.y - curPos.y;
- var bias = 0;
- if (disy > 0) {
- bias = -1;
- } else {
- bias = 1;
- }
- // 变更
- me._marker.setRotation(-bias * 90);
- me._markerL.setRotation(-bias * 90);
- me._markerR.setRotation(-bias * 90);
- }
- return;
- },
- linePixellength: function (from, to) {
- return Math.sqrt(
- Math.abs(from.x - to.x) * Math.abs(from.x - to.x) +
- Math.abs(from.y - to.y) * Math.abs(from.y - to.y)
- );
- },
- pointToPoint: function (from, to) {
- return (
- Math.abs(from.x - to.x) * Math.abs(from.x - to.x) +
- Math.abs(from.y - to.y) * Math.abs(from.y - to.y)
- );
- },
- /**
- * 移动到下一个点
- * @param {Number} index 当前点的索引.
- * @return 无返回值.
- */
- _moveNext: function (index) {
- var me = this;
- // debugger;
- if (index < this.path.length - 1) {
- me._move(me.path[index], me.path[index + 1], me._tween.linear);
- } else {
- me._opts.onComplete && me._opts.onComplete()
- }
- },
- /**
- * 设置小车上方infowindow的内容,位置等
- * @param {Point} pos 经纬度坐标点.
- * @return 无返回值.
- */
- _setInfoWin: function (pos) {
- //设置上方overlay的position
- var me = this;
- if (!me._overlay) {
- return;
- }
- me._overlay.setPosition(pos, me._marker.getIcon().size);
- var index = me._troughPointIndex(pos);
- if (index != -1) {
- clearInterval(me._intervalFlag);
- me._overlay.setHtml(me._opts.landmarkPois[index].html);
- me._overlay.setPosition(pos, me._marker.getIcon().size);
- me._pauseForView(index);
- } else {
- me._overlay.setHtml(me._opts.defaultContent);
- }
- },
- /**
- * 在某个点暂停的时间
- * @param {Number} index 点的索引.
- * @return 无返回值.
- */
- _pauseForView: function (index) {
- var me = this;
- var t = setTimeout(function () {
- //运行下一个点
- me._moveNext(++me.i);
- }, me._opts.landmarkPois[index].pauseTime * 1000);
- me._setTimeoutQuene.push(t);
- },
- //清除暂停后再开始运行的timeout
- _clearTimeout: function () {
- for (var i in this._setTimeoutQuene) {
- clearTimeout(this._setTimeoutQuene[i]);
- }
- this._setTimeoutQuene.length = 0;
- },
- //缓动效果
- _tween: {
- //初始坐标,目标坐标,当前的步长,总的步长
- linear: function (initPos, targetPos, currentCount, count) {
- var b = initPos;
- var c = targetPos - initPos;
- var t = currentCount;
- var d = count;
- return (c * t) / d + b;
- },
- },
- /**
- * 否经过某个点的index
- * @param {Point} markerPoi 当前小车的坐标点.
- * @return 无返回值.
- */
- _troughPointIndex: function (markerPoi) {
- var t = this._opts.landmarkPois;
- var distance;
- for (var i = 0, len = t.length; i < len; i++) {
- //landmarkPois中的点没有出现过的话
- if (!t[i].bShow) {
- distance = this._map.getDistance(
- new BMapGL.Point(t[i].lng, t[i].lat),
- markerPoi
- );
- //两点距离小于10米,认为是同一个点
- if (distance < 10) {
- t[i].bShow = true;
- return i;
- }
- }
- }
- return -1;
- },
- });
- /**
- * 获取大圆点
- * @return {Array} 大圆点
- */
- function getGeodesicPath(points) {
- var gPath = [];
- for (var i = 0; i < points.length - 1; i++) {
- var great = calcGreatCirclePath(points[i], points[i + 1]);
- gPath = gPath.concat(great);
- }
- gPath = gPath.concat(points[points.length - 1]);
- return gPath;
- }
- /**
- * 计算大圆上的点
- * @param {Object} latLng1 点1
- * @param {Object} latLng2 点2
- * @return {Array} 扩充后的点
- */
- function calcGreatCirclePath(latLng1, latLng2) {
- // 计算需要多少个插值点,根据显示效果,每250公里需要一个。
- if (latLng1.equals(latLng2)) {
- // 两个相等的坐标通过下面距离计算会得到地球周长,因此提前判断
- return [latLng1];
- }
- var distance = BMapGL.Projection.getDistance(
- toRadian(latLng1.lng),
- toRadian(latLng1.lat),
- toRadian(latLng2.lng),
- toRadian(latLng2.lat)
- );
- var distance = BMapGL.Projection.getDistanceByLL(latLng1, latLng2);
- if (distance < 250000) {
- return [latLng1];
- }
- // 清空现有数据
- // this.greatCirclePoints.length = 0;
- var result = [];
- // 间隔设置小于250公里是因为在靠近南北两极同样的公里数所代表的平面跨度增加
- var count = Math.round(distance / 150000);
- var angularDistance = calcAngularDistance(latLng1, latLng2);
- result.push(latLng1);
- for (var i = 0; i < count; i++) {
- var eachLatLng = calcMiddlePoint(
- latLng1,
- latLng2,
- i / count,
- angularDistance
- );
- result.push(eachLatLng);
- }
- result.push(latLng2);
- return result;
- }
- /**
- * 给两个点,计算地球大圆上的中间点
- * https://www.movable-type.co.uk/scripts/latlong.html
- *
- * @param {Point} latLng1 起点
- * @param {Point} latLng2 终点
- * @param {number} f fraction along great circle route
- * @param {number} delta angular distance d/R between the two points.
- * @return {Point} 大圆上的中间点
- */
- function calcMiddlePoint(latLng1, latLng2, f, delta) {
- var lat1 = latLng1.lat;
- var lat2 = latLng2.lat;
- var lon1 = latLng1.lng;
- var lon2 = latLng2.lng;
- var phi1 = toRadian(lat1);
- var phi2 = toRadian(lat2);
- var lambda1 = toRadian(lon1);
- var lambda2 = toRadian(lon2);
- var a = Math.sin((1 - f) * delta) / Math.sin(delta);
- var b = Math.sin(f * delta) / Math.sin(delta);
- var x =
- a * Math.cos(phi1) * Math.cos(lambda1) +
- b * Math.cos(phi2) * Math.cos(lambda2);
- var y =
- a * Math.cos(phi1) * Math.sin(lambda1) +
- b * Math.cos(phi2) * Math.sin(lambda2);
- var z = a * Math.sin(phi1) + b * Math.sin(phi2);
- var phi = Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
- var lambda = Math.atan2(y, x);
- return new BMapGL.Point(toAngle(lambda), toAngle(phi));
- }
- function toRadian(angle) {
- return (angle * Math.PI) / 180;
- }
- function toAngle(radian) {
- return (radian / Math.PI) * 180;
- }
- /**
- * 计算角距离
- *
- * @param {Point} latLng1 起点
- * @param {Point} latLng2 终点
- * @return {number} 角距离
- */
- function calcAngularDistance(latLng1, latLng2) {
- // console.log(latLng1.lat, latLng1.lng, latLng2.lat, latLng2.lng);
- var lat1 = toRadian(latLng1.lat);
- var lat2 = toRadian(latLng2.lat);
- var lng1 = toRadian(latLng1.lng);
- var lng2 = toRadian(latLng2.lng);
- return Math.acos(
- Math.sin(lat1) * Math.sin(lat2) +
- Math.cos(lat1) * Math.cos(lat2) * Math.cos(Math.abs(lng2 - lng1))
- );
- }
- /**
- * 自定义的overlay,显示在小车的上方
- * @param {Point} Point 要定位的点.
- * @param {String} html overlay中要显示的东西.
- * @return 无返回值.
- */
- function CustomOverlay(point, html) {
- this._point = point;
- this._html = html;
- }
- CustomOverlay.prototype = new BMapGL.Overlay();
- CustomOverlay.prototype.initialize = function (map) {
- var div = (this._div = baidu.dom.create("div", {
- style:
- "border:solid 1px #ccc;width:auto;min-width:50px;text-align:center;position:absolute;background:#fff;color:#000;font-size:12px;border-radius: 10px;padding:5px;white-space: nowrap;",
- }));
- div.innerHTML = this._html;
- map.getPanes().floatPane.appendChild(div);
- this._map = map;
- return div;
- };
- CustomOverlay.prototype.draw = function () {
- this.setPosition(
- this.lushuMain._marker.getPosition(),
- this.lushuMain._marker.getIcon().size
- );
- };
- baidu.object.extend(CustomOverlay.prototype, {
- //设置overlay的position
- setPosition: function (poi, markerSize) {
- // 此处的bug已修复,感谢 苗冬(diligentcat@gmail.com) 的细心查看和认真指出
- var px = this._map.pointToOverlayPixel(poi);
- var styleW = baidu.dom.getStyle(this._div, "width");
- var styleH = baidu.dom.getStyle(this._div, "height");
- var overlayW = parseInt(this._div.clientWidth || styleW, 10);
- var overlayH = parseInt(this._div.clientHeight || styleH, 10);
- this._div.style.left = px.x - overlayW / 2 + "px";
- this._div.style.bottom = -(px.y - markerSize.height) + "px";
- },
- //设置overlay的内容
- setHtml: function (html) {
- this._div.innerHTML = html;
- },
- //跟customoverlay相关的实例的引用
- setRelatedClass: function (lushuMain) {
- this.lushuMain = lushuMain;
- },
- });
- })();
|