ArcGIS JS API 4.24影像图层ImageryLayer加载太慢又不能做切片?

使用场景

使用arcgis api在网页上加载影像图层时,影像服务因为需要根据影像单景id来过滤图层,没办法在发布服务的时候做切片处理,此时影像速度加载过慢,想要优化加载速度。查询良久后无果,自暴自弃浑水摸鱼半天过后,向组里的大佬请教,大佬给我指了一条路说去吧小伙子,这是我去年开拓出来的路,路上遇到啥不懂的随时问。感动,这就是大佬么,还是抱大腿快乐嗷(废柴猫猫流泪跳起冲向前方.gif)。这是易智瑞的webgis开发大佬@zmskra,webgis开发相关的问题有需要可以去找大佬付费咨询

思路

使用arcgis api中提供的BaseTileLayer相关内容,参考了arcgis官网的以下内容后:
1、Custom TileLayer的例子
2、TileInfo的文档
技术路线为:使用BaseTileLayer提供的createSubclass()创建自定义切片图层方法,在前端页面中用切片的形式加载影像图层

实例

技术框架:vue2 + arcgis api for js
0、初始化地图

this.map = new Map({
      // basemap: basemap,
      // layers: [],
  });
const params = {
      container: 'viewDiv',
      zoom: 5,
      center: [110, 35],
      map: this.map,
      constraints: {
          maxZoom: 18,
          minZoom: 4
      },
  };
//2维
this.activeView = new MapView(params);
//3维
this.activeView = new SceneView(params);

1、要加载动态切片,首先要确认当前坐标系以及切片方案,这里我用的是两种,都列上去了

const refList = [
  {
    name: '3857',
    wkid: 102100,
    latestWkid: 3857,
    origin: {x:-20037508.342787,y:20037508.342787},
    size: [256, 256],
    format: 'jpgpng',
    lods: [
      {levelValue: 0,level:0,resolution:156543.03392800014,scale:591657527.591555},
      {levelValue: 1,level:1,resolution:78271.51696399994,scale:295828763.795777},
      {levelValue: 2,level:2,resolution:39135.75848200009,scale:147914381.897889},
      {levelValue: 3,level:3,resolution:19567.87924099992,scale:73957190.948944},
      {levelValue: 4,level:4,resolution:9783.93962049996,scale:36978595.474472},
      {levelValue: 5,level:5,resolution:4891.96981024998,scale:18489297.737236},
      {levelValue: 6,level:6,resolution:2445.98490512499,scale:9244648.868618},
      {levelValue: 7,level:7,resolution:1222.992452562495,scale:4622324.434309},
      {levelValue: 8,level:8,resolution:611.4962262813797,scale:2311162.217155},
      {levelValue: 9,level:9,resolution:305.74811314055756,scale:1155581.108577},
      {levelValue: 10,level:10,resolution:152.87405657041106,scale:577790.554289},
      {levelValue: 11,level:11,resolution:76.43702828507324,scale:288895.277144},
      {levelValue: 12,level:12,resolution:38.21851414253662,scale:144447.638572},
      {levelValue: 13,level:13,resolution:19.10925707126831,scale:72223.819286},
      {levelValue: 14,level:14,resolution:9.554628535634155,scale:36111.909643},
      {levelValue: 15,level:15,resolution:4.77731426794937,scale:18055.954822},
      {levelValue: 16,level:16,resolution:2.388657133974685,scale:9027.977411},
      {levelValue: 17,level:17,resolution:1.1943285668550503,scale:4513.988705},
      {levelValue: 18,level:18,resolution:0.5971642835598172,scale:2256.994353},
      {levelValue: 19,level:19,resolution:0.29858214164761665,scale:1128.497176},
      {levelValue: 20,level:20,resolution:0.14929107082380833,scale:564.248588},
      {levelValue: 21,level:21,resolution:0.07464553541190416,scale:282.124294},
      {levelValue: 22,level:22,resolution:0.03732276770595208,scale:141.062147},
      {levelValue: 23,level:23,resolution:0.01866138385297604,scale:71.5310735}
    ]
  },
  {
    name: '4326',
    wkid: 4326,
    latestWkid: 4326,
    origin: {x:-180,y:90},
    size: [256, 256],
    format: 'jpgpng',
    lods: [
      {levelValue: 0,level:0,resolution:0.703125013115789,scale:2.95497598570834E8},
      {levelValue: 1,level:1,resolution:0.3515625065578945,scale:1.47748799285417E8},
      {levelValue: 2,level:2,resolution:0.17578125327894775,scale:7.38743996427087E7},
      {levelValue: 3,level:3,resolution:0.08789062663947399,scale:3.69371998213544E7},
      {levelValue: 4,level:4,resolution:0.043945313319736994,scale:1.84685999106772E7},
      {levelValue: 5,level:5,resolution:0.021972656659868472,scale:9234299.95533859},
      {levelValue: 6,level:6,resolution:0.010986328329934226,scale:4617149.97766929},
      {levelValue: 7,level:7,resolution:0.005493164164967124,scale:2308574.98883465},
      {levelValue: 8,level:8,resolution:0.0027465820824835504,scale:1154287.49441732},
      {levelValue: 9,level:9,resolution:0.0013732910412417797,scale:577143.747208662},
      {levelValue: 10,level:10,resolution:0.0006866455206208899,scale:288571.873604331},
      {levelValue: 11,level:11,resolution:0.0003433227603104438,scale:144285.936802165},
      {levelValue: 12,level:12,resolution:0.0001716613801552224,scale:72142.9684010827},
      {levelValue: 13,level:13,resolution:0.00008583069007761132,scale:36071.4842005414},
      {levelValue: 14,level:14,resolution:0.00004291534503880566,scale:18035.7421002707},
      {levelValue: 15,level:15,resolution:0.000021457672519402802,scale:9017.87105013534},
      {levelValue: 16,level:16,resolution:0.000010728836259701402,scale:4508.93552506767},
      {levelValue: 17,level:17,resolution:0.000005364418129850701,scale:2254.467762533835},
      {levelValue: 18,level:18,resolution:0.0000026822090649253505,scale:1127.2338812669175},
      {levelValue: 19,level:19,resolution:0.0000013411045324626752,scale:563.6169406334587},
      {levelValue: 20,level:20,resolution:0.0000006705522662313376,scale:281.80847031672937},
      {levelValue: 21,level:21,resolution:0.0000003352761331156688,scale:140.90423515836468},
      {levelValue: 22,level:22,resolution:0.0000001676380665578344,scale:70.45211757918234},
      {levelValue: 23,level:23,resolution:0.0000000838190332789172,scale:35.22605878959117}
    ]
  }
]

