唯杰地图 logo唯杰地图
VJMAP
EN

拉伸实体

vjmap3d/references/entity/fillExtrusionsEntity.md 15.8 KB417 行
原文

FillExtrusionsEntity 是由 实体Entity 和 FillExtrusionsModule 模块组合而成的新的实体。

FillExtrusionsEntity = Entity + FillExtrusionsModule

常用方法

FillExtrusionsEntity 是由 实体Entity 派生而来。具体 Entity 的所有属性和方法。同时也具有FillExtrusionsModule 的相关方法。

方法 描述
getFillExtrusions 获取拉伸对象
getBorderPolyline 获取拉伸边框对象
setDepths 设置每项的拉伸后的深度、颜色、透明度值:setDepths([{index, depth?, color2?, opacity?}])。⚠️ 实际只有 depth 生效,且是顶面的绝对坐标值(不是相对 baseHeight 的高度);color2/opacity 被写到 attribute 对象而非 .array 上,无效果;带 baseHeight 的项底面顶点也被当成顶面一起改,调用后会压扁。要改颜色/透明度用 setData
getVertexSymbol 获取顶点对象
isShowVertex 是否显示顶点
getVertexData 获取顶点数据
setShowVertex 设置是否显示顶点
getBorderPolyline 获取拉伸边框对象
updateStyle 设置样式 —— updateStyle(style: MeshBasicMaterialParameters),必须传样式参数(不是无参"刷新"方法)
updateHightStyle 设置高亮样式 —— updateHightStyle(style: MeshBasicMaterialParameters),同上必传参(注意官方拼写是 Hight)
setData 修改数据
getData 获取数据
getItemDataByFaceIndex 通过faceIndex获取数据
refreshHighlight 刷新高亮数据
setItemHighlight 设置某项高亮与否。⚠️ setItemHighlight(id, false) 不重绘,需随后调 refreshHighlight()
isItemHighlight 获取某项高亮与否
clearHighlight 清除所有高亮

使用示例

创建FillExtrusionsEntity

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({
    coordinates: [[7,  3],[-4,  -2],[-5,  3]],
    color: "#f00",
    extrude: {
        depth: Math.random()  + 1,
        steps: 1,
        bevelEnabled: false
    }
})
let fillExtrusions = new vjmap3d.FillExtrusionsEntity({ //FillExtrusionsEntity
    data: data
})
fillExtrusions.addTo(app)

TS 用户注意:

  • coordinates 声明为 [number,number][](或带洞的 [number,number][][])——普通 number[][] 字面量推断不过,须 as const、显式 [number,number][] 标注或 toArray() 返回值。
  • .on("mouseover", e => ...) 的事件参数 d.ts 未标类型,strict 下写 e => 报 implicit-any,用 (e: any) => 或自行收窄;e.intersection.faceIndex 运行时存在。
  • updateStyle()/updateHightStyle() 必传 MeshBasicMaterialParameters;要"刷新数据"用 setData(getData()),要刷高亮用 refreshHighlight()(无参)。
  • updateHightStyle({color:'#00ff00'}) 会抛 Cannot create property 'needsUpdate' on string:实现是逐键 material[k]=v 然后 v.needsUpdate=true——值必须传 THREE 对象(color: new THREE.Color('#00ff00') 可用);它作用在高亮拉伸体(highlightFillExtrusions)的材质上,不是边框线;且参数被记进 style 而非 highlightStyle。updateStyle(作用于 fillExtrusions 材质)同型实现同坑。
  • baseHeight 是数值(基准高度,世界单位),但 d.ts 里误标为 boolean——按数值传参是对的,strict 下需自行断言。

创建一个复杂的拉伸对象

data.push({
    // 当为多个多边形时,第一个多边形后面的多边形将掏空挖洞处理
    coordinates: [[[7,  -8],[-1,  -1],[-8,  -9],[17,  -18]],  [ [-2,  -9],[2, -10],[2,  -7],[-1,  -6]]],
    color: "#FFFE91", // 底部颜色
    color2: "#0ff", // 顶部颜色
    showBorder: true, // 显示边框线
    borderColor: "#39107B",// 边框线底部颜色
    borderColor2: "#EA3FF7",// 边框线顶部颜色
    baseHeight: 1, // 基准高度
    extrude: { // 拉伸属性
        depth: Math.random() * 3  + 1,
        steps: 1,
        bevelEnabled: false
    }
})

增加事件

fillExtrusions.pointerEvents = true; // 允许事件交互
fillExtrusions.on("mouseover", e => {
    if (e?.intersection?.faceIndex !== undefined) {
        let itemData = fillExtrusions.getItemDataByFaceIndex(e?.intersection?.faceIndex);
        if (itemData && itemData.id) fillExtrusions.setItemHighlight(itemData.id, true)
    }
})
fillExtrusions.on("mouseout", e => {
    fillExtrusions.clearHighlight()
})

