【地图自学系列】maptalks本地缓存瓦片


前言

这篇是为了提升二次加载瓦片速度的文章。受到前一篇图片本地缓存 indexedDB 技术的启发,想把地图的瓦片缓存到本地,达到少请求,优化加载速度。想不到效果还不错,提升至少50%以上。特别在高分辨率地图的情况下。先看对比效果

高分辨率地图二次加载对比

高分辨率地图层级切换对比


一、需求分析

1.1 找到地图引擎中加载瓦片的方法,然后替换。

这一步很重要,如果找不到,很难实现缓存。这篇文章在maptalks的基础上实现的,主要参考官网这篇案例。《用base64编码载入瓦片》

1.2 缓存本地图片

这里和前面一篇相似,indexedDb操作代码参考这里。indexDB 大图缓存

二、核心功能实现

代码比较简单,主要是对baseLayer进行监听,把原本案例中生成base64的部分进行替换。PhotoPool类只是一个缓存本地图片的类。

import axios from 'axios';
import * as maptalks from 'maptalks'
// 图片池
class PhotoPool {
  // 存储数据库名称
  dbName: string = 'imageCacheDB'
  // 存储空间名称
  storeName: string = 'images'
  constructor (dbName, storeName) {
    this.dbName = dbName
    this.storeName = storeName
    // 1、打开或创建 IndexedDB 数据库
    const dbPromise = indexedDB.open(this.dbName, 1);

    // 定义对象存储空间, 只有在创建时会调用
    dbPromise.onupgradeneeded = (event:any) => {
      const db = event.target.result;
      if (!db.objectStoreNames.contains(this.storeName)) {
        db.createObjectStore(this.storeName,  { keyPath: 'id' });
      }
    };
    // dbPromise.onsuccess = (event:any) => {
    //   const db = event.target.result;
    //   if (!db.objectStoreNames.contains(this.storeName)) {
    //     db.createObjectStore(this.storeName,  { keyPath: 'id' });
    //   }
    // }
  }
  /**
   * 获取图片
   * @param id  存储时的key,这里用瓦片的横纵序号
   * @param url 瓦片地址
   * @param callback 回调函数
   */
  getImageData (id: string, url: string, callback: Function) {
    // 3、 读取
    const dbPromise :IDBOpenDBRequest = indexedDB.open(this.dbName, 1);
    dbPromise.onsuccess = (event:any) => {
      const db = event.target.result;
      const tx = db.transaction(this.storeName, 'readonly');
      const store = tx.objectStore(this.storeName);
      const request = store.get(id);

      request.onsuccess = (event:any) => {
        const blob = event.target.result;
        if (blob) {
          callback(blob.imageData)
        } else {
          this.downloadImage(id, url, callback)
        }
      };
    };
  }
  /**
   * 下载并存储图片
   * @param id 存储时的key,这里用瓦片的横纵序号
   * @param url 瓦片地址
   * @param callback 回调函数
   */
  downloadImage (id: string, url: string, callback: Function) {
    // const req = axios.get( url, { responseType: 'arraybuffer' }); 
    // 发送GET请求获取图片
    axios.get(url, { responseType: 'blob' })
    .then(response => {
      // 创建一个Blob对象
      const blob = new Blob([response.data], { type: 'image/jpeg' });
      callback(blob)

      // 2、 新增 or 修改
      const dbPromise = indexedDB.open(this.dbName);
      dbPromise.onsuccess = (event:any) => {
        const db = event.target.result;
        const tx = db.transaction(this.storeName, 'readwrite');
        const store = tx.objectStore(this.storeName);
        store.put({ id: id, imageData: blob }); // 将 Blob 对象存储到 IndexedDB
      };
    })
    .catch(error => {
      console.error('请求图片失败:', error);
    });
  }
}

// 主要方法
const pool = new PhotoPool('imageMapDB', 'mapData')
...
baseLayer.on('renderercreate', function (e) {
  e.renderer.loadTileImage = function (img, url) {
  	// 主动获取图片
    pool.getImageData(url, url, (blob) => {
      // 为瓦片图片赋值
      img.src = URL.createObjectURL(blob)
    })
  };
});

...
const map = new maptalks.Map(id, {
  center : [120.1, 30.1],
  zoom: 7,
  dragPitch: true,
  dragRotate: true,
  dragRotatePitch: true,
  // spatialReference,
  baseLayer,
  layers: [],
  // centerCross: true,
  doubleClickZoom: false
})
### 使用 Maptalks 实现地图渲染 Maptalks 是一款轻量级且可扩展的地图库,支持集成 2D 和 3D 地图[^3]。为了实现基本的地图渲染功能,可以按照如下方法操作: #### 初始化 Map 对象并设置其属性 创建一个新的 `map` 实例时,需指定容器 ID、视口中心坐标以及缩放级别等参数。 ```javascript var map = new maptalks.Map('map', { center: [-0.113049, 51.49856], zoom: 14, minZoom : 2, maxZoom : 19, baseLayer: new maptalks.TileLayer('base',{ urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', subdomains: ['a','b','c'] }) }); ``` 上述代码片段展示了如何通过设定 URL 模板来加载底图瓦片层,并将其作为基础图层添加到地图实例中[^1]。 #### 添加矢量数据与样式定义 对于更复杂的应用场景而言,在完成地图初始化之后还可以进一步向其中加入地理要素(如点、线、面),并对这些对象应用自定义外观风格。 ```javascript const vectorLayer = new maptalks.VectorLayer('vector').addTo(map); new maptalks.Marker([-0.11747, 51.5075],{ symbol: [ {markerFile:'./img/marker.png'} ] }).addTo(vectorLayer); ``` 此部分演示了怎样利用 `VectorLayer` 类构建一个用于承载几何实体的新图层;接着以标记为例介绍了如何基于该图层绘制单个位置特征及其可视化表现形式。 #### 高级特性——水体特效处理 当涉及到水域区域的表现优化时,则可能需要用到特定的技术手段达成理想中的视觉效果。例如借助 WebGL 技术提供的能力,可以通过调整材质属性等方式增强水面的真实感[^2]。 ```javascript import * as THREE from 'three'; import WaterMaterial from '@maptalksgl/water-material'; // 创建WebGLRenderer... renderer.setClearColor(0xffffff); // 定义water material... scene.add(waterMesh); ``` 这里给出了一种采用 Three.js 库配合专门开发的 water material 插件来进行高级图形编程的方式,从而达到逼真的海洋波浪模拟目的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值