555 lines
17 KiB
Vue
555 lines
17 KiB
Vue
|
/* COPYRIGHT 2012 SUPERMAP
|
|||
|
* 本程序只能在有效的授权许可下使用。
|
|||
|
* 未经许可,不得以任何手段擅自使用或传播。*/
|
|||
|
|
|||
|
/**
|
|||
|
* @requires SuperMap/Tile.js
|
|||
|
*/
|
|||
|
|
|||
|
/**
|
|||
|
* Class: SuperMap.Tile.WebGLImage
|
|||
|
* 瓦片拼接类(webgl)。
|
|||
|
* 用于管理图层图像拼贴。
|
|||
|
*
|
|||
|
* Inherits from:
|
|||
|
* - <SuperMap.Tile>
|
|||
|
*/
|
|||
|
|
|||
|
SuperMap.Tile.WebGLImage = SuperMap.Class(SuperMap.Tile, {
|
|||
|
|
|||
|
/**
|
|||
|
* Property: url
|
|||
|
* {String} The URL of the image being requested. No default. Filled in by
|
|||
|
* layer.getURL() function.
|
|||
|
* 图片的url。
|
|||
|
*/
|
|||
|
url: null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: newImgTag
|
|||
|
* {String} tile最近请求的image的标签。
|
|||
|
*/
|
|||
|
newImgTag:null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: canvasType
|
|||
|
*/
|
|||
|
canvasType: null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: frame
|
|||
|
* {DOMElement} The canvas element is appended to the frame. Any gutter on
|
|||
|
* the canvas will be hidden behind the frame.
|
|||
|
*/
|
|||
|
frame: null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: isLoading
|
|||
|
* {Boolean} Indicates if the tile is currently waiting on a loading image.
|
|||
|
*/
|
|||
|
isLoading: false,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: canvas
|
|||
|
* {DOMElement} The canvas element on which the image is drawn.
|
|||
|
*/
|
|||
|
canvas: null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: lastImage
|
|||
|
* {Image} The last requested image object. This property is used to make sure
|
|||
|
* that only the recent image is drawn.
|
|||
|
*/
|
|||
|
lastImage: null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: lastBounds
|
|||
|
* {<SuperMap.Bounds>} The bounds of the last requested image, needed for
|
|||
|
* VirtualCanvasImage.displayImage().
|
|||
|
*/
|
|||
|
lastBounds: null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: isBackBuffer
|
|||
|
* {Boolean} Is this tile a back buffer tile?
|
|||
|
*/
|
|||
|
isBackBuffer: false,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: backBufferTile
|
|||
|
* {<SuperMap.Tile>} A clone of the tile used to create transition
|
|||
|
* effects when the tile is moved or changes resolution.
|
|||
|
*/
|
|||
|
backBufferTile: null,
|
|||
|
|
|||
|
/**
|
|||
|
* Property: fadingTimer
|
|||
|
* {Number} 记录fading动画的索引ID
|
|||
|
*
|
|||
|
*/
|
|||
|
fadingTimer:null,
|
|||
|
|
|||
|
/**
|
|||
|
* Constructor: SuperMap.Tile.WebGLImage
|
|||
|
* 瓦片拼接类。
|
|||
|
*
|
|||
|
* Parameters:
|
|||
|
* layer - {<SuperMap.Layer>} 瓦片所在的图层。
|
|||
|
* position - {<SuperMap.Pixel>}左上角的点。
|
|||
|
* bounds - {<SuperMap.Bounds>}瓦片大小。
|
|||
|
* url - {<String>}瓦片对应的url地址。
|
|||
|
* size - {<SuperMap.Size>}瓦片的size。
|
|||
|
* canvasType -
|
|||
|
*/
|
|||
|
initialize: function(layer, position, bounds, url, size, canvasType) {
|
|||
|
var me = this;
|
|||
|
SuperMap.Tile.prototype.initialize.apply(me, arguments);
|
|||
|
me.url = url; //deprecated remove me
|
|||
|
me.canvasType = canvasType;
|
|||
|
me.events.addEventType("reprojectionProgress");
|
|||
|
me.events.addEventType("filterProgress");
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* APIMethod: destroy
|
|||
|
* 解构 WebGLImage 类,释放资源。
|
|||
|
*/
|
|||
|
destroy: function() {
|
|||
|
SuperMap.Tile.prototype.destroy.apply(this, arguments);
|
|||
|
var me = this;
|
|||
|
me.lastImage = null;
|
|||
|
me.canvas = null;
|
|||
|
me.canvasContext = null;
|
|||
|
// clean up the backBufferTile if it exists
|
|||
|
if (me.backBufferTile) {
|
|||
|
me.backBufferTile.destroy();
|
|||
|
me.backBufferTile = null;
|
|||
|
me.layer.events.unregister("loadend", me, me.hideBackBuffer);
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: clone
|
|||
|
* 创建当前类的副本。
|
|||
|
* Parameters:
|
|||
|
* obj - {<SuperMap.Tile.Image>} The tile to be cloned
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* {<SuperMap.Tile.Image>} An exact clone of this <SuperMap.Tile.WebGLImage>
|
|||
|
*/
|
|||
|
clone: function (obj) {
|
|||
|
var me = this;
|
|||
|
if (obj == null) {
|
|||
|
obj = new SuperMap.Tile.WebGLImage(me.layer,
|
|||
|
me.position,
|
|||
|
me.bounds,
|
|||
|
me.url,
|
|||
|
me.size,
|
|||
|
me.canvasType);
|
|||
|
}
|
|||
|
//pick up properties from superclass
|
|||
|
obj = SuperMap.Tile.prototype.clone.apply(me, [obj]);
|
|||
|
// a new canvas element should be created for the clone
|
|||
|
obj.canvas = null;
|
|||
|
return obj;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: draw
|
|||
|
* Check that a tile should be drawn, and draw it. Starts a
|
|||
|
* transition if the layer requests one.
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* {Boolean} Always returns true.
|
|||
|
*/
|
|||
|
draw: function() {
|
|||
|
var me = this;
|
|||
|
if (me.layer != me.layer.map.baseLayer && me.layer.reproject) {
|
|||
|
me.bounds = me.getBoundsFromBaseLayer(me.position);
|
|||
|
}
|
|||
|
var drawTile = SuperMap.Tile.prototype.draw.apply(me, arguments);
|
|||
|
me.startTransition(drawTile);
|
|||
|
if (!drawTile) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (me.isLoading) {
|
|||
|
// if we're already loading, send 'reload' instead of 'loadstart'.
|
|||
|
me.events.triggerEvent("reload");
|
|||
|
} else {
|
|||
|
me.isLoading = true;
|
|||
|
me.events.triggerEvent("loadstart");
|
|||
|
}
|
|||
|
return me.renderTile();
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: startTransition
|
|||
|
* Creates a backbuffer tile (if it does not exist already)
|
|||
|
* and then displays this tile.
|
|||
|
*
|
|||
|
* Parameters:
|
|||
|
* drawTile - {<Boolean>} Should the tile be drawn?
|
|||
|
*/
|
|||
|
startTransition: function(drawTile) {
|
|||
|
// <SuperMap.CanvasLayer.> takes care about the transition
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: renderTile
|
|||
|
* Creates the canvas element and sets the URL.
|
|||
|
*
|
|||
|
* Returns:
|
|||
|
* {Boolean} Always returns true.
|
|||
|
*/
|
|||
|
renderTile: function() {
|
|||
|
var me = this;
|
|||
|
me.url = me.layer.getURL(me.bounds);
|
|||
|
me.positionImage();
|
|||
|
return true;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: createImage
|
|||
|
* Creates the image and starts loading it.
|
|||
|
*/
|
|||
|
createImage: function() {
|
|||
|
//如果在缓存的内存图片可以找到的话,就不再创建图片,直接调用图片的onLoad事件的响应函数
|
|||
|
//不过这里需要注意,制作专题图的时候,需要清除已经缓存的内存图片
|
|||
|
//否则有可能看不到专题图的图片。
|
|||
|
|
|||
|
if (this.lastImage !== null && !this.lastImage.complete) {
|
|||
|
// 平移多次时候将不会请求图片,chrome下不能用。 https://bugs.webkit.org/show_bug.cgi?id=35377
|
|||
|
this.lastImage.src = '';
|
|||
|
}
|
|||
|
|
|||
|
//先查看内存中是否有保存
|
|||
|
var me = this, image = me.layer.getMemoryImg(me.bounds);
|
|||
|
me.lastBounds = me.bounds.clone();
|
|||
|
if (image) {
|
|||
|
me.newImgTag = "";
|
|||
|
//找到就显示
|
|||
|
me.lastImage = image;
|
|||
|
me.layer.drawCanvasTile(image, me.position);
|
|||
|
if(me.firstInView){
|
|||
|
me.setFirstInView();
|
|||
|
}
|
|||
|
} else {
|
|||
|
//构造新的image对象
|
|||
|
var key = me.layer.getXYZ(me.bounds);
|
|||
|
//如果使用andriod加载,则需本地加载完成后重新设置url。否则直接加载
|
|||
|
if (!SuperMap.isApp) {
|
|||
|
me.newImgTag = key.x + "_" + key.y + "_" + key.z;
|
|||
|
me.loadTileImage();
|
|||
|
} else{
|
|||
|
var strX = key.x,
|
|||
|
strY = key.y,
|
|||
|
strZ;
|
|||
|
if(me.layer instanceof SuperMap.Layer.CloudLayer || me.layer.storageType=="db"){
|
|||
|
strZ = key.z;
|
|||
|
} else{
|
|||
|
strZ = me.layer.scales[key.z].toExponential();
|
|||
|
}
|
|||
|
var canvasImageContext = {
|
|||
|
tile: me,
|
|||
|
X: strX,
|
|||
|
Y: strY,
|
|||
|
Z: strZ,
|
|||
|
viewRequestID: me.layer.map.viewRequestID
|
|||
|
};
|
|||
|
me.newImgTag = strX + "_" + strY + "_" + strZ;
|
|||
|
// var saveUrlProxy = function() {
|
|||
|
// this.tile.onLoadsaveUrlFunction(this);
|
|||
|
// }
|
|||
|
me.lastImage = new Image();
|
|||
|
|
|||
|
var methodName = me.getMethodName();
|
|||
|
var callBack = function(canvasImageContext,methodName){
|
|||
|
return function(r){
|
|||
|
window[methodName] = null;
|
|||
|
canvasImageContext.tile.onLoadsaveUrlFunction(canvasImageContext,r);
|
|||
|
}
|
|||
|
}(canvasImageContext,methodName);
|
|||
|
window[methodName] = callBack;
|
|||
|
/*window.plugins.localstoragemanager.getImg(me.url, me.layer.name, strX, strY, strZ,methodName,
|
|||
|
function(){},
|
|||
|
function(e){//errorfunction
|
|||
|
}
|
|||
|
); */
|
|||
|
cordova.exec(function(){}, function(e){}, "LocalStoragePlugin","getImg", [me.url, me.layer.name, strX, strY, strZ,methodName]);
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
getMethodName:function(){
|
|||
|
var dateTime=new Date();
|
|||
|
var yy=dateTime.getFullYear();
|
|||
|
var MM1=dateTime.getMonth()+1; //因为1月这个方法返回为0,所以加1
|
|||
|
var dd=dateTime.getDate();
|
|||
|
var hh=dateTime.getHours();
|
|||
|
var mm=dateTime.getMinutes();
|
|||
|
var ss=dateTime.getSeconds();
|
|||
|
var ms = dateTime.getMilliseconds();
|
|||
|
|
|||
|
var name = "getImgFromLocal_"+yy+MM1+dd+hh+mm+ss+ms+(Math.round(Math.random()*10000));
|
|||
|
return name;
|
|||
|
},
|
|||
|
|
|||
|
//重置本地URL,加载图片
|
|||
|
onLoadsaveUrlFunction:function(canvasImageContext, r) {
|
|||
|
var me = this;
|
|||
|
var nowImgTag = r.x + "_" + r.y + "_" + r.z;
|
|||
|
if(me.newImgTag != nowImgTag){
|
|||
|
return;
|
|||
|
}
|
|||
|
if(r.data){
|
|||
|
if(r.data=="null"){
|
|||
|
return false;
|
|||
|
}
|
|||
|
var src = "data:image/jpeg;base64,"+r.data;
|
|||
|
}
|
|||
|
else{
|
|||
|
var src = me.layer.sdcardPath + "SuperMap/" + me.layer.name + "/" +
|
|||
|
canvasImageContext.Z + "/" + canvasImageContext.X + "_" + canvasImageContext.Y + ".png";
|
|||
|
}
|
|||
|
me.url = src;
|
|||
|
me.loadTileImage();
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: loadTileImage
|
|||
|
* 通过url加载图片,并对加载后的图片做缓存处理
|
|||
|
*/
|
|||
|
loadTileImage: function(){
|
|||
|
var me = this,
|
|||
|
image = new Image();
|
|||
|
image.firstInView = true;
|
|||
|
me.lastImage = image;
|
|||
|
var context = {
|
|||
|
image: image,
|
|||
|
tile: me,
|
|||
|
viewRequestID: me.layer.map.viewRequestID,
|
|||
|
newImgTag: me.newImgTag
|
|||
|
//bounds: me.bounds.clone()// todo: do we still need the bounds? guess no
|
|||
|
//urls: this.layer.url.slice() // todo: for retries?
|
|||
|
};
|
|||
|
|
|||
|
var onLoadFunctionProxy = function() {
|
|||
|
if(this.tile.newImgTag == this.newImgTag){
|
|||
|
this.tile.onLoadFunction(this);
|
|||
|
}
|
|||
|
};
|
|||
|
var onErrorFunctionProxy = function() {
|
|||
|
this.tile.onErrorFunction(this);
|
|||
|
};
|
|||
|
|
|||
|
image.onload = SuperMap.Function.bind(onLoadFunctionProxy, context);
|
|||
|
image.onerror = SuperMap.Function.bind(onErrorFunctionProxy, context);
|
|||
|
//图片的url赋予给image后就会从服务器获取到图片
|
|||
|
image.src = me.url;
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: positionImage
|
|||
|
* Sets the position and size of the tile's frame and
|
|||
|
* canvas element.
|
|||
|
*/
|
|||
|
positionImage: function() {
|
|||
|
var me = this;
|
|||
|
// if the this layer doesn't exist at the point the image is
|
|||
|
// returned, do not attempt to use it for size computation
|
|||
|
if (!me.layer) {
|
|||
|
return;
|
|||
|
}
|
|||
|
me.createImage();
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: onLoadFunction
|
|||
|
* Called when an image successfully finished loading. Draws the
|
|||
|
* image on the canvas. 图片加载成功后在canvas上进行绘制
|
|||
|
*
|
|||
|
* Parameters:
|
|||
|
* context - {<Object>} The context from the onload event.
|
|||
|
*/
|
|||
|
onLoadFunction: function(context) {
|
|||
|
if ((this.layer === null) ||
|
|||
|
(context.viewRequestID !== this.layer.map.viewRequestID) ||
|
|||
|
(context.image !== this.lastImage)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
this.canvasContext = null;
|
|||
|
var image = context.image;
|
|||
|
if(context.tile.shouldDraw){
|
|||
|
//绘制图片
|
|||
|
|
|||
|
this.displayImage(image,context.newImgTag);
|
|||
|
}
|
|||
|
//保存图片缓存
|
|||
|
this.layer.addMemoryImg(this.lastBounds, image, context);
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* APIMethod: drawImgData
|
|||
|
*
|
|||
|
* 重新绘制进行像素操作后的imgdata
|
|||
|
*
|
|||
|
* Parameters:
|
|||
|
* imgData - {<String>} canvas.toDataURL()得到的图片字符串
|
|||
|
* evt - {<Object>} tileloaded事件返回的事件对象,layer.events.on({tileloaded: function(evt) {}})
|
|||
|
*/
|
|||
|
drawImgData:function(imgData,evt){
|
|||
|
var m,idx=evt.idx;
|
|||
|
|
|||
|
m = new Image();
|
|||
|
m.onload = function(me,m,idx){
|
|||
|
return function(){
|
|||
|
if(idx==me.newImgTag){
|
|||
|
//m.firstInView = true;
|
|||
|
me.lastImage = m;
|
|||
|
me.layer.drawCanvasTile(m, me.position);
|
|||
|
}
|
|||
|
}
|
|||
|
}(this,m,idx);
|
|||
|
if(idx==this.newImgTag){
|
|||
|
m.src = imgData;
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* Method: displayImage
|
|||
|
* Takes care of resizing the canvas and then draws the
|
|||
|
* canvas.
|
|||
|
*
|
|||
|
* Parameters:
|
|||
|
* image - {Image/Canvas} The image to display
|
|||
|
* idx - {String} tile的标记
|
|||
|
*/
|
|||
|
displayImage: function(image,idx) {
|
|||
|
var me = this,
|
|||
|
layer = me.layer;
|
|||
|
if (layer.canvasFilter && !image.filtered) {
|
|||
|
// if a filter is set, apply the filter first and
|
|||
|
// then use the result
|
|||
|
me.filter(image);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if(image.firstInView){
|
|||
|
me.setFirstInView();
|
|||
|
}
|
|||
|
|
|||
|
//绘制图片
|
|||
|
layer.fixPosition();
|
|||
|
// layer.drawCanvasTile(image, me.position);
|
|||
|
//更新图片状态
|
|||
|
me.isLoading = false;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
me.events.triggerEvent("loadend",{"idx":idx});
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: onErrorFunction
|
|||
|
* Called when an image finished loading, but not successfully.
|
|||
|
*
|
|||
|
* Parameters:
|
|||
|
* context - {<Object>} The context from the onload event.
|
|||
|
*/
|
|||
|
onErrorFunction: function(context) {
|
|||
|
var me = this;
|
|||
|
//图片请求失败,就不绘这个tile,防止调用canvasContext.drawImage方法出错。
|
|||
|
if (context.image !== me.lastImage) {
|
|||
|
/* Do not trigger 'loadend' when a new image was request
|
|||
|
* for this tile, because then 'reload' was triggered instead
|
|||
|
* of 'loadstart'.
|
|||
|
* If we would trigger 'loadend' now, Grid would get confused about
|
|||
|
* its 'numLoadingTiles'.
|
|||
|
*/
|
|||
|
return;
|
|||
|
}
|
|||
|
//retry? with different url?
|
|||
|
|
|||
|
me._attempts = (me._attempts) ? (me._attempts + 1) : 1;
|
|||
|
if (me._attempts <= SuperMap.IMAGE_RELOAD_ATTEMPTS) {
|
|||
|
if (me.layer.url && SuperMap.Util.isArray(me.layer.url) && me.layer.url.length > 1){
|
|||
|
me.layer._attempts = me._attempts;
|
|||
|
me.draw();
|
|||
|
return ;
|
|||
|
}
|
|||
|
}else
|
|||
|
{
|
|||
|
me._attempts = 0;
|
|||
|
}
|
|||
|
|
|||
|
me.events.triggerEvent("loadend");
|
|||
|
},
|
|||
|
/**
|
|||
|
* Method: setFirstInView
|
|||
|
*
|
|||
|
*/
|
|||
|
setFirstInView: function(){
|
|||
|
var me = this;
|
|||
|
if(!me.fadingTimer){
|
|||
|
var context = {
|
|||
|
canvasImage:me,
|
|||
|
image: me.lastImage
|
|||
|
};
|
|||
|
me.fadingTimer = window.setTimeout(SuperMap.Function.bind(me.setNotFirstInView, context),100);
|
|||
|
}
|
|||
|
},
|
|||
|
/**
|
|||
|
* Method: setNotFirstInView
|
|||
|
*
|
|||
|
*/
|
|||
|
setNotFirstInView: function(){
|
|||
|
var me = this;
|
|||
|
// me.lastImage.firstInView = false;
|
|||
|
me.image.firstInView = false;
|
|||
|
window.clearTimeout(me.canvasImage.fadingTimer);
|
|||
|
me.canvasImage.fadingTimer = null;
|
|||
|
me.canvasImage.displayImage(me.image);
|
|||
|
},
|
|||
|
/**
|
|||
|
* Method: show
|
|||
|
* Show the tile. Called in <SuperMap.Tile.showTile()>.
|
|||
|
*/
|
|||
|
show: function() {},
|
|||
|
|
|||
|
/**
|
|||
|
* Method: hide
|
|||
|
* Hide the tile. To be implemented by subclasses (but never called).
|
|||
|
*/
|
|||
|
hide: function() { },
|
|||
|
|
|||
|
/**
|
|||
|
* Method: isTooBigCanvas
|
|||
|
* Used to avoid that the backbuffer canvas gets too big when zooming in very fast.
|
|||
|
* Otherwise drawing the canvas would take too long and lots of memory would be
|
|||
|
* required.
|
|||
|
*/
|
|||
|
isTooBigCanvas: function(size) {
|
|||
|
return size.w > 5000;
|
|||
|
},
|
|||
|
/**
|
|||
|
* Method: moveTo
|
|||
|
*
|
|||
|
*/
|
|||
|
moveTo: function (bounds, position, redraw) {
|
|||
|
if (redraw == null) {
|
|||
|
redraw = true;
|
|||
|
}
|
|||
|
this.bounds = bounds.clone();
|
|||
|
this.position = position.clone();
|
|||
|
//设置不重置canvas
|
|||
|
this.layer.redrawCanvas = false;
|
|||
|
if (redraw) {
|
|||
|
this.draw();
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
CLASS_NAME: "SuperMap.Tile.WebGLImage"
|
|||
|
});
|