hi-ucs/front/public/leaflet/libs/iclient8c/examples/js/layer/WebGLImage.js

555 lines
17 KiB
Vue
Raw Normal View History

2022-06-14 09:32:49 +08:00
/* 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"
});