设计一个SuperMap3DLayer类来汇总超图的功能点
用于汇总超图的功能点,这样可以方便地管理和使用超图的三维地图功能。同时这个类可以封装超图提供的各种三维地图操作,如加载三维图层、进行空间分析、实现交互式操作等。
一、 自定义事件监听
- 通过事件监听,可以实现模块间的解耦,提高代码的可维护性和可扩展性。
- 自定义事件监听允许开发者根据特定需求来定义事件和响应。
- 通过自定义事件监听,可以捕捉用户的操作,如点击,扩展超图的点击。
1. 自己实现发布订阅的事件
export default class SuperMap3DLayer {
private subscribe: Map<string, Array<Function>>;
constructor(options?: any) {
this.subscribe = new Map();
}
public static on(event: BaseMapEventEnum, callback: Function) {
if (!event) return;
const sub = this.subscribe.get(event.toString()) || [];
sub.push(callback);
this.subscribe.set(event.toString(), sub);
}
public static emit(type: BaseMapEventEnum, ...args: any[]) {
const events = this.subscribe.get(type.toString());
if (events) {
events.forEach((el) => el(...args));
}
}
public static off(event: BaseMapEventEnum, callback: Function) {
const events = this.subscribe.get(event.toString());
if (events) {
const index = events.indexOf(callback);
if (index !== -1) {
events.splice(index, 1);
}
}
}
public destroy() {
this.subscribe.clear();
}
}
使用方法:
- 监听事件:
SuperMap3DLayer.on('resetMap', (e) => console.log); - 发送事件:
SuperMap3DLayer.emit('resetMap', false);
2、使用mitt 【推荐😄😄😄】
import mitt, { Emitter, EventType } from 'mitt';
export default class SuperMap3DLayer {
static emitter: Emitter<Record<EventType, unknown>>;
constructor(options?: SuperMap3DLayerOptions) {
SuperMap3DLayer.emitter = mitt();
}
}
使用方法:
-
监听事件:
SuperMap3DLayer.emitter.on('resetMap', (e) => console.log); -
发送事件:
SuperMap3DLayer.emitter.emit('resetMap', false);
二、 基础图层功能
1. 使用天地图初始化超图 ✨
const URL_CONFIG = {
TOKEN_TIANDITU: '天地图TOKEN',
TDT_VEC: '//t0.tianditu.gov.cn/vec_w/wmts', // 天地图影像
TDT_IMG: '//[subdomain].tianditu.com/img_w/wmts', // 天地图影像
TDT_LABEL: '//{s}.tianditu.gov.cn/mapservice', // 天地图文字注记
};
initSuperMap() {
// 初始化
SuperMap3DLayer.viewer = new SuperMap3D.Viewer(SuperMap3DLayer.options.container, {
skyAtmosphere: false, // 自行根据业务调整
skyBox: false, // 自行根据业务调整
InfoBox: false, // 自行根据业务调整
});
// 设置背景
SuperMap3DLayer.viewer.scene.backgroundColor = new SuperMap3D.Color(0.0, 0.0, 0.0, 0.0);
// 设置相机
SuperMap3DLayer.viewer.scene.camera.setView({
destination: SuperMap3D.Cartesian3.fromDegrees(120.2, 30.3, 1000000.0),
});
// 缩放比例,以匹配设备的像素比例
SuperMap3DLayer.viewer.resolutionScale = window.devicePixelRatio;
// 添加影像图层
SuperMap3DLayer.imagery_img_w = SuperMap3DLayer.viewer.imageryLayers.addImageryProvider(
new SuperMap3D.TiandituImageryProvider({
token: URL_CONFIG.TOKEN_TIANDITU,
}),
);
// 添加矢量图层
SuperMap3DLayer.imagery_vec_w = SuperMap3DLayer.viewer.imageryLayers.addImageryProvider(
new SuperMap3D.TiandituImageryProvider({
mapStyle: 'vec_w',
token: URL_CONFIG.TOKEN_TIANDITU,
}),
);
// 指定三维场景的默认底图样式
SuperMap3DLayer.baseMapStyle = 'imagery_img_w';
// 最大缩放距离,单位为米
SuperMap3DLayer.viewer.scene.screenSpaceCameraController.maximumZoomDistance = 700000;
// 环境光颜色
SuperMap3DLayer.viewer.scene.lightSource.ambientLightColor = new SuperMap3D.Color(0.65, 0.65, 0.65, 1);
}
2. 实现底图切换 ✨
public static set baseMapStyle(mapStyle: string) {
const styles = {
imagery_img_w: 0,
imagery_vec_w: 0,
};
for (const stylesKey in styles) {
if (mapStyle === stylesKey) {
SuperMap3DLayer[stylesKey].alpha = 1;
} else {
SuperMap3DLayer[stylesKey].alpha = 0;
}
}
}
3. 监听场景的缩放事件 ✨
public static bindScaleEvent() {
SuperMap3DLayer.viewer.scene.camera.changed.addEventListener(
throttle(() => {
const cameraHeight = SuperMap3DLayer.viewer.scene.camera.positionCartographic.height;
SuperMap3DLayer.emitter.emit('zoomRangeLevelWatch', cameraHeight);
}, 500),
);
};
4. 监听场景的鼠标移入事件 ✨
public static bindMouseOverEvent() {
const handler = new SuperMap3D.ScreenSpaceEventHandler(SuperMap3DLayer.viewer.canvas);
// 过滤不需要监听移入的实体
const blackList = ['2D_XGQ_PROTECT', ''];
handler.setInputAction(
debounce((event) => {
const pickedObjects = SuperMap3DLayer.viewer.scene.drillPick(event.endPosition);
let pickedObject = null;
for (let i = 0; i < pickedObjects.length; i++) {
const type = pickedObjects[i].id?.dataset?.type;
if (type && !blackList.includes(type)) {
pickedObject = pickedObjects[i];
}
if (i > 3) {
break;
}
}
if (SuperMap3D.defined(pickedObject) && pickedObject.id) {
const picked = pickedObject.id;
const { dataset } = picked;
// 拿到移入对象的额外数据
}
}, 2),
SuperMap3D.ScreenSpaceEventType.MOUSE_MOVE,
);
}
5. 监听场景的鼠标点击事件 ✨
public static bindClickEvent() {
const handler = new SuperMap3D.ScreenSpaceEventHandler(SuperMap3DLayer.viewer.canvas);
const blackList = ['2D_HXBHQFW_PROTECT', '2D_HJXTQ_PROTECT', '2D_XGQ_PROTECT', ''];
handler.setInputAction((event) => {
// @ts-ignore
const pickedObjects = SuperMap3DLayer.viewer.scene.drillPick(event.position);
let pickedObject = null;
for (let i = 0; i < pickedObjects.length; i++) {
const type = pickedObjects[i].id?.dataset?.type;
if (type && !blackList.includes(type)) {
pickedObject = pickedObjects[i];
}
if (i > 3) {
break;
}
}
if (SuperMap3D.defined(pickedObject) && pickedObject.id) {
const picked = pickedObject.id;
const { dataset } = picked;
// 拿到点击对象的额外数据
}
}, SuperMap3D.ScreenSpaceEventType.LEFT_CLICK);
}
6. 渲染倾斜摄影图层
public static renderProtectObliquePhotography(url: string, only3D: boolean) {
SuperMap3DLayer.viewer.scene.addS3MTilesLayerByScp(
`${url}/datas/Combine/config`,
{
autoSetView: !!only3D,
cullEnabled: false,
subdomains: [],
name: '3D_PROTECT',
},
1,
)
.then((layer) => {
layer.dataset = {
name: '3D_PROTECT',
pname: '倾斜摄影',
};
}
7. 划线
/**
* 绘制行政区划线
* @param position [lng, lat, lng, lat, ....]
* @param isScale 是否在添加完成后画面缩放到此实体
* @param name 标识名称
*/
public static drawLine(position, isScale = false, name = '') {
const points = SuperMap3D.Cartesian3.fromDegreesArray(position);
const lineEntity = new SuperMap3D.Entity({
pname: `${name}线`,
polyline: {
positions: points,
width: 2,
clampToGround: true,
material: new SuperMap3D.Color(255 / 255.0, 235 / 255.0, 59 / 255.0, 0.7),
},
});
SuperMap3DLayer.viewer.entities.add(lineEntity);
if (isScale) {
SuperMap3DLayer.viewer.camera.setView(lineEntity);
}
}
8. 划面
let zIndex = 1000;
public static drawPoly(polys: any[]) {
const renderPolygon = (polygons, el, zIndex) => {
SuperMap3DLayer.viewer.entities.add({
name: '配置图层',
pname: this.options.pname,
position: SuperMap3D.Cartesian3.fromDegrees(el.center.x, el.center.y, zHeight),
// 文字标记
label: {
fillColor: SuperMap3D.Color.BLACK,
outlineColor: SuperMap3D.Color.WHITE,
outlineWidth: 5,
style: SuperMap3D.LabelStyle.FILL_AND_OUTLINE,
font: '16px Helvetica',
text: el.name,
disableDepthTestDistance: 1200,
distanceDisplayCondition: new SuperMap3D.DistanceDisplayCondition(10, 10000),
pixelOffset: new SuperMap3D.Cartesian2(43, 0),
},
// 自定义图标
billboard: {
image: `/images/layer/${imgName}.png`,
width: 43,
height: 87,
disableDepthTestDistance: 1200,
distanceDisplayCondition: new SuperMap3D.DistanceDisplayCondition(10, 5000),
scaleByDistance: new SuperMap3D.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.0),
},
// 额外数据
dataset: {
...this.options,
pname: this.options.pname,
active: false,
name: el.name,
center: el.center,
},
polygon: {
hierarchy: SuperMap3D.Cartesian3.fromDegreesArray(el.point),
outline: true,
zIndex,
...polygons,
},
});
};
polys.forEach((el) => {
const polygons = {
clampToGround: true, // 多边形紧贴地形
material: featColors[type].base,
outlineColor: featColors[type].base,
outlineWidth: 2.0,
};
renderPolygon(polygons, el, zIndex);
}
}
9. 划体
// 面增加 hierarchy 即可
polygon: {
hierarchy: SuperMap3D.Cartesian3.fromDegreesArrayHeights(el.point),
outline: false,
perPositionHeight: true,
...polygons,
},
10. 删除实体
static clearEntitiesLayers() {
const toRemove = [];
SuperMap3DLayer.viewer?.entities?.values.forEach((el) => {
if (el.pname === '删除标识') {
toRemove.push(el);
}
});
toRemove.forEach((el) => {
SuperMap3DLayer.viewer.entities.remove(el);
});
}
11. 绘制流光墙
/**
* 绘制流光墙
* @param features { poly: [], childRegion: [] }
*/
static drawAreaWall(features) {
// 设置墙的高度
const hWall = [0, 23200, 8000, 2000][features.regionLevel];
/**
* 渲染墙体动画
* @param positions [[lng, lat], [lng, lat]]
*/
const renderWall = (positions: [[lng, lat], [lng, lat]]) => {
SuperMap3DLayer.isRenderWall = true;
const arr = [];
positions.forEach((item) => {
arr.push(item[0]);
arr.push(item[1]);
});
const points = SuperMap3D.Cartesian3.fromDegreesArray(arr);
const wall = new SuperMap3D.Entity({
name: '立体墙效果',
wall: {
positions: points,
material: new SuperMap3D.PolylineTrailLinkMaterialProperty({
color: SuperMap3D.Color.fromBytes(82, 193, 236).withAlpha(0.7),
duration: 4500,
viewer: SuperMap3DLayer.viewer,
}),
clampToGround: true,
minimumHeights: new Array(points.length).fill(0),
maximumHeights: new Array(points.length).fill(hWall),
},
});
SuperMap3DLayer.viewer.entities.add(wall);
};
renderWall(poly)
}
11. 绘制遮罩层
static renderMask(poly:[[lng, lat], [lng, lat]] ) {
if (SuperMap3DLayer.hasMask) return;
SuperMap3DLayer.hasMask = true;
const holes = [];
poly?.forEach((el) => {
const arr = [];
el[0].forEach((item) => {
arr.push(item[0]);
arr.push(item[1]);
});
const points = SuperMap3D.Cartesian3.fromDegreesArray(arr);
holes.push({
positions: points,
});
});
// 遮罩地球
const polygonEntity = new SuperMap3D.Entity({
name: '遮照图层',
polygon: {
hierarchy: {
// 添加外部区域为1/4半圆,设置为180会报错
positions: SuperMap3D.Cartesian3.fromDegreesArray([0, 0, 0, 90, 179, 90, 179, 0]),
// 中心挖空的“洞”
holes,
},
material: new SuperMap3D.Color(15 / 255.0, 38 / 255.0, 84 / 255.0, 0.7),
},
});
SuperMap3DLayer.viewer.entities.add(polygonEntity);
}
12. 加载模型
static loadGlb() {
// 加载FBX模型
SuperMap3DLayer.viewer.entities.add({
name: 'WYJGLTFModel',
position: SuperMap3D.Cartesian3.fromDegrees(120.1787749, 30.48038052, 27.179),
orientation: SuperMap3D.Quaternion.fromHeadingPitchRoll(new SuperMap3D.HeadingPitchRoll(-1.05, -0.79, -1.01)),
model: {
uri: '/static/wangyuanjing/wangyuanjing.gltf', // FBX模型的路径
scale: 1.0,
minimumPixelSize: 40,
maximumScale: 40,
modelMatrix: SuperMap3D.Transforms.eastNorthUpToFixedFrame(
SuperMap3D.Cartesian3.fromDegrees(0, 0, 0),
new SuperMap3D.Ellipsoid(6378137, 6378137, 6356752.3142451793),
{
rotation: {
angle: 85,
axis: SuperMap3D.Cartesian3.UNIT_X,
},
},
),
},
});
}
四、 超图的分析工具类
已整合为一个综合类AnalysisTools,和各个不同的工具类。
const actionArr = [
{
name: '点选',
iconTop: 0,
fun: AnalysisTools.PickXYZ.bind(AnalysisTools),
},
{
name: '测距',
iconTop: -30,
fun: AnalysisTools.MeasureDistance.bind(AnalysisTools),
},
{
name: '测高',
iconTop: -60,
fun: AnalysisTools.MeasureHeight.bind(AnalysisTools),
},
{
name: '测面积',
iconTop: -90,
fun: AnalysisTools.MeasureArea.bind(AnalysisTools),
},
{
name: '测体积',
iconTop: -120,
fun: AnalysisTools.MeasureVolume.bind(AnalysisTools),
},
{
name: '天际线分析',
iconTop: -150,
fun: AnalysisTools.DrawSkyline.bind(AnalysisTools),
},
{
name: '绘制限高体',
iconTop: -180,
fun: AnalysisTools.DrawLimitHeight.bind(AnalysisTools),
},
{
name: '视域分析',
iconTop: -210,
fun: AnalysisTools.DrawView3D.bind(AnalysisTools),
},
{
name: '清除',
iconTop: -240,
fun: AnalysisTools.ClearAll.bind(AnalysisTools),
},
];
<div
v-for="(item, index) in actionArr"
:key="`action-${index}`"
class="flex cursor-pointer items-center px-10"
@click="item.fun()"
>
<div class="action-icon" :style="{ backgroundPosition: `0 ${item.iconTop}px` }"></div>
<div>{{ item.name }}</div>
</div>
- 😄 😃 🥰 😍 😘
- ❤️ ✨⭐ ❗❓❕❔
- ✊✌️ ✋✋ ☝️ 👏 🤝
- ☀️ ☔ ☁️ ❄️ ⛄ ⚡ ⛅
- ⛪ ⛺ ⛲ ⛵ ⚓ ✈️ ⛽ ⚠️ ♨️
- 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 0️⃣
- ◀️ ⬇️ ▶️ ⬅️ ↙️ ↘️ ➡️ ⬆️ ↖️ ↗️
- ⏬ ⏫ ⤵️ ⤴️ ↩️ ↪️ ↔️ ↕️ ⏪ ⏩ ℹ️
- ♿ ㊙️ ㊗️ Ⓜ️ ⛔ ✳️ ❇️ ✴️
- ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ⛎
- ❎ ♻️ ©️ ®️ ™️ ❌ ⁉️ ⭕ ✖️ ➕ ➖ ➗ ✔️
- ☑️ ➰ 〰️ 〽️ ▪️ ▫️ ◾ ◽ ◼️ ◻️ ⬛ ⬜ ✅ ⚫ ⚪
二、 公共点位弹泡
超图中提供的点位有时候不满足我们的点位样式需求,且难以做动画。我们可以使用自己熟悉的方式生成点位。
注意:大量数据不可使用此方法生成。性能较差。
效果图
使用方法:
- 使用类名控制样式、图标、动画
- callback:点击回调事件
- dataset:额外绑定数据,在实例上可以拿到
- 可以使用forEach循环去取数据
- css中解决了点击无法穿透问题
import SuperPopup from '@/utils/SuperPopup';
SuperMap3DLayer.commonPopup = new SuperPopup({
viewer: SuperMap3DLayer.viewer,
show: options.show,
classname: options.classname || '',
verticalOrigin: SuperMap3D.VerticalOrigin.BOTTOM,
position: SuperMap3D.Cartesian3.fromDegrees(options.center[0], options.center[1]),
pixelOffset: new SuperMap3D.Cartesian2(0, 6),
dataset: {
id: 1,
},
callback: (item) => {
console.log(item);
},
});
封装类的样式
.g-supermap-popup {
position: absolute;
color: #fff;
font-size: 14px;
width: 128px;
height: 216px;
display: flex;
&__1 {
.g-supermap-popup__content {
width: 44px;
height: 53px;
background: url('/static/screen/icon_point_1.png') 0 0 no-repeat;
position: relative;
z-index: 9999;
}
.g-supermap-popup__custom {
transform: translate(42px, 176px); // 仅可使用translate改变图标位置
}
}
// 点击事件穿透
&__event {
pointer-events: auto;
user-select: none;
cursor: pointer;
position: relative;
}
}
封装类:SuperPopup.ts
点击查看SuperPopup.ts
```typescript
let popupId = 1;
export default class SuperPopup {
private viewerIns: any;
private element: any;
private html: any;
private pixelOffset: SuperMap3D.Cartesian2;
private position: any;
private isShow: boolean;
private hideOnBehindGlobe: any;
private scaleByDistance: any;
private translucencyByDistance: any;
private distanceDisplayCondition: any;
private scratch: SuperMap3D.Cartesian2;
private RemoveCallback: () => void;
private uid: string;
private superPopupContainer: HTMLElement;
private label: any;
private dataset: any;
private callback: () => void;
constructor(opt) {
this.viewerIns = opt.viewer;
this.element = opt.element; // dom or id
this.callback = opt.callback || null;
this.dataset = opt.dataset;
this.uid = `g_popup_${++popupId}`;
this.html = opt.html;
this.label = opt.label;
this.position = opt.position; // Cartesian3
this.pixelOffset = opt.pixelOffset || new SuperMap3D.Cartesian2(0, 0); // 像素偏移
// eslint-disable-next-line no-underscore-dangle
this.isShow = opt.show || false;
this.hideOnBehindGlobe = opt.hideOnBehindGlobe || false; // 是否在地球背面隐藏
this.scaleByDistance = opt.scaleByDistance; // 距离控制大小
this.translucencyByDistance = opt.translucencyByDistance; // 距离控制透明度
this.distanceDisplayCondition = opt.distanceDisplayCondition; // 距离控制显隐
this.scratch = new SuperMap3D.Cartesian2();
this.RemoveCallback = function () {};
this.init(opt);
this.resize();
}
initContainer() {
this.superPopupContainer = document.getElementById('super_popup_container');
if (!this.superPopupContainer) {
this.superPopupContainer = document.createElement('div');
this.superPopupContainer.setAttribute('id', 'super_popup_container');
document.body.appendChild(this.superPopupContainer);
}
}
init(opt) {
// this.initContainer();
// 在Cesium容器中添加元素
let dom;
// 传入html时转为dom元素
if (this.html) {
const parent = document.createElement('div');
parent.innerHTML = opt.html;
dom = parent.firstChild;
}
if (typeof opt.element === 'string') {
this.element = document.getElementById(opt.element);
} else {
const ctx = document.createElement('div');
ctx.setAttribute('id', this.uid);
ctx.setAttribute('class', `g-supermap-popup ${opt.classname}`);
const div = document.createElement('div');
div.setAttribute('class', 'g-supermap-popup__custom');
const innerEvent = document.createElement('div');
innerEvent.setAttribute('class', 'g-supermap-popup__event');
const innerDiv = document.createElement('div');
innerDiv.setAttribute('class', 'g-supermap-popup__content');
let labelDiv = null;
if (this.label) {
labelDiv = document.createElement('div');
labelDiv.setAttribute('class', 'g-supermap-popup__label-wrap');
labelDiv.innerText = this.label;
}
const triDiv = document.createElement('div');
triDiv.setAttribute('class', 'tri');
if (this.label) innerDiv.appendChild(labelDiv);
div.appendChild(innerEvent);
innerEvent.appendChild(innerDiv);
innerEvent.appendChild(triDiv);
ctx.appendChild(div);
if (this.callback) {
innerEvent.addEventListener('click', () => this.callback(this.dataset));
}
dom = ctx;
}
if (!this.element) this.element = dom; // 获取元素优先级高于获取html
if (!this.viewerIns) {
console.log('Popup :viewer is required!');
return;
}
this.element.style.pointerEvents = 'none';
this.element.style.transformOrigin = 'left bottom 0px'; // 缩放中心点
this.viewerIns.container.appendChild(this.element);
this.setViewer();
if (this.isShow) {
if (this.position) {
setTimeout(() => {
this.setPosition(opt.position);
}, 500);
}
}
}
/**
* 设置关联的cesium viewer
* @param viewer
*/
setViewer() {
// 每一帧触发
// this.RemoveCallback = this.viewerIns.scene.preRender.addEventListener(function () {
// if (this._show) {
// this.update()
// }
// });
// 相机改变触发
this.RemoveCallback = this.viewerIns.camera.changed.addEventListener(() => {
if (this.isShow) {
this.update();
}
});
}
/**
* 获取关联的cesium viewer
* @return {SuperMap3D.Viewer}
*/
getViewer() {
return this.viewerIns;
}
/**
* 设置位置
* @param position{Array}
*/
setPosition(position) {
if (!position) {
this.close();
return;
}
if (!this.getViewer()) {
return;
}
const canvasPosition = this.getViewer().scene.cartesianToCanvasCoordinates(position, this.scratch); // 笛卡尔坐标到画布坐标
if (SuperMap3D.defined(canvasPosition)) {
this.element.style.top = `${canvasPosition.y + this.pixelOffset.y - this.element.offsetHeight}px`;
this.element.style.left = `${canvasPosition.x + this.pixelOffset.x - this.element.offsetWidth / 2}px`;
// this.element.style.transform = `matrix(1, 0, 0, 1, ${canvasPosition.x + this.pixelOffset.x}, ${canvasPosition.y + this.pixelOffset.y})`;
this.element.style.opacity = 1;
this.isShow = true;
if (
this.hideOnBehindGlobe ||
this.distanceDisplayCondition ||
this.translucencyByDistance ||
this.scaleByDistance
) {
const cameraPosition = this.getViewer().camera.position;
const distance = SuperMap3D.Cartesian3.distance(cameraPosition, position);
if (this.hideOnBehindGlobe) {
let { height } = this.getViewer().scene.globe.ellipsoid.cartesianToCartographic(cameraPosition);
height += this.getViewer().scene.globe.ellipsoid.maximumRadius;
if (!(distance > height)) {
this.element.style.display = 'flex';
} else {
this.element.style.display = 'none';
}
}
if (this.distanceDisplayCondition) {
if (distance < this.distanceDisplayCondition.near || distance > this.distanceDisplayCondition.far) {
this.element.style.opacity = 0;
return;
}
this.element.style.opacity = 1;
}
if (this.translucencyByDistance) {
if (distance < this.translucencyByDistance.near) {
this.element.style.opacity = this.translucencyByDistance.nearValue;
} else if (distance > this.translucencyByDistance.far) {
this.element.style.opacity = this.translucencyByDistance.farValue;
} else {
const val1 = this.translucencyByDistance.farValue - this.translucencyByDistance.nearValue;
const val2 = this.translucencyByDistance.far - this.translucencyByDistance.near;
const val3 =
((distance - this.translucencyByDistance.near) / val2) * val1 + this.translucencyByDistance.nearValue;
this.element.style.opacity = val3;
}
}
if (this.scaleByDistance) {
if (distance < this.scaleByDistance.near) {
const val = this.scaleByDistance.nearValue;
this.element.style.transform = `scale(${val}, ${val})`;
} else if (distance > this.scaleByDistance.far) {
const val = this.scaleByDistance.farValue;
this.element.style.transform = `scale(${val}, ${val})`;
} else {
const val1 = this.scaleByDistance.farValue - this.scaleByDistance.nearValue;
const val2 = this.scaleByDistance.far - this.scaleByDistance.near;
const val3 = ((distance - this.scaleByDistance.near) / val2) * val1 + this.scaleByDistance.nearValue;
this.element.style.transform = `scale(${val3}, ${val3})`;
}
}
}
}
this.position = position;
}
// 当窗口大小改变时候重新计算popup的位置
resize() {
window.addEventListener('resize', () => {
this.setPosition(this.position);
});
}
update() {
this.setPosition(this.position);
}
getPosition() {
return this.position;
}
close() {
this.element.style.opacity = 0;
this.isShow = false;
}
show() {
if (this.position) {
this.element.style.opacity = 1;
this.isShow = true;
this.setPosition(this.position);
}
}
hide() {
if (this.position) {
this.element.style.opacity = 0;
this.isShow = false;
this.setPosition(this.position);
}
}
destroy() {
this.RemoveCallback();
this.close();
this.viewerIns.container?.removeChild(this.element);
}
}
```