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


