Openlayer地图折线上点的信息错位标注方法,尽量不压到线,如下图所示:
解决思路如下:
一、起点处理
起点与第二点标牌方向相反
二、中间点处理
以中间点为坐标系原点,求中间点连接的两条边线在第几象限,并求出每天条边线与y轴正半轴之间的夹角。
1、两个边不在一条直线上,标牌标在中间点连接的边线的两个夹角的角度最大的一边
(1)两个边在同一象限
case 同象限1、1 标牌标在象限3
case 同象限2、2 标牌标在象限4
case 同象限3、3 标牌标在象限1
case 同象限4、4 标牌标在象限2
(2)两个边在两个相连象限
case 象限1、2 标牌标在y轴负半轴
case 象限2、3 标牌标在x轴正半轴
case 象限3、4 标牌标在y轴正半轴
case 象限1、4 标牌标在x轴负半轴
(3)两个边在两个不相连象限
case 象限1、3 if(大角-小角)>180 标牌标在象限4 else 标牌标在象限2
case 象限2、4 if(大角-小角)>180 标牌标在象限3 else 标牌标在象限1
2、如果两个夹角的角度相等,即两个边在一条直线上,标牌标注与上一个点的标注相反错开标注
case 边线与坐标Y轴正方向角度小的线在[0<=a<45 and 135<=a<=180] 标牌左右标注,第一个点默认右(最好与上一标牌左右错开)
case 边线与坐标Y轴正方向角度小的线在[45<=a<135] 标牌上下标注,第一个点默认下(最好与上一标牌上下错开)
三、终点处理
终点与前一点标牌方向相反。
javascript关键代码如下:
//获得线上结点标牌显示位置以该点为原点,与X轴正半轴之间的夹角(先调用这个函数)
//sx 要标注点的前一个点的x坐标
//sy 要标注点的前一个点的y坐标
//mx 要标注点的x坐标
//my 要标注点的y坐标
//ex 要标注点后一个点的x坐标
//ey 要标注点后一个点的y坐标
//pAngle 要标注点前一个点的标牌标准角度
getLabelPlace (sx, sy, mx, my, ex, ey, pAngle = -1) {
//console.log('sssss:', sx + ',' + sy + ',' + mx + ',' + my + ',' + ex + ',' + ey);
let mSAngle = this.getAngle(mx, my, sx, sy);
let mEAngle = this.getAngle(mx, my, ex, ey);
//console.log('pAngle:', pAngle);
//console.log('mSAngle:', mSAngle);
//console.log('mEAngle:', mEAngle);
let minAngle = mSAngle < mEAngle ? mSAngle : mEAngle;
let maxAngle = mSAngle > mEAngle ? mSAngle : mEAngle;
//console.log('pAngle0:', pAngle);
//console.log('minAngle:', minAngle);
//console.log('maxAngle:', maxAngle);
let angle = 0;
//判断大角与小角是否在一条直线上
if ((maxAngle - minAngle) == 180) {//在一条直线上
if ((minAngle >= 0 && minAngle < 45) || (minAngle >= 135 && minAngle <= 180)) {
if (0 <= pAngle && pAngle < 180) {
angle = 270;
}
else {
angle = 90;
}
}
else {
if (90 <= pAngle && pAngle < 270) {
angle = 0;
}
else {
angle = 180;
}
}
//console.log('直线不考虑象限');
}
else {//不在一条直线上
//判断大角与小角所在象限情况
switch (true) {
case 0 <= minAngle && minAngle < 90 && 0 <= maxAngle && maxAngle <= 90://大、小角同在象限1
angle = 225;
//console.log('象限:', '大、小角同在象限1');
break;
case 90 <= minAngle && minAngle < 180 && 90 <= maxAngle && maxAngle <= 180://大、小角同在象限2
angle = 315;
//console.log('象限:', '大、小角同在象限2');
break;
case 180 <= minAngle && minAngle < 270 && 180 <= maxAngle && maxAngle <= 270://大、小角同在象限3
angle = 45;
//console.log('象限:', '大、小角同在象限3');
break;
case 270 <= minAngle && minAngle < 360 && 270 <= maxAngle && maxAngle <= 360://大、小角同在象限4
angle = 135;
//console.log('象限:', '大、小角同在象限4');
break;
case 0 <= minAngle && minAngle < 90 && 90 < maxAngle && maxAngle <= 180://大角象限2、小角象限1
angle = 270;
//console.log('象限:', '大角象限2、小角象限1');
break;
case 90 <= minAngle && minAngle < 180 && 180 < maxAngle && maxAngle <= 270://大角象限3、小角象限2
angle = 0;
//console.log('象限:', '大角象限3、小角象限2');
break;
case 180 <= minAngle && minAngle < 270 && 270 < maxAngle && maxAngle <= 360://大角象限4、小角象限3
angle = 90;
//console.log('象限:', '大角象限4、小角象限3');
break;
case 0 <= minAngle && minAngle < 90 && 270 < maxAngle && maxAngle <= 360://大角象限4、小角象限1
angle = 180;
//console.log('象限:', '大角象限4、小角象限1');
break;
case 0 <= minAngle && minAngle < 90 && 180 <= maxAngle && maxAngle < 270: //大角象限3、小角象限1
if ((maxAngle - minAngle) < 180) {
angle = 315;
}
else {
angle = 135;
}
//console.log('象限:', '大角象限3、小角象限1');
break;
case 90 <= minAngle && minAngle < 180 && 270 < maxAngle && maxAngle <= 360://大角象限4、小角象限2
if ((maxAngle - minAngle) < 180) {
angle = 45;
}
else {
angle = 225;
}
//console.log('象限:', '大角象限4、小角象限2');
break;
default:
angle = -1;
//console.log('象限:', '输入角度范围错误!');
break;
}
}
return angle;
},
//获得两坐标点连线,与X轴正半轴之间的夹角
getAngle (sx, sy, ex, ey) {
let x = Math.abs(ex - sx);
let y = Math.abs(ey - sy);
let z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
let sin = y / z;
let radina = Math.asin(sin);//用反三角函数求弧度
let angle = Math.floor(180 / (Math.PI / radina));//将弧度转换成角度
//console.log('angle:', angle);
if (ex == sx && ey > sy) {//在y轴正方向上
angle = 90;
}
if (ex < sx && ey > sy) {//在第二象限
angle = 180 - angle;
}
if (ex < sx && ey == sy) {//在x轴负方向
angle = 180;
}
if (ex < sx && ey < sy) {//在第三象限
angle = 180 + angle;
}
if (ex == sx && ey < sy) {//在y轴负方向上
angle = 270;
}
if (ex > sx && ey < sy) {//在第四象限
angle = 360 - angle;
}
return angle;
},
//求传入角度直线反方向上角度
getAngleReverse (labelAngle) {
if (labelAngle < 180) {
labelAngle = labelAngle + 180;
}
else {
labelAngle = labelAngle - 180;
}
return labelAngle;
},