zoukankan      html  css  js  c++  java
  • OpenLayer实现路径运动

         近期由于业务的需求,让我这从未想过要碰Web Gis的业余前端开发者,走了Web Gis的开发道路。功能需求很简单,但却也是让自己难为了好几天。如,应该选择那个Gis框架,Gis框架的兼容性如何,直接Ie哪些版,能不能简单到只有一张图片就行解决问题,等等。。。。。。

    在如此多的技术盲点,以及不确定的因素,我开始了征程,现将一些心得做些记录。

    一、需求分析

         客户需要的功能就是能在一张Gis图上实现小车根据路径进行移动,为什么一定要Gis呢(这是客户指定需求,无语一该)。并且客户还说底图要很容易更换,但他想要用Gis表现的却是室内的地理信息,我也没办法用baidu, 高德等现成的Gis接口。

    针对上述需求,我没有去了解过多的web gis框架。因为客户对Gis的概念就是能放大,缩小,可以做路径规划等。所以我就选择ol,利用他的静态图片(选择这个是为满足客户灵活更新底图的需求)做Gis底图的功能来解决此问题。

    二、效果展示

    三、伪代码实现

    由于是技术验证代码, 有些杂乱,现只给出关键性代码。如有业务需要欢迎共同讨论。

    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事件的监听,如果是LineString情况,就将此feature放在一个共公变量,方便路径运行时使用。

    3.2 分解路径数据

         此部分就是获取到3.1步骤的路径路径,然后进行解析,因为3.1上的linestring是多个线段的集合,但运动其本质就是改变图标的坐标,使其快速且连续的变化就形成了移动效果。所以这里有一个方法进行路径细分,代码如下:

    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('postcompose', 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('postcompose', 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 + '  ' + dy + '  ' + 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: 'Car',
                        fill: new Fill({
                            color: 'red'
                        }),
                        offsetY: -20
                    })
                });  
                vCxt.drawFeature(anchor, style);
                //this.map.getView().setCenter(bCrood);
            }
            this.map.render();
        }

        此移动代码的是用ol的postcompose事件进行实现的,因为render方法执行完成后会触发postcompose事件,所以就代替了定时器的的实现方案。其中rotation根据两点坐标计算出移动图标的斜度、以及移动的方向等,更为影响的展示。

  • 相关阅读:
    day 66 ORM django 简介
    day 65 HTTP协议 Web框架的原理 服务器程序和应用程序
    jQuery的事件绑定和解绑 事件委托 轮播实现 jQuery的ajax jQuery补充
    background 超链接导航栏案例 定位
    继承性和层叠性 权重 盒模型 padding(内边距) border(边框) margin 标准文档流 块级元素和行内元素
    属性选择器 伪类选择器 伪元素选择器 浮动
    css的导入方式 基础选择器 高级选择器
    03-body标签中相关标签
    Java使用内存映射实现大文件的上传
    正则表达式
  • 原文地址:https://www.cnblogs.com/cqhaibin/p/10786886.html
Copyright © 2011-2022 走看看