riku
2025-09-04 7f6661cca40e3530111d628222fa25462022ec78
src/utils/chart/chart-map.js
@@ -2,6 +2,12 @@
// import * as shanghaiMap from 'echarts-china-cities-js/echarts-china-cities-js/shanghai.js'; // 修正地图数据文件路径
// import 'echarts-china-cities-js/echarts-china-cities-js/shanghai.js'; // 修正地图数据文件路径
import { shanghai, jingan } from '@/utils/chart/shanghai.js'; // 确保路径正确
import calculate from '@/utils/map/calculate.js';
// 偏移纬度,对应约100米
const OFFSET_LAT = 0.00082;
// 偏移纬度,对应约100米
const OFFSET_LNG = 0.0009;
/**
 * 计算地图中心点和缩放比例
@@ -9,40 +15,47 @@
 * @returns
 */
function calCenterPointAndZoom(gridData) {
  let centerLng = 0;
  let centerLat = 0;
  const coordinates = [];
  let maxLng = -180;
  let minLng = 180;
  let maxLat = -90;
  let minLat = 90;
  let zoom = 100;
  let zoom = 1;
  gridData.forEach((g) => {
    centerLng += g.centerLng;
    centerLat += g.centerLat;
    maxLng = Math.max(maxLng, g.centerLng);
    minLng = Math.min(minLng, g.centerLng);
    maxLat = Math.max(maxLat, g.centerLat);
    minLat = Math.min(minLat, g.centerLat);
    g.coordinates.forEach((coordArr) => {
      coordinates.push({
        lng: coordArr[0],
        lat: coordArr[1]
  });
  if (gridData.length > 0) {
    centerLng /= gridData.length;
    centerLat /= gridData.length;
  }
      maxLng = Math.max(maxLng, coordArr[0]);
      minLng = Math.min(minLng, coordArr[0]);
      maxLat = Math.max(maxLat, coordArr[1]);
      minLat = Math.min(minLat, coordArr[1]);
    });
  });
  console.log((maxLng - centerLng) / zoom);
  console.log('zoom', zoom);
  return {
    centerLng,
    centerLat,
    zoom
    centerLng: (maxLng + minLng) / 2,
    centerLat: (maxLat + minLat) / 2,
    zoom,
    bounds: [
      minLng - OFFSET_LNG,
      minLat - OFFSET_LAT,
      maxLng + OFFSET_LNG,
      maxLat + OFFSET_LAT
    ]
  };
}
function generateGridMap(gridData) {
  const width = 800;
  const height = 400;
  // 1. 创建临时DOM元素
  const div = document.createElement('div');
  div.style.width = '800px';
  div.style.height = '400px';
  div.style.width = `${width}px`;
  div.style.height = `${height}px`;
  document.body.appendChild(div);
  // 注册上海市地图数据
  // console.log(shanghaiMap);
@@ -57,7 +70,8 @@
    value: [grid.centerLng, grid.centerLat, grid.value], // 中心点经纬度和数值
    coords: grid.coordinates // 网格四角经纬度坐标数组 [[lng1,lat1], [lng2,lat2], ...]
  }));
  const { centerLng, centerLat, zoom } = calCenterPointAndZoom(gridData);
  const { centerLng, centerLat, zoom, bounds } =
    calCenterPointAndZoom(gridData);
  // 2. 配置项
  const option = {
@@ -72,18 +86,6 @@
      label: { show: true }, // 显示地名标签
      itemStyle: { areaColor: '#ddddddff', borderColor: '#999' }
    },
    // series: [
    //   {
    //     type: 'scatter',
    //     coordinateSystem: 'geo',
    //     data: [
    //       {
    //         name: '黄浦区',
    //         value: [121.490317, 31.222771, 100] // 中心点坐标+数值
    //       }
    //     ]
    //   }
    // ]
    series: [
      {
        type: 'custom',
@@ -112,12 +114,136 @@
  };
  chart.setOption(option);
  // 3. 导出为图片(返回base64)
  return chart.getDataURL({
    type: 'png',
    pixelRatio: 1,
    backgroundColor: '#ddddddff'
  });
  // 将像素坐标转换为经纬度
  // const convert = (x, y) => {
  //   return chart.convertFromPixel(
  //     {
  //       geoIndex: 0
  //     },
  //     [x, y]
  //   );
  // };
  // 将经纬度转换为像素坐标
  const convert = (lng, lat) => {
    return chart.convertToPixel(
      {
        geoIndex: 0
      },
      [lng, lat]
    );
  };
  // 计算画布的左上角和右下角对应的经纬度
  // 计算网格区域的左上角和右下角经纬度对应的像素坐标
  const topLeft = convert(bounds[0], bounds[3]);
  const bottomRight = convert(bounds[2], bounds[1]);
  // 计算合适的缩放倍数
  const scale = Math.min(
    Math.abs(width / (bottomRight[0] - topLeft[0])),
    Math.abs(height / (bottomRight[1] - topLeft[1]))
  );
  console.log('scale', scale);
  // 地图缩放比例
  chart.setOption({
    geo: {
      zoom: scale
}
  });
  // 3. 导出为图片(返回base64)
  return new Promise((resolve, reject) => {
    // 延迟执行确保绘制完成
    setTimeout(() => {
      const url = chart.getDataURL({
        type: 'png',
        pixelRatio: 2,
        backgroundColor: '#fff'
      });
      resolve(url);
    }, 1000);
  });
  // return captureMapByBounds({
  //   chart: chart,
  //   bounds: bounds
  // }).catch((err) => {
  //   console.error('截图失败:', err);
  // });
}
/**
 * 根据经纬度范围截取地图区域
 * @param {Object} params - 截取参数
 * @param {Array} params.bounds - 经纬度范围 [minLng, minLat, maxLng, maxLat]
 * @param {Object} params.chart - ECharts实例
 * @returns {Promise<string>} 截取区域的base64图片
 */
