需求:有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>
根據你的項目的需求,把代碼帶進去就可以了!
demo詳情下載地址:百度地圖超出當前視野邊界提示
歡迎各位大佬交流!