修改、新增、删除

调用 setData 来对数据进行增删改

// 如新增一条
data.push({
    coordinates: [[7, 3],[-4, -2],[-5, 3]],
    color: "#f00",
    extrude: {
        depth: Math.random() * 1 + 1,
        steps: 1,
        bevelEnabled: false
    }
})
fillExtrusions.setData(data)

全部显示或隐藏边框线

// 获取模块对象
let mod = fillExtrusions.getModule(vjmap3d.FillExtrusionsModule);
mod.showBorder = true; // 设置属性
mod.setData(mod.getData()); // 刷新下

3D示例

let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    scene: {
        gridHelper: { visible: true } // 是否显示坐标网格
    },
    stat: {
        show: true,
        left: "0"
    },
    camera: {  // 相机设置
        viewHelper: { enable: true, position: "leftBottom" } // 是否显示视角指示器
    }
})
let data = [];
data.push({
    coordinates: [[7,  3],[-4,  -2],[-5,  3]],
    color: "#f00",
    extrude: {
        depth: Math.random()  + 1,
        steps: 1,
        bevelEnabled: false
    }
})
data.push({
    coordinates: [[[7,  -8],[-1,  -1],[-8,  -9],[17,  -18]],  [ [-2,  -9],[2, -10],[2,  -7],[-1,  -6]]],
    color: "#FFFE91", // 底部颜色
    color2: "#0ff", // 顶部颜色
    showBorder: true, // 显示边框线
    borderColor: "#39107B",// 边框线底部颜色
    borderColor2: "#EA3FF7",// 边框线顶部颜色
    baseHeight: 1, // 基准高度
    extrude: {
        depth: Math.random() * 3  + 1,
        steps: 1,
        bevelEnabled: false
    }
})
//
let fillExtrusions = new vjmap3d.FillExtrusionsEntity({ //FillExtrusionsEntity
    data: data,
    // showBorder: true, 可以全局控制是否显示边框线
    highlightStyle: {
        color: "#777" // 高亮时颜色
    }
})
fillExtrusions.addTo(app)
//
fillExtrusions.pointerEvents = true; // 允许事件交互
fillExtrusions.on("mouseover", e => {
    if (e?.intersection?.faceIndex !== undefined) {
        let itemData = fillExtrusions.getItemDataByFaceIndex(e?.intersection?.faceIndex);
        if (itemData && itemData.id) fillExtrusions.setItemHighlight(itemData.id, true)
    }
})
fillExtrusions.on("mouseout", e => {
    fillExtrusions.clearHighlight()
})
//
const ui = await app.getConfigPane({ title: "设置", style: { width: "250px", overflow: "hidden"}});
let cfg = [
    {
        type: 'checkbox',
        label: '显示顶点',
        getValue: () => fillExtrusions.isShowVertex(),
        setValue: v => {
            fillExtrusions.setShowVertex(v)
        }
    },
    {
        type: 'checkbox',
        label: '显示边框线',
        value: false,
        onChange: ({ value } )=> {
            // 获取模块对象
            let mod = fillExtrusions.getModule(vjmap3d.FillExtrusionsModule);
            mod.showBorder = value; // 设置属性
            mod.setData(mod.getData()); // 刷新下
        }
    },
    {
        type: 'button',
        label: '增加一个拉伸',
        value: ()=> {
            data.push({
                coordinates: [vjmap3d.randPoint2D(),vjmap3d.randPoint2D(),vjmap3d.randPoint2D()],
                color: vjmap3d.randColor(),
                extrude: {
                    depth: Math.random() * 1 + 1,
                    steps: 1,
                    bevelEnabled: false
                }
            })
        fillExtrusions.setData(data)
    }
},
{
    type: 'button',
    label: '修改第一个拉伸颜色',
    value: ()=> {
        if (data.length > 0) {
            data[0].color = vjmap3d.randColor()
        }
        fillExtrusions.setData(data)
    }
},
{
    type: 'button',
    label: '删除第一个拉伸',
    value: ()=> {
        if (data.length == 0) {
            return
        }
        data.splice(0, 1)
        fillExtrusions.setData(data)
    }
}

] cfg.forEach(c => ui.appendChild(c));

2D地图模式示例

 let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
