先上最终实现图
关键点:
1.首先是箭头线图形,entity 实体中polyline 有一个PolylineArrowMaterialProperty字段可以生成箭头,具体实现官网上有,这里不做阐述
2.其次三个方向的坐标系的建立,单方向的轴,像点位置可以作为一个Z轴,然后去该轴和竖直方向的轴进行叉乘,得出一个方向的轴,以此类推,
代码局部实现:
// 向上的向量
const vectorNormalUp = new Cartesian3();
const vZ = new Cartesian3(0, 0, 1);
Cartesian3.normalize(this.position.clone(), vectorNormalUp);
// 向右的向量
const vectorNormalRight = new Cartesian3();
// 由z轴向上 地表向上两个向量叉乘, 则可以得出, 向右的向量
Cartesian3.cross(vZ, vectorNormalUp, vectorNormalRight);
Cartesian3.normalize(vectorNormalRight, vectorNormalRight);
// 向前的向量
const vectorNormalFront = new Cartesian3();
Cartesian3.cross(vectorNormalRight, vectorNormalUp, vectorNormalFront);
Cartesian3.multiplyByScalar(vectorNormalFront, -1, vectorNormalFront);
Cartesian3.normalize(vectorNormalFront, vectorNormalFront);
三个轴方向可以同时解决我们两个问题,一个是轴的绘制,一个是平移方向的单位向量
3.平移拖动拖动的长度方法如下,参数(两个相机到点的位置作差)
/**
* 获取相机到点的向量
* @param position{Cartesian3} 模型位置
* @param cameraPosition{Cartesian3} 相机位置
* @param pickRay{Ray} 从相机到屏幕的射线
* @param axisDirection{Cartesian3} 轴的向量
*/
getPlaneC3(position, cameraPosition, pickRay, axisDirection) {
// 模型到相机
const cartesian3 = Cartesian3.subtract(
cameraPosition,
position,
new Cartesian3()
);
// 相机到轴投影
const length = Cartesian3.dot(cartesian3, axisDirection);
const projectionC3 = Cartesian3.multiplyByScalar(
axisDirection,
length,
new Cartesian3()
);
// 相机到轴法线
const faxian = Cartesian3.subtract(
cartesian3,
projectionC3,
new Cartesian3()
);
// 相机到实际点在法线映射长度
const num2 = Cartesian3.dot(pickRay.direction, faxian);
// 相机法线总长度
const alllen = Cartesian3.dot(cartesian3, faxian);
// 相机到实际点的向量
const result = Cartesian3.multiplyByScalar(
pickRay.direction,
-alllen / num2,
new Cartesian3()
);
return result;
}
4.轴根据视角大小变动------坐标系轴长一开始的确立会导致缩放地图时看不清----目前暂时想到能用的办法是实际长度和相机到点位置的高度设置一个比例,调整相机时比例跟着同步增长
代码实现:
// 根据当前相机定轴长(注意:若相机未飞在最高处,轴将获得一个很大的值)
this.height = Cartographic.fromCartesian(this.position).height;
const cameraHeight = this.viewer.camera.positionCartographic.height;
const heghtPoor = Math.abs(cameraHeight - this.height);
this.length = (15 / 350) * heghtPoor;
this.id = option.id;
const axis = Cartesian3.multiplyByScalar(
this.direction,
this.length,
new Cartesian3()
);
this.endPos = Cartesian3.add(axis, this.position, new Cartesian3());
this.entity = new Entity({
id: this.id,
polyline: new PolylineGraphics({
positions: new CallbackProperty(
() => [this.position, this.endPos],
false
),
// clampToGround: true,
width: 15,
material: new PolylineArrowMaterialProperty(this.color)
})
});
this.eventHandler = new ScreenSpaceEventHandler(
this.viewer.scene.canvas as HTMLCanvasElement
);
this.eventHandler.setInputAction(
() => this.updateLength(),
ScreenSpaceEventType.WHEEL
);
参考博客: