Home  >  Article  >  Web Front-end  >  How does OpenLayer realize the movement of the car according to the path?

How does OpenLayer realize the movement of the car according to the path?

little bottle
little bottleforward
2019-04-30 11:53:333594browse

This article mainly talks about realizing path motion on openlayer. Let's go with the editor to see how it is implemented. Interested friends can take a look.

1. Requirements Analysis

The function the customer needs is to enable the car to move according to the path on a Gis map. Why does it have to be Gis? (This is a customer-specified requirement. I am speechless. ). And the customer also said that the base map should be easy to replace, but what he wanted to use Gis to express was indoor geographical information. I couldn't use ready-made Gis interfaces such as Baidu and Amap.

In view of the above requirements, I have not learned too much about web gis frameworks. Because the customer's concept of Gis is that it can zoom in and out, and can do path planning, etc. So I chose ol and used his static pictures (choose this to meet the customer's need to flexibly update the base map) as a Gis base map to solve this problem.

Related tutorials: js video tutorial

2. Effect display

3. Pseudocode implementation

Because it is a technical verification code, it is a bit complicated, so only the key code is given. If you have any business needs, welcome to discuss together.

3.1 Implement path drawing

This step is relatively simple. It mainly uses Ol’s Draw object. Here is the code:


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

The key code lies in the monitoring of the drawend event. If it is a LineString situation, put this feature in a public variable to facilitate use when the path is running.

3.2 Decompose path data

This part is to obtain the path path of step 3.1, and then analyze it, because the linestring on 3.1 is a collection of multiple line segments, but the essence of movement is It is to change the coordinates of the icon so that its rapid and continuous changes form a moving effect. So here is a method for path subdivision, the code is as follows:

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

Some mathematical trigonometric functions and calculation methods are used. This method finally selects a coordinate set calculated based on the step size.

3.3 Use postcompose to achieve motion effects

The code is as follows:


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

This movement code is implemented using ol’s postcompose event , because the postcompose event will be triggered after the render method is executed, so it replaces the timer implementation. Among them, rotation calculates the slope of the moving icon and the direction of movement based on the two-point coordinates, which is more impactful for the display.

The above is the detailed content of How does OpenLayer realize the movement of the car according to the path?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete