唯杰地图 logo唯杰地图
VJMAP
EN

精灵图像实体

vjmap3d/references/entity/spriteImagesEntity.md 8.8 KB235 行
原文

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));