Marker3D标记
Marker3D是基于threejs中 CSS3DObject 实现的div标记。
常用方法
| 方法 | 描述 |
|---|---|
| isShow | 是否显示 |
| show | 显示 |
| hide | 隐藏 |
| getElement | 获取元素对象 |
| updateSize | 更新大小 |
| getPosition | 获取位置 |
| setPosition | 设置位置 |
| updatePopupPosition | 更新弹出框信息窗口位置 |
| addTo | 增加至应用或实体中 |
| isCss3dSprite | 是否为Css3dSprite |
| togglePopup | 切换弹出信息框显示或隐藏 |
| setPopup | 设置弹出信息框 |
| getOpacity | 获取透明度 |
| setOpacity | 设置透明度 |
| remove | 移除 |
| setAnimation | 设置动画 |
| setCursor | 设置光标 |
信号名
| 方法 | 描述 |
|---|---|
| click | 点击 |
| occlusion | 遮挡状态变化,回调参数 {object, occlusion}。⚠️ 只有构造选项 occlusionOpacity < 1(默认 1)时才做遮挡检测,否则永不触发;被遮挡时只把透明度设为 occlusionOpacity,元素不隐藏 |
| elementSizeReady | 元素大小已就绪。⚠️ 同时给了 pixelWidth 和 pixelHeight 时在构造函数内同步派发,new 之后再 .add 的监听收不到;否则在挂载后由 ResizeObserver 量到尺寸时异步派发 |
| onAdd | 增加 |
| onRemove | 移除 |
对于div的事件,可以通过getElement获取div元素,对此div增加事件。如
marker3d.getElement().addEventListener("dblclick", event => {
console.log("双击")
});
⚠️
isHide: true不是 addTo 同步生效:isHide在内部ResizeObserver回调的setTimeout(...,10ms)里才被应用——addTo(app)后立即isShow()仍返回true,要等元素完成一次尺寸测量(约 10ms+ 之后)才会变false。不要在 addTo 后立刻根据isShow()判断初始隐藏是否生效。⚠️ 另外(headless/无布局环境):若
ResizeObserver回调始终不触发(如 headless Chrome 无布局刷新),isShow()可恒为 true——等待翻false的轮询必须有超时上限,不能假定它一定会翻。
用法示例
创建一个marker3D
let marker3d = new vjmap3d.Marker3D({
color: vjmap3d.randHtmlColor(),
width: 1
});
marker3d.setPosition([2, 0, 1]);
marker3d.addTo(app);
事件
marker3d.signal.click.add(() => {
app.logInfo("click");
});
marker3d.signal.occlusion.add(() => { // 需构造时设 occlusionOpacity < 1 才会触发
app.logInfo("occlusion");
});
marker3d.signal.elementSizeReady.add(() => {
app.logInfo("elementSizeReady");
});
marker3d.signal.onAdd.add(() => {
app.logInfo("onAdd");
});
marker3d.signal.onRemove.add(() => {
app.logInfo("onRemove");
});
marker3d.getElement().addEventListener("contextmenu", event => {
// @ts-ignore
if (event.button != 2) return;//不是右键
// 阻止地图默认右键菜单触发
event.preventDefault();
event.stopPropagation();
new vjmap3d.ContextMenu({
event: event,
theme: "dark", //light
width: "250px",
items: [
{type: 'custom', markup: `<span style="color: #ffff00; padding-left: 30px">我是标注Marker的右键菜单</span>`},
{
label: '删除Marker',
onClick: () => {
marker3d.remove()
}
}
]
});
})
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
stat: { show: true, left: "0" },
scene: {
gridHelper: { visible: true } // 是否显示坐标网格
},
camera: { // 相机设置
viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
}
})
let marker3d = new vjmap3d.Marker3D({
color: vjmap3d.randHtmlColor(),
width: 1
});
marker3d.setPosition([2, 0, 1]);
marker3d.addTo(app);
marker3d.signal.click.add(() => {
app.logInfo("click");
});
marker3d.signal.occlusion.add(() => { // 需构造时设 occlusionOpacity < 1 才会触发
app.logInfo("occlusion");
});
marker3d.signal.elementSizeReady.add(() => {
app.logInfo("elementSizeReady");
});
marker3d.signal.onAdd.add(() => {
app.logInfo("onAdd");
});
marker3d.signal.onRemove.add(() => {
app.logInfo("onRemove");
});
marker3d.getElement().addEventListener("contextmenu", event => {
// @ts-ignore
if (event.button != 2) return;//不是右键
// 阻止地图默认右键菜单触发
event.preventDefault();
event.stopPropagation();
new vjmap3d.ContextMenu({
event: event,
theme: "dark", //light
width: "250px",
items: [
{type: 'custom', markup: `<span style="color: #ffff00; padding-left: 30px">我是标注Marker的右键菜单</span>`},
{
label: '删除Marker',
onClick: () => {
marker3d.remove()
}
}
]
});
})
关联信息提示框
for (let i = 0; i < 100; i++) {
let marker3d = new vjmap3d.Marker3D({
color: vjmap3d.randHtmlColor(),
asSprite: true,
width: 1
});
marker3d.setPosition(vjmap3d.toVector3(vjmap3d.randPoint3D()));
marker3d.addTo(app);
marker3d.setPopup(
new vjmap3d.Popup2D({
backgroundColor: "#A0FFA0",
buttonColor: "#f00",
closeOnClick: true,
closeButton: true
}).setHTML(`index${i + 1}`)
);
// marker3d.togglePopup();
}
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
stat: { show: true, left: "0" },
scene: {
gridHelper: { visible: true } // 是否显示坐标网格
},
camera: { // 相机设置
viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
}
})
for (let i = 0; i < 100; i++) {
let marker3d = new vjmap3d.Marker3D({
color: vjmap3d.randHtmlColor(),
asSprite: true,
width: 1
});
marker3d.setPosition(vjmap3d.toVector3(vjmap3d.randPoint3D()));
marker3d.addTo(app);
marker3d.setPopup(
new vjmap3d.Popup2D({
backgroundColor: "#A0FFA0",
buttonColor: "#f00",
closeOnClick: true,
closeButton: true
}).setHTML(`index${i + 1}`)
);
// marker3d.togglePopup();
}
遮挡时设置透明度
let box = new THREE.BoxGeometry(2, 2, 2)
const material = new THREE.MeshStandardMaterial({
color: '#0ff'
});
let mesh = new THREE.Mesh(box, material);
mesh.position.set(0, 0, 0)
app.scene.add(mesh);
//
let marker3d = new vjmap3d.Marker3D({
color: "#f00",
width: 1,
occlusionOpacity: 0.2 // 遮挡时透明度
});
marker3d.setPosition([0, -1, -1.5]);
marker3d.addTo(app);
marker3d.signal.occlusion.add(e => {
if (e.occlusion) {
app.logInfo("被遮挡", "warn");
} else {
app.logInfo("没被遮挡", "success");
}
});
app.signal.onAppAfterRender.add(t => {
app.cameraControl.azimuthAngle += 20 * t.deltaTime * THREE.MathUtils.DEG2RAD;
})
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
stat: { show: true, left: "0" },
scene: {
gridHelper: { visible: true } // 是否显示坐标网格
},
camera: { // 相机设置
viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
}
})
let box = new THREE.BoxGeometry(2, 2, 2)
const material = new THREE.MeshStandardMaterial({
color: '#0ff'
});
let mesh = new THREE.Mesh(box, material);
mesh.position.set(0, 0, 0)
app.scene.add(mesh);
//
let marker3d = new vjmap3d.Marker3D({
color: "#f00",
width: 1,
occlusionOpacity:0.2 // 遮挡时透明度
});
marker3d.setPosition([0, -1, -1.5]);
marker3d.addTo(app);
marker3d.signal.occlusion.add(e => {
if (e.occlusion) {
app.logInfo("被遮挡", "warn");
} else {
app.logInfo("没被遮挡", "success");
}
});
app.signal.onAppAfterRender.add(t => {
app.cameraControl.azimuthAngle += 20 * t.deltaTime * THREE.MathUtils.DEG2RAD;
})
动画Marker
let marker3d = new vjmap3d.Marker3D({
color: vjmap3d.randHtmlColor(),
width: 1,
});
marker3d.setPosition(vjmap3d.toVector3(vjmap3d.toVector3(vjmap3d.randPoint3D({maxX: 5, maxY: 2, maxZ: 5, minX: -5, minY: -2, minZ: -5}))))
marker3d.addTo(app);
marker3d.setAnimation("MAP_ANIMATION_BOUNCE");
RotatingTextBorderMarker3d
// 创建一个缺省的
let markerEle = new vjmap3d.RotatingTextBorderMarker(
{
position: vjmap3d.randPoint3D({maxX: 5, maxY: 2, maxZ: 5, minX: -5, minY: -2, minZ: -5}),
text: "3D地图"
},
{}
);
let marker3d = markerEle.createMarker3d({
pixelWidth: 120,
pixelHeight: 50,
width: 5,
asSprite: true
});
marker3d.addTo(app);
BreathingApertureMarker3D
// 创建一个缺省的
let markerEle = new vjmap3d.BreathingApertureMarker(
{
position: vjmap3d.randPoint3D({maxX: 5, maxY: 2, maxZ: 5, minX: -5, minY: -2, minZ: -5}),
text: "3D地图"
},
{
textColor: vjmap3d.randHtmlColor()
}
);
let marker3d = markerEle.createMarker3d({
pixelWidth: 120,
pixelHeight: 50,
width: 5,
asSprite: true
});
marker3d.addTo(app);
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
stat: { show: true, left: "0" },
scene: {
gridHelper: { visible: true } // 是否显示坐标网格
},
camera: { // 相机设置
viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
}
})
const ui = await app.getConfigPane({ title: "Marker", style: { width: "250px"}});
let gui = new vjmap3d.UiPanelJsonConfig();
gui.addButton("动画Marker", async () => {
let marker3d = new vjmap3d.Marker3D({
color: vjmap3d.randHtmlColor(),
width: 1,
});
marker3d.setPosition(vjmap3d.toVector3(vjmap3d.toVector3(vjmap3d.randPoint3D({maxX: 5, maxY: 2, maxZ: 5, minX: -5, minY: -2, minZ: -5}))))
marker3d.addTo(app);
marker3d.setAnimation("MAP_ANIMATION_BOUNCE");
});
gui.addButton("RotatingTextBorderMarker3d", async () => {
// 创建一个缺省的
let markerEle = new vjmap3d.RotatingTextBorderMarker(
{
position: vjmap3d.randPoint3D({maxX: 5, maxY: 2, maxZ: 5, minX: -5, minY: -2, minZ: -5}),
text: "3D地图"
},
{}
);
let marker3d = markerEle.createMarker3d({
pixelWidth: 120,
pixelHeight: 50,
width: 5,
asSprite: true
});
marker3d.addTo(app);
});
gui.addButton("BreathingApertureMarker", async () => {
// 创建一个缺省的
let markerEle = new vjmap3d.BreathingApertureMarker(
{
position: vjmap3d.randPoint3D({maxX: 5, maxY: 2, maxZ: 5, minX: -5, minY: -2, minZ: -5}),
text: "3D地图"
},
{
textColor: vjmap3d.randHtmlColor()
}
);
let marker3d = markerEle.createMarker3d({
pixelWidth: 120,
pixelHeight: 50,
width: 5,
asSprite: true
});
marker3d.addTo(app);
});
gui.toJson().forEach(c => ui.appendChild(c));