`
夏莹_合肥
  • 浏览: 178410 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

OpenLayers动画效果显示路线

阅读更多

该类继承自Vector,加入层时不是一下子加入的,而是慢慢变长,动态的轨迹效果。这里借助了别人写的一个算法Point.js(附件)。已知地理位置两点,求第三点,其在第一点到第二点之间且距离第一点X米。见代码中的这个方法getPointOnLineByDistance。

trms.DynamicEffectLineVector = OpenLayers.Class(OpenLayers.Feature.Vector, {

    internal : 50, // 50ms
   
    speed : 50, // 50m/50ms, 1000m/s
   
    setVectorLayer : function(vectorLayer) {
       
        var components = this.geometry.components;
       
        this.geometry = new OpenLayers.Geometry.LineString(components[0], components[0]);
        vectorLayer.addFeatures([this]);
       
        var startPointIndex = 0;
        var startPoint = components[startPointIndex];
        var stopPoint = components[startPointIndex + 1];
        var currentPoint = components[startPointIndex];
        var nextPoint;
       
        var t = this;
        var fn = function() {
           
            nextPoint = t.getNextPoint(currentPoint, stopPoint);
            t.geometry.addPoint(nextPoint);
            vectorLayer.drawFeature(t);
           
            currentPoint = nextPoint;
           
            if(currentPoint.equals(stopPoint)) {
               
                // is end point
                if(stopPoint.equals(components[components.length - 1])) {
                    return;
                }
               
                startPoint = stopPoint;
                startPointIndex++;
                stopPoint = components[startPointIndex + 1];
            }
           
            setTimeout(fn, t.internal);
        };
       
        fn();
    },
   
    getNextPoint : function(currentPoint, stopPoint) {
       
        var nextPoint = this.getPointOnLineByDistance(currentPoint, stopPoint, this.speed);
       
        var x_current_stop = Math.abs(stopPoint.x - currentPoint.x);
        var x_current_next = Math.abs(nextPoint.x - currentPoint.x);
        var y_current_stop = Math.abs(stopPoint.y - currentPoint.y);
        var y_current_next = Math.abs(nextPoint.y - currentPoint.y);
       
        if(x_current_next > x_current_stop || y_current_next > y_current_stop) {
            return stopPoint;
        }
       
        return nextPoint;
    },
   
    getPointOnLineByDistance : function(p1, p2, distance) {
       
        var ppp1 = new Point(p1.x, p1.y);
        var ppp2 = new Point(p2.x, p2.y);
       
        var bearing = ppp1.geoBearingTo(ppp2);
        var ppp3 = ppp1.geoWaypoint(distance / 1000, bearing);
       
        return new OpenLayers.Geometry.Point(ppp3.x, ppp3.y);
    }
});
 



这下面的代码是一个完整的封装版本,包括状态管理、事件通知和样式等。下面用到的方法getBindToFn 请见我的这篇文章http://xiaying4415139-163-com.iteye.com/blog/430675

/**
 * support geom: MultiLineString
 */
trms.DynamicEffectLineVector = OpenLayers.Class(OpenLayers.Feature.Vector, {

    internal : 50, // 50ms
   
    speed : 5, // 5m/50ms, 100m/s
   
    vectorLayer : null,
   
    components : null,
   
    currentPointIndex : null,
   
    currentLineIndex : null,
   
    startPoint : null,
   
    stopPoint : null,
   
    currentTempPoint : null,
   
    timer : null,
   
    // event, fire when new point added
    pointAdded : null,
   
    // 'start', 'run', 'stop', 'end'
    dynamicState : 'start',
   
    // here state management
    orders : {
           
        start : {
            guardFn : function() {
                return this.dynamicState != 'start';
            },
            changeState : function() {
                this.dynamicState = 'run'; // start ---> run
            }
        },
       
        stop : {
            guardFn : function() {
                return this.dynamicState != 'run';
            },
            changeState : function() {
                this.dynamicState = 'stop'; // run ---> stop
            }
        },
       
        continueFn : {
            guardFn : function() {
                return this.dynamicState != 'stop';
            },
            changeState : function() {
                this.dynamicState = 'run'; // stop ---> run
            }
        },
       
        restart : {
            guardFn : function() {
                return this.dynamicState == 'start';
            },
            changeState : function() {
                this.dynamicState = 'run'; // * except start ---> run
            }
        }
    },
   
    initialize : function(geom, attributes) {
       
        if(geom instanceof OpenLayers.Geometry.LineString) {
            geom = new OpenLayers.Geometry.MultiLineString([geom]);
        }
       
        var style = this.getStyle();
        style.label = attributes.name;
        style.strokeColor  = attributes.color;
        style.fontColor = attributes.color;
       
        OpenLayers.Feature.Vector.prototype.initialize.apply(this, [geom, attributes, style]);
       
        this.components = this.geometry.components;
       
        this.initVariable();
    },
   
    // public
    setVectorLayer : function(vectorLayer) {
        this.vectorLayer = vectorLayer;
    },
   
    // public
    executeOrder : function(order) { // start, stop, continueFn, restart
       
        var guardFn = this.orders[order].guardFn.getBindToFn(this);
        var changeState = this.orders[order].changeState.getBindToFn(this);

        if(guardFn())
            return;

        this[order]();
       
        changeState();
    },
   
    /*-- private methods -------------------------------------------------------------------------------*/
   
    initVariable : function() {
        this.currentPointIndex = 0;
        this.currentLineIndex = 0;
        this.startPoint = this.components[0].components[0];
        this.stopPoint = this.components[0].components[1];
        this.currentTempPoint = this.startPoint;
    },
   
    start : function() {
   
        var line1 = new OpenLayers.Geometry.LineString(this.startPoint, this.startPoint);
        this.geometry = new OpenLayers.Geometry.MultiLineString([line1]);
        this.vectorLayer.addFeatures([this]);
       
        this.timeFn();
    },
   
    stop : function() {
        clearTimeout(this.timer);
    },
   
    continueFn : function() {
        this.timeFn();
    },
   
    restart : function() {
       
        this.stop();
       
        this.vectorLayer.removeFeatures([this]);
        this.initVariable();
       
        this.start();
    },
   
    timeFn : function() {
   
        this.currentTempPoint = this.getNextPoint(this.currentTempPoint, this.stopPoint);
        this.geometry.components[this.currentLineIndex].addPoint(this.currentTempPoint);
        this.vectorLayer.drawFeature(this);
       
        if(this.currentTempPoint.equals(this.stopPoint)) {            
           
            var currentLine = this.components[this.currentLineIndex];
           
            // last point on current line
            if(this.currentTempPoint.equals(currentLine.components[currentLine.components.length - 1])) {
               
                // last line, end
                if(this.currentLineIndex == this.components.length - 1) {
                    this.dynamicState = 'end';
                    return;
                }
               
                this.currentLineIndex++;
                this.currentPointIndex = 0;
               
                this.startPoint = this.components[this.currentLineIndex].components[0];
                this.stopPoint = this.components[this.currentLineIndex].components[1];
                this.currentTempPoint = this.startPoint;
               
                var newLine = new OpenLayers.Geometry.LineString(this.startPoint, this.startPoint);
                this.geometry.addComponent(newLine);
               
            } else {
               
                this.startPoint = this.stopPoint;
                this.currentPointIndex++;
                this.stopPoint = this.components[this.currentLineIndex].components[this.currentPointIndex + 1];
            }
        }
       
        this.timer = setTimeout(this.timeFn.getBindToFn(this), this.internal);

                if(this.pointAdded) {
            this.pointAdded(this.currentTempPoint); // fire event
        }

    },
   
    getNextPoint : function(currentTempPoint, stopPoint) {
       
        var nextPoint = this.getPointOnLineByDistance(currentTempPoint, stopPoint, this.speed);
       
        var x_current_stop = Math.abs(stopPoint.x - currentTempPoint.x);
        var x_current_next = Math.abs(nextPoint.x - currentTempPoint.x);
        var y_current_stop = Math.abs(stopPoint.y - currentTempPoint.y);
        var y_current_next = Math.abs(nextPoint.y - currentTempPoint.y);
       
        // deviation 0.000001 lonlat, about 0.01m
        var deviation = 1e-7;
        if(x_current_next - x_current_stop > deviation || y_current_next - y_current_stop > deviation) {
            return stopPoint;
        }
       
        return nextPoint;
    },
   
    getPointOnLineByDistance : function(p1, p2, distance) {
       
        var ppp1 = new Point(p1.x, p1.y);
        var ppp2 = new Point(p2.x, p2.y);
       
        var bearing = ppp1.geoBearingTo(ppp2);
        var ppp3 = ppp1.geoWaypoint(distance / 1000, bearing);
       
        return new OpenLayers.Geometry.Point(ppp3.x, ppp3.y);
    },
   
    getStyle : function() {
       
        var style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
       
        style.strokeWidth = 3;
       
        style.fontSize = '15px';
        style.fontFamily = '楷体_GB2312';
        style.fontWeight = 'bold';
        style.labelAlign = 'rm';
       
        return style;
    }
});

trms.DynamicEffectLineVectorToolbar = Ext.extend(Ext.Toolbar, {
   
    dynamicVector : null,
   
    initComponent : function() {
       
        trms.DynamicEffectLineVectorToolbar.superclass.initComponent.call(this);
       
        var t = this;
       
        var btnStart = new Ext.Button({
            text : '开始',
            handler : function() {
                t.dynamicVector.executeOrder('start');
            }
        });
       
        var btnStop = new Ext.Button({
            text : '停止',
            handler : function() {
                t.dynamicVector.executeOrder('stop');
            }
        });
       
        var btnContinue = new Ext.Button({
            text : '继续',
            handler : function() {
                t.dynamicVector.executeOrder('continueFn');
            }
        });
       
        var btnRestart = new Ext.Button({
            text : '重新开始',
            handler : function() {
                t.dynamicVector.executeOrder('restart');
            }
        });
       
        var btnDestroy = new Ext.Button({
            text : '清除',
            handler : function() {
                t.dynamicVector.destroy();
            }
        });
       
        this.add(btnStart);
        this.add(btnStop);
        this.add(btnContinue);
        this.add(btnRestart);
        this.add(btnDestroy);
    }
});
 

 

分享到:
评论
9 楼 xmxujinjun 2016-06-18  
大神,怎么调用啊
8 楼 s33ker 2013-08-30  
能简单说说怎么调用吗? 我也有点看蒙了
7 楼 yingkong87 2013-08-27  
请教一下这个有没有调用的例子?对这块不是太熟。谢谢
6 楼 fjut 2010-08-22  
感谢博主提示!借助您的思路,问题已经基本解决!
5 楼 夏莹_合肥 2010-08-20  
fjut 写道
谢谢博主的解答!初学者还想问几个简单的问题:1 在第一个代码框中的第11行        this.geometry = new OpenLayers.Geometry.LineString(components[0], components[0]);为什么是两个一样的 components[0]? 
2  同样是第一个代码框的20行  var t = this;  这个this代表什么?



第一个问题:线是慢慢变长的啊,初始的时候线是一个点(起点和终点在一起),然后随着时间慢慢改变第二个点的位置,当直线拐弯时增加第三个点,依次类推。所以如果线上有弧线的话,就会非常影响性能,因为描述一个弧线需要的点太多了。

第二个问题:保留js的当前对象,这个你学习过js的函数的当前对象,如果你知道这个,就能明白this了。
4 楼 fjut 2010-08-20  
谢谢博主的解答!初学者还想问几个简单的问题:1 在第一个代码框中的第11行        this.geometry = new OpenLayers.Geometry.LineString(components[0], components[0]);为什么是两个一样的 components[0]? 
2  同样是第一个代码框的20行  var t = this;  这个this代表什么?
3 楼 夏莹_合肥 2010-08-20  
fjut 写道
博主,想请教一下,对于这个openlayers的动态显示路径的方法适用于数组(许多的经纬度点)吗?


LineString 类型啊,其中不就是许多经纬度点组成的吗
2 楼 fjut 2010-08-20  
博主,想请教一下,对于这个openlayers的动态显示路径的方法适用于数组(许多的经纬度点)吗?
1 楼 e6175423 2010-05-21  
你好,我最近正在做关于台风路径的动画显示,能否给点技术上的指导,谢谢!

相关推荐

Global site tag (gtag.js) - Google Analytics