2、项目中引入所需模块

import refList from "../js/refLod"
import esriRequest from "@arcgis/core/request"
import BaseTileLayer from "@arcgis/core/layers/BaseTileLayer.js"
import TileInfo from "@arcgis/core/layers/support/TileInfo"

3、构造图层函数

async tileimageLayer(url, id, lockRasterIds, nowRef) {
    const _self = this;
    let teLayer = null;
    const tileimageLayer = BaseTileLayer.createSubclass({
        properties: {
            urlTemplate: null
        },
        getTileUrl: function (level, row, col) {
            // console.log("getTileUrl里的this",this);
            const lt_x = this.tileInfo.origin.x +
                col * this.tileInfo.lods[level].resolution 
                * this.tileInfo.size[0],
            lt_y = this.tileInfo.origin.y -
                row * this.tileInfo.lods[level].resolution 
                * this.tileInfo.size[1],
            rb_x = this.tileInfo.origin.x +
                (col + 1) *
                this.tileInfo.lods[level].resolution *
                this.tileInfo.size[0],
            rb_y = this.tileInfo.origin.y -
                (row + 1) *
                this.tileInfo.lods[level].resolution *
                this.tileInfo.size[1],
            bbox = lt_x + "," + rb_y + "," + rb_x + "," + lt_y,
            content = {
                bbox: bbox,
                size: this.tileInfo.size[0] + "," + this.tileInfo.size[1],
                dpi: this.tileInfo["dpi"],
                format: this.tileInfo["format"],
                bboxSR: this.bboxSR,
                imageSR: this.imageSR,
                // pixelType:this.pixelType,
                // noData:"0,0,0",
                mosaicRule:JSON.stringify({
                    "mosaicMethod":"esriMosaicLockRaster",
                    "lockRasterIds":this.lockRasterIds,
                }),
                transparent: true,
                f: "image",
            };
            return content;
        }, 
        fetchTile: function (level, row, col) {
            const content = this.getTileUrl(level, row, col);
            return esriRequest(this.urlTemplate + "/exportImage", {
                responseType: "image",
                query: content,
                // body:content,
                allowImageDataAccess: true,
            }).then(response => {
                const image = response.data,
                    width = this.tileInfo.size[0],
                    height = this.tileInfo.size[0],
                    canvas = document.createElement("canvas"),
                    context = canvas.getContext("2d");
                canvas.width = width;
                canvas.height = height;
                context.drawImage(image, 0, 0, width, height);
                return canvas;
            })
        },
    }),
    tileInfo = TileInfo.create({
        dpi: 96,
        format: nowRef.format,
        size: nowRef.origin.size,
        origin: {
            x: nowRef.origin.x,
            y: nowRef.origin.y,
            type: 'Point',
            spatialReference: {
                wkid: nowRef.wkid
            }
        },
        spatialReference: {
            wkid: nowRef.wkid
        },
        lods: nowRef.lods
    });
    teLayer = new tileimageLayer({
        title: "raster Layer",
        id: id,
        urlTemplate: url,
        tileInfo: tileInfo,
        bboxSR: nowRef.wkid,
        imageSR: nowRef.wkid,
        lockRasterIds: lockRasterIds,
        ascending: true,
    })
    return teLayer;
},

4、使用函数生成图层并加载

//首先选出来当前场景的坐标系
const nowRef = refList.find(l => {
  return l.wkid == this.activeView.spatialReference.wkid
})
//id是从影像服务中查询到的单景影像的objectId
const raster = this.tileimageLayer(url, "imgLayer", [id], nowRef)
this.map.add(raster, 0);

5、打完收功