// 打开地图
let res = await svc.openMap({
    mapid: env.exampleMapId, // 地图ID
    // @ts-ignore
    mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
    style: vjmap.openMapLightStyle() // div为深色背景颜色时,这里也传深色背景样式
})
if (res.error) {
    // 如果打开出错
    showError(res.error)
    return;
}
// 获取地图范围
let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
// 根据地图范围建立几何投影坐标系
let prj = new vjmap.GeoProjection(mapBounds);
//
// 地图对象
let map = new vjmap.Map({
    container: 'map', // DIV容器ID
    style: svc.rasterStyle(), // 样式,这里是栅格样式
    center: prj.toLngLat(mapBounds.center()), // 设置地图中心点
    zoom: 2, // 设置地图缩放级别
    pitch: 45,
    antialias: true, // 反锯齿
    renderWorldCopies: false // 不显示多屏地图
});
//
// 关联服务对象和投影对象
map.attach(svc, prj);
await map.onLoad();
//
// 创建3d图层
let mapLayer = new vjmap3d.MapThreeLayer(map, {
    stat: {
        show: true,
        left: "0"
    }
});
map.addLayer(new vjmap.ThreeLayer({ context: mapLayer }))
let app = mapLayer.app;
let data = [];
// 外面边界的cad图上点坐标
let edge = [
	[587653761.9404196, 3103856376.721289],
	[587602251.0620328, 3103887684.472128],
	[587616705.4171646, 3103910542.4372025],
	[587668345.3998574, 3103879913.002372]
].map(p => vjmap3d.toWorld(p).toArray());
// 里面洞1的cad图上点坐标
let holes1 = [
	[587611243.649386, 3103892845.733727],
	[587618986.3449678, 3103888191.3405075],
	[587624099.183289, 3103897555.098504],
	[587616962.944966, 3103901844.930998]
].map(p => vjmap3d.toWorld(p).toArray());
// 里面洞2的cad图上点坐标
let holes2 = [
	[587648133.0725995, 3103883387.5836215],
	[587642667.2109047, 3103873956.0132804],
	[587650162.938667, 3103869450.080676],
	[587655761.2825799, 3103878763.0610456]
].map(p => vjmap3d.toWorld(p).toArray());
//
let bounds = map.getMapExtent();
let depth = vjmap3d.toDist(bounds.width() / 40);// 取地图范围的宽度的1/40距离做为拉伸高度
data.push({
    coordinates: [edge, holes1, holes2],
    color: "#FFFE91", // 底部颜色
    color2: "#0ff", // 顶部颜色
    showBorder: true, // 显示边框线
    borderColor: "#39107B",// 边框线底部颜色
    borderColor2: "#EA3FF7",// 边框线顶部颜色
    baseHeight: depth / 5, // 基准高度
    extrude: {
        depth: depth,
        steps: 1,
        bevelEnabled: false
    }
})
//
let fillExtrusions = new vjmap3d.FillExtrusionsEntity({ //FillExtrusionsEntity
    data: data,
    // showBorder: true, 可以全局控制是否显示边框线
    highlightStyle: {
        color: "#777" // 高亮时颜色
    }
})
fillExtrusions.addTo(app)
//
fillExtrusions.pointerEvents = true; // 允许事件交互
fillExtrusions.on("mouseover", e => {
    if (e?.intersection?.faceIndex !== undefined) {
        let itemData = fillExtrusions.getItemDataByFaceIndex(e?.intersection?.faceIndex);
        if (itemData && itemData.id) fillExtrusions.setItemHighlight(itemData.id, true)
    }
})
fillExtrusions.on("mouseout", e => {
    fillExtrusions.clearHighlight()
})
//
const ui = await app.getConfigPane({ title: "设置", style: { width: "250px", overflow: "hidden"}});
let cfg = [
    {
        type: 'checkbox',
        label: '显示顶点',
        getValue: () => fillExtrusions.isShowVertex(),
        setValue: v => {
            fillExtrusions.setShowVertex(v)
        }
    },
    {
        type: 'checkbox',
        label: '显示边框线',
        value: false,
        onChange: ({ value } )=> {
            let mod = fillExtrusions.getModule(vjmap3d.FillExtrusionsModule);
            mod.showBorder = value;
            mod.setData(mod.getData());
        }
    },
    {
        type: 'button',
        label: '增加一个拉伸',
        value: ()=> {
            data.push({
                coordinates: [mapBounds.randomPoint().toArray(),mapBounds.randomPoint().toArray(),mapBounds.randomPoint().toArray()].map(p => vjmap3d.toWorld(p).toArray()),
                color: vjmap3d.randColor(),
                extrude: {
                    depth: vjmap3d.toDist(bounds.width() * (Math.random() + 0.1) / 60),
                    steps: 1,
                    bevelEnabled: false
                }
            })
            fillExtrusions.setData(data)
        }
    },
    {
        type: 'button',
        label: '修改第一个拉伸颜色',
        value: ()=> {
            if (data.length > 0) {
                data[0].color = vjmap3d.randColor()
            }
            fillExtrusions.setData(data)
        }
    },
    {
        type: 'button',
        label: '删除第一个拉伸',
        value: ()=> {
            if (data.length == 0) {
                return
            }
            data.splice(0, 1)
            fillExtrusions.setData(data)
        }
    }
]
cfg.forEach(c => ui.appendChild(c));