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

 

 

转载自:https://blog.csdn.net/lanshan_84/article/details/83432524

You may also like...

退出移动版