记录cesium的图元关闭深度测试后任然覆盖在Entity上的问题

1 阅读1分钟

仔细排查之后发现问题

  • 可能是填充颜色透明度问题,透明度必须为非1值
  • 可能是贴地设置的问题,必须不贴地,polygon必须设置height属性,注意PolygonHierarchy的position属性中携带的高度不生效
  • label/billboard被遮挡问题无法通过设置解决(我没找到),可以通过直接在dom上模拟效果来实现具体代码如下
import { SceneTransforms, Viewer, Cartesian3, Cartesian2 } from 'cesium'
import DefMark from './template.vue'
import { createVNode, render } from 'vue'
interface MarkOption {
    id?: string
    position?: Cartesian3
    show?: boolean
    img?: any
    name?: string
    imgWidth?: number
    imgHeight?: number
    text?: string
    background?: boolean // 图片是否作为文字的背景,文字在图片中居中展示
    backgroundColor?: string // 是否给文字添加背景色
    className?: string // 设置mark的类名
    imgClassName?: string // 设置mark中图片的类名
    textClassName?: string // 设置mark中文字的类名
    template?: any // 标记模板
    pointerEvents?: 'none' | 'all',
    properties?: any
}

interface Mark {
    dom: HTMLDivElement, 
    position: Cartesian3, 
    vNode: VNode, 
    show: boolean,
    noNeedUpdate?: boolean,
    properties: any
}
class UIMark {
    viewer: Viewer
    container: HTMLElement
    marks: {[key: string]: Mark}
    animationId: number
    animations: Function[]
    nameSpace: {[key: string]: string[]}
    constructor( viewer: Viewer = window.viewer, container: string | HTMLElement ) {
        this.viewer = viewer
        this.marks = {}
        this.nameSpace = {}
        this.container = typeof container === 'string' ? document.querySelector('#'+container) : container
        this.animations = []
        this.startAnimation()
        this.updatePositionAnimation()
    }

    private startAnimation() {
        const _this = this
        function animationFrame() {
            _this.animations.forEach(fn => fn())
            requestAnimationFrame(animationFrame)
        }
        this.animationId = requestAnimationFrame(animationFrame)
    }
    c3ToView (c3: Cartesian3) {
        return SceneTransforms.worldToWindowCoordinates(this.viewer.scene, c3, new Cartesian2())
    }

    getViewerPosition(dom: HTMLDivElement,position:Cartesian3) {
        const c2 = this.c3ToView(position)
        if(!c2) return
        dom.style.left = c2.x + 'px'
        dom.style.top = c2.y + 'px'
    }

    setFrameAction(callback: Function) {
        this.animations.push(callback)
    }

    removeFrameAction(callback: Function) {
        this.animations = this.animations.filter(fn => fn !== callback)
    }
    updatePosition(id: string, position: Cartesian3) {
        this.marks[id].position = position
    }

    updateProps(id: string, newProps:any) {
        Object.keys(newProps).forEach((key:any) => {
            this.marks[id].vNode.component.props[key] = newProps[key]
        })
    }

    updatePositionAnimation() {
        const _this = this
        function animation() {
            Object.values(_this.marks).forEach(item => {
                if(!item.show || !item.position || item.noNeedUpdate) return
                _this.getViewerPosition(item.dom, item.position)
            })
        }
        this.setFrameAction(animation)
    }

    createMark(opt: MarkOption) {
        // 获取容器
        const dom = document.createElement('div')
        const id = opt.id ?? `${+new Date()}`
        dom.id = id
        // 设置容器位置
        dom.style.position = 'absolute'
        // 暂时只能居中
        dom.style.transform = 'translate(-50%, -50%)'
        opt.show = opt.show === undefined ? true : opt.show ? true : false
        dom.style.display = opt.show ? 'block' : 'none'
        if(opt.pointerEvents !== 'all') dom.style.pointerEvents = 'none'
        // 创建mark的vnode
        const opt1 = reactive(Object.assign(opt))
        delete opt1.template
        const vn = createVNode(opt.template || DefMark, opt1)
        render(vn, dom)
        this.container.append(dom)
        this.marks[id] = {dom, position:opt.position, vNode: vn, show: opt.show, properties: opt.properties}
        if(opt.name) {
            if (!this.nameSpace[opt.name]) this.nameSpace[opt.name] = []
            this.nameSpace[opt.name].push(id)
        }
        return dom
    }
    clear() {
        Object.keys(this.marks).forEach(key => this.remove(key))
    }

    destroy() {
        cancelAnimationFrame(this.animationId)
        this.clear()
        this.nameSpace = {}
    }
}