core/screen/ShotGrid.js

import html2canvas from 'html2canvas'
import { Cesium } from '../../../namespace'
import { getScale, mapImg, mapSize, viewExtend } from '../../utils/Navigation'

const TDFT = [
  1, 2, 5, 10, 15, 20, 30, 45, 60, 120, 300, 600, 900, 1200, 1800, 2700, 3600,
  7200, 18000, 36000, 54000, 72000, 108000, 162000,
]

/**
 * 地图场景出图主类
 * @class
 */
class ShotGrid {
  /**
   * 构造函数
   * @param {Viewer} viewer 地图场景
   */
  constructor(viewer) {
    this._viewer = viewer
  }
  /**
   * 地图尺寸
   * @type {Object}
   */
  get mapSize() {
    return mapSize(this._viewer)
  }

  /**
   * 场景图片,base64格式
   * @type {String}
   */
  get img() {
    return mapImg(this._viewer)
  }

  /**
   * 场景比例尺,指的是场景画布1px的距离,单位m
   * @type {Number}
   */
  get scale() {
    return getScale(this._viewer)
  }

  /**
   * 获取地图四至,最小和最大经纬度,WGS84坐标,例如:{minx:95,miny:25,maxx:125,maxy:35}
   * @type {Object}
   */
  get viewExtend() {
    return viewExtend(this._viewer)
  }

  async getCanvas(id, options, download = false) {
    options = options || {}
    const ele = document.getElementById(id)
    if (!ele) throw new Error('The current ID element does not exist')
    const { dpi = 96, name = 'default', format = '.png' } = options
    const scale = dpi / 96
    const option = { scale }
    const canvas = await html2canvas(ele, option)
    download && (await this._downloadCanvas(canvas, name, format))
    return canvas
  }

  _downloadCanvas(canvas, name, format) {
    return new Promise((resolve, reject) => {
      var dataURL = canvas.toDataURL('image/png')
      var downloadLink = document.createElement('a')
      downloadLink.href = dataURL
      downloadLink.download = `${name}${format}`
      downloadLink.addEventListener('click', async () => {
        await Promise.resolve()
        resolve()
      })

      document.body.appendChild(downloadLink)
      downloadLink.click()
    })
  }
  // 返回当前数字位置
  _findIndexForNewNumber(newNumber) {
    let low = 0
    let high = TDFT.length - 1
    while (low <= high) {
      const mid = Math.floor((low + high) / 2)
      if (TDFT[mid] === newNumber) {
        return mid // 数字已经存在,返回位置
      } else if (TDFT[mid] < newNumber) {
        low = mid + 1
      } else {
        high = mid - 1
      }
    }
    return low
  }
  /**
   * 获取格网坐标值
   * @param {Number} min 最小坐标值,经纬度坐标
   * @param {Number} max 最大坐标值,经纬度坐标
   * @param {Number} count 插值数量
   * @returns {Object} 坐标值及位置
   */
  calculateCoords(min, max, count) {
    // 四个刻度
    min = min * 3600
    max = max * 3600
    const _t = (max - min) / count
    const _index = this._findIndexForNewNumber(_t)
    const step = TDFT[_index - 1]
    const start = Math.ceil(min / step) * step
    const end = Math.floor(max / step) * step
    const coordCount = 1 + (end - start) / step
    const result = []
    for (let index = 0; index < coordCount; index++) {
      const val = start + step * index
      const per = (val - min) / (max - min)
      result.push({ value: this._convertSecondsToDMS(val), per })
    }
    return result
  }

  // 生成度分秒
  _convertSecondsToDMS(seconds) {
    const degrees = Math.floor(seconds / 3600)
    const remainingSeconds = seconds % 3600
    let minutes = Math.floor(remainingSeconds / 60)
    minutes = minutes < 10 ? '0' + minutes : minutes
    let second = remainingSeconds % 60
    second = second < 10 ? '0' + second : second

    return `${degrees}° ${minutes}' ${second}"`
  }
}
export default ShotGrid