实体常用模块
事件模块EventModule
事件模块EventModule主要用来响应实体的hover和click事件。
增加事件模块
// 增加一个事件模块,用来高亮提示
entity.add(vjmap3d.EventModule, {
clickHighlight: true,
highlightOpacity: 0.2,
hoverSelect: true,
hoverHtmlText: "我是MeshEntity",
popupOptions: {
anchor: "bottom"
},
clickCallback: (ent, isClick) => {
if (!isClick) return;
app.logInfo(`您点击了我`)
}
});
移除事件模块
entity.removeModule(vjmap3d.EventModule);
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
render: { // 渲染参数
alpha: true,
antialias: true
},
scene: { // 场景设置
gridHelper: { visible: true } // 是否显示坐标网格
}
})
//
let box = new THREE.BoxGeometry(2, 2, 2)
const material = new THREE.MeshStandardMaterial({
color: "#0f0",
side: THREE.DoubleSide
});
let mesh = new THREE.Mesh(box, material);
let entity = vjmap3d.Entity.fromObject3d(mesh);
entity.addTo(app);
// 增加一个事件模块,用来高亮提示
entity.add(vjmap3d.EventModule, {
clickHighlight: true,
highlightOpacity: 0.2,
hoverSelect: true,
hoverHtmlText: "我是MeshEntity",
popupOptions: {
anchor: "bottom"
},
clickCallback: (ent, isClick) => {
if (!isClick) return;
app.logInfo(`您点击了我`)
}
});
let control = new vjmap3d.ButtonGroupControl({
buttons: [
{
id: "id1",
html: "移除事件模块",
title: "移除事件模块",
style: {
width: "130px"
},
onclick: async () => {
entity.removeModule(vjmap3d.EventModule);
app.logInfo(`移除事件后,将不会响应事件`)
}
}
]
});
app.addControl(control, "top-right");
动画模块AnimatorModule
动画模块AnimatorModule主要用来对实体进行动画操作。
加载有动画的模型做为实体对象时,会自动给实体添加动画模块AnimatorModule。
let ent = await vjmap3d.ResManager.loadModel(vjmap3d.ResManager.svrUrl("models/Stork.glb"), {
splitSubEntity: true,
scale: 0.1,
anchor: "front-bottom-right"
});
ent.addTo(app);
let mod = ent.getModule(vjmap3d.AnimatorModule);
if (mod) {
let animator = mod.getAnimator();
animator.play(0) // 开启动画
// animator.stop(0) // 停止动画
}
⚠️
Animator实例上isLoop()/setPosition(time)/removeClip/playAnimation均为undefined(d.ts 声明存在但运行时没有——removeClip宿主是另一个Animation内部类、playAnimation宿主是SpriteAnimatorEntity,都不在Animator)——可用的剪辑/循环控制是addAnimationClip(clip)→AnimationClip/getAnimationClips()/setLoop/reset/stopAllAction/setTime/play(idx),信号袋只有signal.onLoop/signal.onFinished。另外new Animator(options)的options.object必填(Object3D/Entity),空 options 会抛Cannot read properties of undefined (reading 'isEntity')。
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
control:{
initState: { // 相机初始位置
cameraTarget: new THREE.Vector3(-15, 0, -10),
cameraPosition: new THREE.Vector3(-30, 30, -10)
}
},
ui: {
configPane: {
title: "设置",
style: { width: "240px", overflow: "hidden"}
}
}
})
let ent = await vjmap3d.ResManager.loadModel(vjmap3d.ResManager.svrUrl("models/Stork.glb"), {
splitSubEntity: true,
scale: 0.1,
anchor: "front-bottom-right"
});
ent.addTo(app);
let mod = ent.getModule(vjmap3d.AnimatorModule);
if (mod) {
let animator = mod.getAnimator();
animator.play(0) // 开启动画
// animator.stop(0) // 停止动画
}
增加新的动画
如:增加一个闪烁动画
let mod = ent.add(vjmap3d.AnimatorModule);
let animator = mod.getAnimator();
let clip = animator.addVisibilityAnimation();
animator.play(clip);
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
scene: { // 场景设置
gridHelper: { visible: true } // 是否显示坐标网格
}
})
//
let box = new THREE.BoxGeometry(2, 2, 2)
const material = new THREE.MeshStandardMaterial({
color: "#0f0",
side: THREE.DoubleSide
});
let mesh = new THREE.Mesh(box, material);
let entity = vjmap3d.Entity.fromObject3d(mesh);
entity.addTo(app);
let mod = entity.add(vjmap3d.AnimatorModule);
let animator = mod.getAnimator();
let clip = animator.addVisibilityAnimation();
animator.play(clip);
路径动画模块PathAnimateModule
路径动画模块PathAnimateModule是实体沿指定路径行走的动画模块。
let pathAnmiMod = ent.add(vjmap3d.PathAnimateModule)
pathAnmiMod.start({
paths: line.data.coordinates,
cameraFollow: true,
animation: {
duration: 10000,
yoyoForever: true
},
startAimatorClipName: 'Walk',
stopAimatorClipName: ""
})
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
scene: { // 场景设置
gridHelper: { visible: true } // 是否显示坐标网格
}
})
let ent = await vjmap3d.ResManager.loadModel(env.assetsPath + "models/soldier.glb", {
splitSubEntity: true
});
app.logInfo("请在图上绘制一条要行走的路径线,双击结束", 60000)
let line = await app.actionDrawLineSting({
isAddToApp: true
});
if (line.isCancel) return
ent.addTo(app);
let pathAnmiMod = ent.add(vjmap3d.PathAnimateModule)
pathAnmiMod.start({
paths: line.data.coordinates,
cameraFollow: true,
animation: {
duration: 10000,
yoyoForever: true
},
startAimatorClipName: 'Walk',
stopAimatorClipName: ""
})
let miniMapControl = true; // 是否显示小地图
if (miniMapControl) {
let miniMapControl = new vjmap3d.MiniMapControl({
followTarget: ent.node,
// mapSyncRotateZ: true,
mapSize: 10,
});
app.addControl(miniMapControl)
}
每段路径设置不同动画和速度
let pathSegs = [
{
point: [0,0,0]
},
{
point: [10,0,10],
time: 1000
},
{
point: [10, 0, 20],
time: 2000
},
{
point: [20, 0, 20],
time: 1000
},
{
point: [20, 0, 10],
time: 3000
},
{
point: [10, 0, 10],
time: 2000
}
]
let pathAnmiMod = ent.add(vjmap3d.PathAnimateModule)
for(let n = 1; n < pathSegs.length; n++) {
await pathAnmiMod.start({
paths: [pathSegs[n - 1].point, pathSegs[n].point],
animation: {
// @ts-ignore
duration: pathSegs[n].time
},
cameraFollow: true,
startAimatorClipName: 'Walk',
stopAimatorClipName: n == pathSegs.length - 1 ? "" : "Walk"
})
}
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
container: "map", // 容器id
scene: { // 场景设置
gridHelper: { visible: true } // 是否显示坐标网格
}
})
let ent = await vjmap3d.ResManager.loadModel(env.assetsPath + "models/soldier.glb", {
splitSubEntity: true
});
ent.addTo(app);
let pathSegs = [
{
point: [0,0,0]
},
{
point: [10,0,10],
time: 1000
},
{
point: [10, 0, 20],
time: 2000
},
{
point: [20, 0, 20],
time: 1000
},
{
point: [20, 0, 10],
time: 3000
},
{
point: [10, 0, 10],
time: 2000
}
]
//
let pathAnmiMod = ent.add(vjmap3d.PathAnimateModule)
for(let n = 1; n < pathSegs.length; n++) {
await pathAnmiMod.start({
paths: [pathSegs[n - 1].point, pathSegs[n].point],
animation: {
// @ts-ignore
duration: pathSegs[n].time
},
cameraFollow: true,
startAimatorClipName: 'Walk',
stopAimatorClipName: n == pathSegs.length - 1 ? "" : "Walk"
})
}