// function captureMapByBounds(params) {
//   const { bounds, chart } = params;
//   const [minLng, minLat, maxLng, maxLat] = bounds;
//   // 获取地图坐标系
//   // const geo = chart.getModel().getComponent('geo');
//   // if (!geo) return Promise.reject('未找到地图组件');
//   // 将经纬度转换为像素坐标
//   const convert = (lng, lat) => {
//     return chart.convertToPixel(
//       {
//         geoIndex: 0
//       },
//       [lng, lat]
//     );
//   };
//   // 计算四个角的像素坐标
//   const topLeft = convert(minLng, maxLat);
//   const bottomRight = convert(maxLng, minLat);
//   // 创建临时Canvas
//   const canvas = document.createElement('canvas');
//   const ctx = canvas.getContext('2d');
//   // 获取原始图表Canvas
//   const originalCanvas = chart.getDom().querySelector('canvas');
//   // 设置Canvas尺寸为截取区域大小
//   topLeft[0] -= 10;
//   topLeft[1] -= 10;
//   bottomRight[0] += 10;
//   bottomRight[1] += 10;
//   topLeft[0] = Math.max(topLeft[0], 0);
//   topLeft[1] = Math.max(topLeft[1], 0);
//   bottomRight[0] = Math.min(bottomRight[0], originalCanvas.width);
//   bottomRight[1] = Math.min(bottomRight[1], originalCanvas.height);
//   const width = bottomRight[0] - topLeft[0];
//   const height = bottomRight[1] - topLeft[1];
//   canvas.width = width;
//   canvas.height = height;
//   // 裁剪指定区域
//   ctx.drawImage(
//     originalCanvas,
//     topLeft[0],
//     topLeft[1], // 源图像裁剪起点
//     width,
//     height, // 源图像裁剪尺寸
//     0,
//     0, // 目标图像绘制起点
//     width,
//     height // 目标图像绘制尺寸
//   );
//   // 转换为base64图片
//   return new Promise((resolve) => {
//     // 延迟执行确保绘制完成
//     setTimeout(() => {
//       const base64 = canvas.toDataURL('image/png', 1.0);
//       resolve(base64);
//     }, 100);
//   });
// }
export default { generateGridMap };