# 符号实体

 `SymbolEntity` 是由 实体`Entity` 和 `SymbolModule` 模块组合而成的新的实体。

 [SymbolEntity](https://vjmap.com/map3d/api/classes/SymbolEntity.html) =  [Entity](https://vjmap.com/map3d/api/classes/Entity.html) + [SymbolModule](https://vjmap.com/map3d/api/classes/SymbolModule.html) 

 ## 常用方法


 `SymbolEntity` 是由 实体`Entity` 派生而来。具体 [Entity](https://vjmap.com/map3d/api/classes/Entity.html) 的所有属性和方法。同时也具有[SymbolModule](https://vjmap.com/map3d/api/classes/SymbolModule.html)  的相关方法。


|方法|描述|
|:---|:---|
|[symbolObject](https://vjmap.com/map3d/api/classes/SymbolEntity.html#symbolObject)|获取符号对象。webgl 下是 `THREE.Points`（`pixelRaycasting: true` 时为其子类）；**webgpu 下是 `SymbolSprites`（继承 `THREE.Sprite`，点几何在 `.pointsGeometry` 上）**——`.d.ts` 一律标为 `Points`，跨引擎代码勿直接访问 `.geometry` 的点属性|
|[updateStyle](https://vjmap.com/map3d/api/classes/SymbolEntity.html#updateStyle)|更新样式|
|[setData](https://vjmap.com/map3d/api/classes/SymbolEntity.html#setData)|修改数据|
|[getData](https://vjmap.com/map3d/api/classes/SymbolEntity.html#getData)|获取数据|
|[getItemDataByPointIndex](https://vjmap.com/map3d/api/classes/SymbolEntity.html#getItemDataByPointIndex)|通过pointIndex获取获取数据|

    
## 使用示例


### 创建SymbolEntity
```js
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let data = [];
data.push({
    position: [-2, 3, 4],
    color: "#0ff",
    borderColor: "#ff0",
    size: 20
})
data.push({
    position: [2, 4, 3],
    color: "#0f0",
    borderColor: "#ff0",
    size: 25
})
let symbol = new vjmap3d.SymbolEntity({ //SymbolEntity
    data: data,
    pixelRaycasting: true, // 像素大小拾取
    style: {
        shape: "circle",
        transparent: true,
        //fadeDistance: 500,
        borderWidth: 2,
        sizeAttenuation: false
    }
})
symbol.addTo(app);
symbol.symbolObject.userData.RaycasterThreshold = 15; // 可设置像素捕捉的距离，默认为6
```

### 增加事件
```js
symbol.pointerEvents = true;
symbol.on("mouseover", e => {
    if (e.intersection.index >= 0) {
        let pointsData = symbol.getData();
        app.setCursor("pointer");
        pointsData[e.intersection.index].highlightColor = "#f00";
        pointsData[e.intersection.index].highlightSize =
            (pointsData[e.intersection.index].size ?? 3) + 5;
        symbol.setData(pointsData)
        app.popup2d.setText(`id: ${pointsData[e.intersection.index].id}`)
        app.popup2d.setPosition(pointsData[e.intersection.index].position)
        app.popup2d.show();
    }
});
symbol.on("mouseout", e => {
    if (e.intersection.index >= 0) {
        app.setCursor("");
        // 取消高亮
        let pointsData = symbol.getData();
        delete pointsData[e.intersection.index].highlightColor;
        delete pointsData[e.intersection.index].highlightSize;
        symbol.setData(pointsData)
        app.popup2d.hide();
    }
});
```

### 修改、新增、删除
调用 [setData](https://vjmap.com/map3d/api/classes/SymbolEntity.html#setData) 来对数据进行增删改
```js
// 如新增一条
data.push({
    position: vjmap3d.randPoint3D(),
    color: vjmap3d.randColor(),
    borderColor: vjmap3d.randColor(),
    size: vjmap3d.randInt(10, 20)
})
symbol.setData(data)
```


### 修改样式
```js
// 获取模块对象
let mod = symbol.getModule(vjmap3d.SymbolModule);
mod.style.shape = "triangle"; // 设置为三角形形状
symbol.updateStyle(mod.style)
```


### 3D示例
<mapFrame>
<pre>
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let data = [];
data.push({
    position: [-2, 3, 4],
    color: "#0ff",
    borderColor: "#ff0",
    size: 20
})
data.push({
    position: [2, 4, 3],
    color: "#0f0",
    borderColor: "#ff0",
    size: 25
})
let symbol = new vjmap3d.SymbolEntity({ //SymbolEntity
    data: data,
    pixelRaycasting: true, // 像素大小拾取
    style: {
        shape: "circle",
        transparent: true,
        //fadeDistance: 500,
        borderWidth: 2,
        sizeAttenuation: false
    }
})
symbol.addTo(app);
symbol.symbolObject.userData.RaycasterThreshold = 15; // 可设置像素捕捉的距离，默认为6
// 允许事件
symbol.pointerEvents = true;
symbol.on("mouseover", e => {
    if (e.intersection.index >= 0) {
        let pointsData = symbol.getData();
        app.setCursor("pointer");
        pointsData[e.intersection.index].highlightColor = "#f00";
        pointsData[e.intersection.index].highlightSize =
            (pointsData[e.intersection.index].size ?? 3) + 5;
        symbol.setData(pointsData)
        app.popup2d.setText(`id: ${pointsData[e.intersection.index].id}`)
        app.popup2d.setPosition(pointsData[e.intersection.index].position)
        // app.popup2d.setPosition(e?.intersection?.point, true)
        app.popup2d.show();
    }
});
symbol.on("mouseout", e => {
    if (e.intersection.index >= 0) {
        app.setCursor("");
        // 取消高亮
        let pointsData = symbol.getData();
        delete pointsData[e.intersection.index].highlightColor;
        delete pointsData[e.intersection.index].highlightSize;
        symbol.setData(pointsData)
        app.popup2d.hide();
    }
});
//
let mod = symbol.getModule(vjmap3d.SymbolModule);
const ui = await app.getConfigPane({ title: "设置", style: { width: "250px", overflow: "hidden"}});
let cfg = [
    {
        type: 'button',
        label: '增加一个点符号',
        value: ()=> {
            data.push({
                position: vjmap3d.randPoint3D(),
                color: vjmap3d.randColor(),
                borderColor: vjmap3d.randColor(),
                size: vjmap3d.randInt(10, 20)
            })
            symbol.setData(data)
        }
    },
    {
        type: 'button',
        label: '修改第一个符号颜色',
        value: ()=> {
            if (data.length > 0) {
                data[0].color = vjmap3d.randColor()
            }
            symbol.setData(data)
        }
    },
    {
        type: 'button',
        label: '删除第一个符号',
        value: ()=> {
            if (data.length == 0) {
                return
            }
            data.splice(0, 1)
            symbol.setData(data)
        }
    },
    {
        type: 'dropdown',
        label: '形状',
        property: [mod.style, 'shape'],
        children: [
            {
                label: "正方形",
                value: "square",
            },
            {
                label: "圆",
                value: "circle",
            },
            {
                label: "三角形",
                value: "triangle",
            }
        ],
        onChange: () => {
            symbol.updateStyle(mod.style)
        }
    }
]
cfg.forEach(c => ui.appendChild(c));
</pre>
</mapFrame>
