精灵图像实体
SpriteImagesEntity 是由 实体Entity 和 SpriteImagesModule 模块组合而成的新的实体。
SpriteImagesEntity = Entity + SpriteImagesModule
SpriteImagesModule 中引用的是 SpriteImages 对象
常用方法
SpriteImagesEntity 是由 实体Entity 派生而来。具体 Entity 的所有属性和方法。同时也具有SpriteImagesModule 的相关方法。通过 SpriteImages 对象 可访问 SpriteImages 类的所有方法
| 方法 | 描述 |
|---|---|
| SpriteImages | 获取精灵图像对象 |
| getData | 获取数据 |
| setData | 设置数据。异步(返回 Promise<void>,内部先加载图标图片)——需要紧接着操作新精灵(如 setItemHighlight)时先 await |
| setItemHighlight | 设置某项高亮:setItemHighlight(index, isHighlight),index 为数据下标(不是 id)。⚠️ 该数据项须设置了 highlightIcon 或 highlightOpacity > 0,否则没有高亮材质、调用静默无效 |
| update | 更新数据 |
| getOptions | 获取选项 |
使用示例
创建SpriteImagesEntity
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 data = [];
for(let i = 0; i < 20; i++) {
for(let j = 0; j < 20; j++) {
data.push({
position: [i * 5 - 50, 0, j * 5 - 50],
icon: env.assetsPath + `image/sensor${(i % 5) + 1}.png`,
highlightOpacity: 0.6,
id: j * 20 + i
});
}
}
let spriteImagesEnt = new vjmap3d.SpriteImagesEntity({
data: data,
sizeAttenuation: false,
allowOverlap: false,
});
spriteImagesEnt.addTo(app);
增加事件
spriteImagesEnt.pointerEvents = true
spriteImagesEnt.on("mouseover", e => {
let index = e?.intersection?.object?.userData.objectDataIndex
if (index !== undefined) {
spriteImagesEnt.setItemHighlight(index, true);
app.popup2d.show();
app.popup2d.setOffset([0, -40]);
app.popup2d.setHTML(`<span style="color:red">ID:${data[index].id}</span>`)
app.popup2d.setPosition(data[index].position)
}
})
spriteImagesEnt.on("mouseout", e => {
let index = e?.intersection?.object?.userData.objectDataIndex
if (index !== undefined) {
spriteImagesEnt.setItemHighlight(index, false)
app.popup2d.hide()
}
})
spriteImagesEnt.on("click", e => {
let index = e?.intersection?.object?.userData.objectDataIndex
if (index !== undefined) {
app.logInfo(`您点击了ID:${data[index].id}`)
}
})
修改、新增、删除
调用 setData 来对数据进行增删改
// 如新增一条
data.push({
position: vjmap3d.randPoint3D(),
icon: env.assetsPath + `image/sensor${vjmap3d.randInt(1, 5)}.png`,
highlightOpacity: 0.6,
id: data.length + 1
})
spriteImagesEnt.setData(data)
设置是否允许重叠
调用 getOptions 来获取属性,update更新数据
spriteImagesEnt.getOptions().allowOverlap = true;
spriteImagesEnt.update(); // 更新
设置透明度随相机距离大小消退距离
调用 getOptions 来获取属性,update更新数据
spriteImagesEnt.getOptions().fadeDistance = 100; // 距相机距离
spriteImagesEnt.update(); // 更新
⚠️ webgl 引擎下
fadeDistance在图片材质首次编译时写进着色器,而材质按"图标+尺寸+旋转+透明度"缓存复用,update()不会让已渲染过的材质重新编译——运行时改fadeDistance后update()对已显示的图片基本不生效。最好在构造时设定;运行时要改,先await spriteImagesEnt.setData([])(释放缓存材质)再await spriteImagesEnt.setData(data)重建。
示例
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 data = [];
for(let i = 0; i < 20; i++) {
for(let j = 0; j < 20; j++) {
data.push({
position: [i * 5 - 50, 0, j * 5 - 50],
icon: env.assetsPath + `image/sensor${(i % 5) + 1}.png`,
highlightOpacity: 0.6,
id: j * 20 + i
});
}
}
let spriteImagesEnt = new vjmap3d.SpriteImagesEntity({
data: data,
sizeAttenuation: false,
allowOverlap: false,
});
spriteImagesEnt.addTo(app);
//
spriteImagesEnt.pointerEvents = true
spriteImagesEnt.on("mouseover", e => {
let index = e?.intersection?.object?.userData.objectDataIndex
if (index !== undefined) {
spriteImagesEnt.setItemHighlight(index, true);
app.popup2d.show();
app.popup2d.setOffset([0, -40]);
app.popup2d.setHTML(`ID:${data[index].id}`)
app.popup2d.setPosition(data[index].position)
}
})
spriteImagesEnt.on("mouseout", e => {
let index = e?.intersection?.object?.userData.objectDataIndex
if (index !== undefined) {
spriteImagesEnt.setItemHighlight(index, false)
app.popup2d.hide()
}
})
spriteImagesEnt.on("click", e => {
let index = e?.intersection?.object?.userData.objectDataIndex
if (index !== undefined) {
app.logInfo(`您点击了ID:${data[index].id}`)
}
})
const ui = await app.getConfigPane({ title: "设置", style: { width: "250px", overflow: "hidden"}});
let cfg = [
{
type: 'checkbox',
label: '允许重叠',
property: [spriteImagesEnt.getOptions(), "allowOverlap"],
onChange: () => {
spriteImagesEnt.update()
}
},
{
type: 'slider',
label: '消退距离',
bounds: [0, 5000],
stepSize: 1,
getValue: () => spriteImagesEnt.getOptions().fadeDistance ?? 0,
setValue: async (v) => {
spriteImagesEnt.getOptions().fadeDistance = v;
// webgl 下缓存材质不会重编译,update() 不够,需清空重建
await spriteImagesEnt.setData([])
await spriteImagesEnt.setData(data)
}
},
{
type: 'button',
label: '再增加一个',
value: ()=> {
data.push({
position: vjmap3d.randPoint3D(),
icon: env.assetsPath + `image/sensor${vjmap3d.randInt(1, 5)}.png`,
highlightOpacity: 0.6,
id: data.length + 1
})
spriteImagesEnt.setData(data)
}
},
{
type: 'button',
label: '修改第一个图标',
value: ()=> {
if (data.length > 0) {
let icon = env.assetsPath + `image/sensor${vjmap3d.randInt(1, 5)}.png`
data[0].icon = icon;
data[0].highlightIcon = icon;
}
spriteImagesEnt.setData(data)
}
},
{
type: 'button',
label: '删除第一个',
value: ()=> {
if (data.length == 0) {
return
}
data.splice(0, 1)
spriteImagesEnt.setData(data)
}
}
]
cfg.forEach(c => ui.appendChild(c));