>웹 프론트엔드 >JS 튜토리얼 >OpenLayer는 경로에 따른 자동차의 움직임을 어떻게 구현하나요?

OpenLayer는 경로에 따른 자동차의 움직임을 어떻게 구현하나요?

little bottle
little bottle앞으로
2019-04-30 11:53:333643검색

이 글에서는 주로 openlayer에서 경로 모션을 구현하는 방법에 대해 설명합니다. 관심 있는 친구들은 한 번 살펴보세요.

1. 요구사항 분석

고객이 원하는 기능은 Gis 지도의 경로에 따라 차량이 이동할 수 있도록 하는 것입니다. (이것은 고객이 지정한 요구사항입니다. 말문이 막힙니다.) 그리고 고객님께서도 기본 지도는 교체가 쉬워야 한다고 하셨는데, Gis를 이용해 표현하고 싶었던 것은 Baidu나 Amap 같은 기성 Gis 인터페이스를 사용할 수가 없었습니다.

위의 요구 사항을 고려하여 웹 GiS 프레임워크에 대해 너무 많이 배우지 않았습니다. Gis의 고객 컨셉은 확대 및 축소가 가능하고 경로 계획 등을 할 수 있다는 것이기 때문입니다. 그래서 나는 이 문제를 해결하기 위해 ol을 선택하고 그의 정적 사진(기본 맵을 유연하게 업데이트하려는 고객의 요구를 충족시키기 위해 이것을 선택)을 Gis 기본 맵으로 사용했습니다.

관련 튜토리얼: js 영상 튜토리얼

2. 효과 표시

3. 의사코드 구현

기술적인 인증코드라 좀 지저분해서 키코드만 알려드립니다. 비즈니스 요구 사항이 있는 경우 함께 논의할 수 있습니다.

3.1 경로 그리기 구현

이 단계는 주로 Ol의 Draw 개체를 사용합니다.


draw(type){
        this.stopdraw();
        this._draw = new Draw({
            source: this.layer.getSource(),
            type: type == 'Icon' ? 'Point' : type
        });
        this._draw.on('drawend', (event)=>{
            if(type == 'LineString'){
                this.traceLine = event.feature;
            }
            if(type != 'Icon') return;
            let f = event.feature;
            f.setStyle(new Style({
                image: new Icon({
                    src: '/content/battery.gif'
                }),
                text: new Text({
                    text: 'new item',
                    fill: new Fill({
                        color: "red"
                    })
                })
            }));
            f.type = 'battery';
        });
        this.map.addInteraction(this._draw);
        this._snap = new Snap({source: this.layer.getSource()});
        this.map.addInteraction(this._snap);
    }

핵심 코드는 Drawend 이벤트인 경우입니다. , 이것을 사용하십시오. 이 기능은 경로가 실행될 때 사용하기 쉽도록 공용 변수에 배치됩니다.

3.2 경로 데이터 분해

3.1의 선스트링은 여러 선분의 집합이므로 이동의 본질은 아이콘의 좌표를 변경하는 것이므로 3.1단계의 경로를 구해서 분석하는 부분입니다. 빠르게 만들고 지속적인 변화는 움직이는 효과를 만듭니다. 따라서 경로 세분화 방법은 다음과 같습니다. 코드는 다음과 같습니다.

cutTrace(){
        let traceCroods = this.traceLine.getGeometry().getCoordinates(); 
        let len = traceCroods.length;
        let destCroods = [];
        for(let i = 0; i < len - 1; ++i){
            let bPoint = traceCroods[i];
            let ePoint = traceCroods[i+1];
            let bevelling = Math.sqrt(Math.pow(ePoint[0] - bPoint[0], 2)
            + Math.pow(ePoint[1] - bPoint[1], 2) );
            let cosA = (ePoint[0] - bPoint[0]) / bevelling;
            let sinA = (ePoint[1] - bPoint[1]) / bevelling;
            
            let curStep = 0;
            let step = 5;
            destCroods.push(new Point([bPoint[0], bPoint[1]]));
            do{
                curStep++;
                let nextPoint;
                if(curStep * step >= bevelling){
                    nextPoint = new Point([ePoint[0], ePoint[1]]);
                }else{
                    nextPoint = new Point([
                        cosA * curStep * step + bPoint[0]
                        ,
                        sinA * curStep * step + bPoint[1]
                    ]);
                }
                destCroods.push(nextPoint);
            }while(curStep * step < bevelling);
        }
        return destCroods;
    }

일부 수학적 삼각함수와 계산 방법이 사용됩니다. 이 방법은 최종적으로 스텝 크기를 기준으로 계산된 좌표 세트를 선택합니다.

3.3 postcompose를 사용하여 모션 효과 구현

코드는 다음과 같습니다.


tracerun(){
        if(!this.traceLine) return;
        this.traceCroods = this.cutTrace();
        this.now = new Date().getTime();
        this.map.on(&#39;postcompose&#39;, this.moveFeature.bind(this));
        this.map.render();
    }
    moveFeature(event){
        let vCxt = event.vectorContext;
        let fState = event.frameState;
        let elapsedTime = fState.time - this.now;
        let index = Math.round(300 * elapsedTime / 1000);
        let len = this.traceCroods.length;
        if(index >= len){
            //stop
            this.map.un(&#39;postcompose&#39;, this.moveFeature);
            return;
        }
        let dx, dy, rotation;
        if(this.traceCroods[index] && this.traceCroods[index + 1]){
            let isRigth = false;
            let bCrood = this.traceCroods[index].getCoordinates();
            let eCrood = this.traceCroods[index + 1].getCoordinates();
            if(bCrood[0] < eCrood[0]){
                //左->右
                isRigth = true
            }
            dx = bCrood[0] - eCrood[0];
            dy = bCrood[1] - eCrood[1];

            rotation = Math.atan2(dy,dx);
            if(rotation > (Math.PI / 2)){
                //修正
                rotation =  Math.PI - rotation;
            }else if(rotation < -1 * (Math.PI / 2)){
                rotation = -1 * Math.PI - rotation;
            }else{
                rotation = -rotation;
            }
            console.log(dx + &#39;  &#39; + dy + &#39;  &#39; + rotation);
            let curPoint = this.traceCroods[index];
            var anchor = new Feature(curPoint);
            let style = new Style({
                image: new Icon({
                    img: isRigth ? this.carRight : this.carImg,
                    imgSize: [32,32],
                    rotateWithView: false,
                    rotation: rotation
                }),
                text: new Text({
                    text: &#39;Car&#39;,
                    fill: new Fill({
                        color: &#39;red&#39;
                    }),
                    offsetY: -20
                })
            });  
            vCxt.drawFeature(anchor, style);
            //this.map.getView().setCenter(bCrood);
        }
        this.map.render();
    }

이 모바일 코드는 ol의 postcompose 이벤트를 사용하여 구현됩니다. 렌더링 메서드가 실행된 후 postcompose 이벤트가 트리거되기 때문에 타이머 구현 계획. 그 중 회전은 2점 좌표를 기준으로 움직이는 아이콘의 기울기와 이동 방향을 계산해 디스플레이에 더욱 임팩트를 준다.

위 내용은 OpenLayer는 경로에 따른 자동차의 움직임을 어떻게 구현하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 cnblogs.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제