js实现百度地图超过边界提示
程序员文章站
2022-07-13 14:56:19
...
需求:有55个点,其中50个点在省内,5个点在省外,地图加载的时候视野默认为省内的范围,然后省外的点需要动态的使用箭头的形式去提示地图外的那一个方向还有点,且随着地图放大缩小,拖动而实时更新箭头的位置。效果图:
其实这个需求最大的难点在于,怎么去找到省外的点在那个方向,夹角是多少。
实现思路:首先,我们是可以拿到当前地图视野的四个角,中心店以及省外的点经纬度的,所以只需要把经纬度(球面坐标),当成平面的直角坐标换算就可以了,如果外面的点不在当前地图视野内的话,外面的点与当前视野地图中心店连接,肯定会与当前地图的四条边界线有交点的。然后只需要知道与那一条边界线有交点,之后求出交点的坐标以及夹角就可以了。对地图做放大缩小以及拖动事件,然后在取得的点上面添加箭头的覆盖物就可以了。这个思路会有一点偏差,但是在可接受的范围内。
下面是完整代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html{width: 100%;height: 100%;margin:0;font-family:"微软雅黑";}
#allmap{height:100%;width:100%;}
</style>
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=你的AK"></script>
<title>demo</title>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
<script type="text/javascript">
// 百度地图API功能
var map = new BMap.Map("allmap");
// 贵州省人民* 106.711957,26.606065
//随机生成50个贵州附近的点坐标
var baseGps = new BMap.Point(106.711957,26.606065);
//集中视野坐标集合
var listGps = [];
for(var i = 0; i < 50; i++){
var difLng = Math.random() * 2 - 1;
var difLat = Math.random() * 2 -1;
var newGps = new BMap.Point(baseGps.lng + difLng,baseGps.lat + difLat);
var newGpsMarker = new BMap.Marker(newGps);
map.addOverlay(newGpsMarker);
listGps.push(newGps);
}
map.centerAndZoom(baseGps,11);
map.enableScrollWheelZoom(true);
map.setViewport(listGps);
//用于保存外围坐标点marker集合
var crossMarkers = {};
//外围坐标点,也不一定全在外边
var outList = [];
//随机生成几个大范围坐标
for(var i = 0; i < 5; i++){
var lng = Math.random() * 60 + 75;
var lat = Math.random() * 50 + 3;
var out = new BMap.Point(lng,lat);
var outMarker = new BMap.Marker(out);
map.addOverlay(outMarker);
outList.push(out);
crossMarkers[i] = null;
}
guide();
//放大缩小监听事件
map.addEventListener("zoomend", guide);
//拖动中监听事件
map.addEventListener("dragging", guide);
//拖动结束监听事件
map.addEventListener("dragend", guide);
function guide(){
//获取当前地图边界信息以及四个角的坐标点
var bounds = map.getBounds();
var sw = bounds.getSouthWest();
var ne = bounds.getNorthEast();
var wn = new BMap.Point(sw.lng,ne.lat);
var es = new BMap.Point(ne.lng,sw.lat);
var center = map.getBounds().getCenter();
//坐标转换
var pxCenter = map.pointToPixel(center);
var pxSW = map.pointToPixel(sw);
var pxWN = map.pointToPixel(wn);
var pxNE = map.pointToPixel(ne);
var pxES = map.pointToPixel(es);
var myIcon = new BMap.Icon("location.png", new BMap.Size(30,30));
for(var i = 0; i < outList.length; i++){
var outGps = outList[i];
if(!bounds.containsPoint(outGps)){
var pxOut = map.pointToPixel(outGps);
var cross;
var swn = false;
var wne = false;
var nes = false;
var esw = false;
//左
if(segmentsIntr(pxOut,pxCenter,pxSW,pxWN)){
swn = true;
cross = map.pixelToPoint(segmentsIntr(pxOut,pxCenter,pxSW,pxWN));
}
//上
if(segmentsIntr(pxOut,pxCenter,pxWN,pxNE)){
wne = true;
cross = map.pixelToPoint(segmentsIntr(pxOut,pxCenter,pxWN,pxNE));
}
//右
if(segmentsIntr(pxOut,pxCenter,pxNE,pxES)){
nes = true;
cross = map.pixelToPoint(segmentsIntr(pxOut,pxCenter,pxNE,pxES));
}
//下
if(segmentsIntr(pxOut,pxCenter,pxES,pxSW)){
esw = true;
cross = map.pixelToPoint(segmentsIntr(pxOut,pxCenter,pxES,pxSW));
}
if(cross){
if(!crossMarkers[i]){
crossMarkers[i] = new BMap.Marker(cross,{icon:myIcon});
if(swn){
var size = new BMap.Size(19,0);
crossMarkers[i].setOffset(size);
}
if(wne){
var size = new BMap.Size(0,25);
crossMarkers[i].setOffset(size);
}
if(nes){
var size = new BMap.Size(-19,0);
crossMarkers[i].setOffset(size);
}
if(esw){
var size = new BMap.Size(0,0);
crossMarkers[i].setOffset(size);
}
crossMarkers[i].setRotation(getRotation(pxCenter,pxOut));
map.addOverlay(crossMarkers[i]);
crossMarkers[i].setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
}
}
}else{
map.removeOverlay(crossMarkers[i]);
}
}
}
/**
* 求两条线段的交点
*/
function segmentsIntr(a, b, c, d){
/** 1 解线性方程组, 求线段交点. **/
// 如果分母为0 则平行或共线, 不相交
var denominator = (b.y - a.y)*(d.x - c.x) - (a.x - b.x)*(c.y - d.y);
if (denominator==0) {
return false;
}
// 线段所在直线的交点坐标 (x , y)
var x = ( (b.x - a.x) * (d.x - c.x) * (c.y - a.y)
+ (b.y - a.y) * (d.x - c.x) * a.x
- (d.y - c.y) * (b.x - a.x) * c.x ) / denominator ;
var y = -( (b.y - a.y) * (d.y - c.y) * (c.x - a.x)
+ (b.x - a.x) * (d.y - c.y) * a.y
- (d.x - c.x) * (b.y - a.y) * c.y ) / denominator;
/** 2 判断交点是否在两条线段上 **/
if (
// 交点在线段1上
(x - a.x) * (x - b.x) <= 0 && (y - a.y) * (y - b.y) <= 0
// 且交点也在线段2上
&& (x - c.x) * (x - d.x) <= 0 && (y - c.y) * (y - d.y) <= 0
){
// 返回交点p
return new BMap.Pixel(x,y);
}
//否则不相交
return false;
}
/**
* 求两个坐标点之间的偏移角度
*/
function getRotation(p_start,p_end){
var diff_x = p_end.x - p_start.x, diff_y = p_end.y - p_start.y;
return 360*Math.atan2(diff_y, diff_x)/(2*Math.PI)+90;
}
</script>
根据你的项目的需求,把代码带进去就可以了!
欢迎各位大佬交流!