| 
 | 1 | +import { PointLayer } from '@antv/l7';  | 
 | 2 | +import type { TestCase } from '../../types';  | 
 | 3 | +import { CaseScene } from '../../utils';  | 
 | 4 | + | 
 | 5 | +export const exportImage: TestCase = async (options) => {  | 
 | 6 | +  const scene = await CaseScene({  | 
 | 7 | +    ...options,  | 
 | 8 | +    mapConfig: {  | 
 | 9 | +      center: [116.417463, 40.015175],  | 
 | 10 | +      zoom: 8,  | 
 | 11 | +      minZoom: 5,  | 
 | 12 | +    },  | 
 | 13 | +  });  | 
 | 14 | + | 
 | 15 | +  // 添加示例数据  | 
 | 16 | +  const data = await fetch(  | 
 | 17 | +    'https://gw.alipayobjects.com/os/antfincdn/8Ps2h%24qgmk/traffic_110000.csv',  | 
 | 18 | +  ).then((res) => res.text());  | 
 | 19 | + | 
 | 20 | +  const colors = ['#c57f34', '#cbfddf', '#edea70', '#8cc9f1', '#2c7bb6'];  | 
 | 21 | +  const pointLayer = new PointLayer({})  | 
 | 22 | +    .source(data, {  | 
 | 23 | +      parser: {  | 
 | 24 | +        type: 'csv',  | 
 | 25 | +        y: 'lat',  | 
 | 26 | +        x: 'lng',  | 
 | 27 | +      },  | 
 | 28 | +    })  | 
 | 29 | +    .shape('dot')  | 
 | 30 | +    .size(0.5)  | 
 | 31 | +    .color('type', (type) => {  | 
 | 32 | +      switch (parseInt(type)) {  | 
 | 33 | +        case 3:  | 
 | 34 | +          return colors[0];  | 
 | 35 | +        case 4:  | 
 | 36 | +          return colors[1];  | 
 | 37 | +        case 41:  | 
 | 38 | +          return colors[2];  | 
 | 39 | +        case 5:  | 
 | 40 | +          return colors[3];  | 
 | 41 | +        default:  | 
 | 42 | +          return colors[4];  | 
 | 43 | +      }  | 
 | 44 | +    });  | 
 | 45 | + | 
 | 46 | +  scene.addLayer(pointLayer);  | 
 | 47 | + | 
 | 48 | +  // 等待图层渲染完成  | 
 | 49 | +  await new Promise((resolve) => {  | 
 | 50 | +    const checkRender = () => {  | 
 | 51 | +      if (scene.getLayers().every((layer) => layer.isVisible())) {  | 
 | 52 | +        resolve(true);  | 
 | 53 | +      } else {  | 
 | 54 | +        setTimeout(checkRender, 100);  | 
 | 55 | +      }  | 
 | 56 | +    };  | 
 | 57 | +    checkRender();  | 
 | 58 | +  });  | 
 | 59 | + | 
 | 60 | +  // 创建导出UI  | 
 | 61 | +  const createExportUI = () => {  | 
 | 62 | +    const container = document.createElement('div');  | 
 | 63 | +    container.style.cssText = `  | 
 | 64 | +      position: absolute;  | 
 | 65 | +      top: 140px;  | 
 | 66 | +      right: 20px;  | 
 | 67 | +      z-index: 1000;  | 
 | 68 | +      background: rgba(255, 255, 255, 0.95);  | 
 | 69 | +      padding: 15px;  | 
 | 70 | +      border-radius: 8px;  | 
 | 71 | +      box-shadow: 0 2px 8px rgba(0,0,0,0.15);  | 
 | 72 | +      font-family: Arial, sans-serif;  | 
 | 73 | +      min-width: 200px;  | 
 | 74 | +    `;  | 
 | 75 | + | 
 | 76 | +    const title = document.createElement('div');  | 
 | 77 | +    title.textContent = '地图导出';  | 
 | 78 | +    title.style.cssText = `  | 
 | 79 | +      font-weight: bold;  | 
 | 80 | +      margin-bottom: 10px;  | 
 | 81 | +      color: #333;  | 
 | 82 | +      font-size: 16px;  | 
 | 83 | +    `;  | 
 | 84 | + | 
 | 85 | +    const formatSelect = document.createElement('select');  | 
 | 86 | +    formatSelect.style.cssText = `  | 
 | 87 | +      width: 100%;  | 
 | 88 | +      padding: 5px;  | 
 | 89 | +      margin-bottom: 10px;  | 
 | 90 | +      border: 1px solid #ddd;  | 
 | 91 | +      border-radius: 4px;  | 
 | 92 | +      font-size: 14px;  | 
 | 93 | +    `;  | 
 | 94 | + | 
 | 95 | +    const formats = [  | 
 | 96 | +      { value: 'png', text: 'PNG' },  | 
 | 97 | +      { value: 'jpg', text: 'JPEG' },  | 
 | 98 | +    ];  | 
 | 99 | + | 
 | 100 | +    formats.forEach((format) => {  | 
 | 101 | +      const option = document.createElement('option');  | 
 | 102 | +      option.value = format.value;  | 
 | 103 | +      option.textContent = format.text;  | 
 | 104 | +      formatSelect.appendChild(option);  | 
 | 105 | +    });  | 
 | 106 | + | 
 | 107 | +    const exportBtn = document.createElement('button');  | 
 | 108 | +    exportBtn.textContent = '导出图片';  | 
 | 109 | +    exportBtn.style.cssText = `  | 
 | 110 | +      width: 100%;  | 
 | 111 | +      background: #1890ff;  | 
 | 112 | +      color: white;  | 
 | 113 | +      border: none;  | 
 | 114 | +      padding: 8px 16px;  | 
 | 115 | +      border-radius: 4px;  | 
 | 116 | +      cursor: pointer;  | 
 | 117 | +      font-size: 14px;  | 
 | 118 | +      margin-bottom: 8px;  | 
 | 119 | +    `;  | 
 | 120 | + | 
 | 121 | +    const downloadBtn = document.createElement('button');  | 
 | 122 | +    downloadBtn.textContent = '下载';  | 
 | 123 | +    downloadBtn.style.cssText = `  | 
 | 124 | +      width: 100%;  | 
 | 125 | +      background: #52c41a;  | 
 | 126 | +      color: white;  | 
 | 127 | +      border: none;  | 
 | 128 | +      padding: 8px 16px;  | 
 | 129 | +      border-radius: 4px;  | 
 | 130 | +      cursor: pointer;  | 
 | 131 | +      font-size: 14px;  | 
 | 132 | +    `;  | 
 | 133 | + | 
 | 134 | +    const status = document.createElement('div');  | 
 | 135 | +    status.id = 'export-status';  | 
 | 136 | +    status.style.cssText = `  | 
 | 137 | +      margin-top: 10px;  | 
 | 138 | +      font-size: 12px;  | 
 | 139 | +      color: #666;  | 
 | 140 | +      text-align: center;  | 
 | 141 | +    `;  | 
 | 142 | + | 
 | 143 | +    const previewContainer = document.createElement('div');  | 
 | 144 | +    previewContainer.style.cssText = `  | 
 | 145 | +      margin-top: 10px;  | 
 | 146 | +      text-align: center;  | 
 | 147 | +    `;  | 
 | 148 | + | 
 | 149 | +    container.appendChild(title);  | 
 | 150 | +    container.appendChild(formatSelect);  | 
 | 151 | +    container.appendChild(exportBtn);  | 
 | 152 | +    container.appendChild(downloadBtn);  | 
 | 153 | +    container.appendChild(status);  | 
 | 154 | +    container.appendChild(previewContainer);  | 
 | 155 | + | 
 | 156 | +    // 导出功能 - 使用场景提供的导出API  | 
 | 157 | +    const exportImage = async () => {  | 
 | 158 | +      try {  | 
 | 159 | +        status.textContent = '导出中...';  | 
 | 160 | +        exportBtn.disabled = true;  | 
 | 161 | + | 
 | 162 | +        // @ts-ignore  | 
 | 163 | +        const format = formatSelect.value as 'png' | 'jpg';  | 
 | 164 | +        //@ts-ignore  | 
 | 165 | +        console.log('format', scene.mapService);  | 
 | 166 | +        //@ts-ignore  | 
 | 167 | +        const dataURL = await scene.mapService.exportMap('png');  | 
 | 168 | +        // 使用场景的导出方法  | 
 | 169 | +        // const dataURL = await scene.exportMap(format)  | 
 | 170 | +        if (!dataURL) {  | 
 | 171 | +          throw new Error('导出失败:无法获取图片数据');  | 
 | 172 | +        }  | 
 | 173 | + | 
 | 174 | +        // 创建预览  | 
 | 175 | +        let preview = document.getElementById('image-preview') as HTMLImageElement;  | 
 | 176 | +        if (!preview) {  | 
 | 177 | +          preview = document.createElement('img');  | 
 | 178 | +          preview.id = 'image-preview';  | 
 | 179 | +          preview.style.cssText = `  | 
 | 180 | +            max-width: 100%;  | 
 | 181 | +            max-height: 150px;  | 
 | 182 | +            margin-top: 10px;  | 
 | 183 | +            border: 1px solid #ddd;  | 
 | 184 | +            border-radius: 4px;  | 
 | 185 | +            cursor: pointer;  | 
 | 186 | +          `;  | 
 | 187 | +          preview.title = '点击查看大图';  | 
 | 188 | +          previewContainer.appendChild(preview);  | 
 | 189 | +        }  | 
 | 190 | + | 
 | 191 | +        preview.src = dataURL;  | 
 | 192 | +        (window as any).exportedImageData = {  | 
 | 193 | +          dataURL,  | 
 | 194 | +          format,  | 
 | 195 | +          timestamp: Date.now(),  | 
 | 196 | +        };  | 
 | 197 | + | 
 | 198 | +        status.textContent = '导出成功!';  | 
 | 199 | +        status.style.color = '#52c41a';  | 
 | 200 | + | 
 | 201 | +        // 添加点击预览功能  | 
 | 202 | +        preview.onclick = () => {  | 
 | 203 | +          window.open(dataURL, '_blank');  | 
 | 204 | +        };  | 
 | 205 | +      } catch (error) {  | 
 | 206 | +        status.textContent = '导出失败:' + (error as Error).message;  | 
 | 207 | +        status.style.color = '#ff4d4f';  | 
 | 208 | +        console.error('导出失败:', error);  | 
 | 209 | +      } finally {  | 
 | 210 | +        exportBtn.disabled = false;  | 
 | 211 | +      }  | 
 | 212 | +    };  | 
 | 213 | + | 
 | 214 | +    const downloadImage = () => {  | 
 | 215 | +      const exportData = (window as any).exportedImageData;  | 
 | 216 | +      if (!exportData || !exportData.dataURL) {  | 
 | 217 | +        status.textContent = '请先导出图片';  | 
 | 218 | +        status.style.color = '#faad14';  | 
 | 219 | +        setTimeout(() => {  | 
 | 220 | +          status.textContent = '';  | 
 | 221 | +        }, 2000);  | 
 | 222 | +        return;  | 
 | 223 | +      }  | 
 | 224 | + | 
 | 225 | +      try {  | 
 | 226 | +        const link = document.createElement('a');  | 
 | 227 | +        const extension = exportData.format;  | 
 | 228 | +        link.download = `l7-map-${new Date(exportData.timestamp).toISOString().slice(0, 19).replace(/:/g, '-')}.${extension}`;  | 
 | 229 | +        link.href = exportData.dataURL;  | 
 | 230 | +        link.click();  | 
 | 231 | + | 
 | 232 | +        status.textContent = '下载成功!';  | 
 | 233 | +        status.style.color = '#52c41a';  | 
 | 234 | +        setTimeout(() => {  | 
 | 235 | +          status.textContent = '';  | 
 | 236 | +        }, 2000);  | 
 | 237 | +      } catch (error) {  | 
 | 238 | +        status.textContent = '下载失败:' + (error as Error).message;  | 
 | 239 | +        status.style.color = '#ff4d4f';  | 
 | 240 | +        console.error('下载失败:', error);  | 
 | 241 | +      }  | 
 | 242 | +    };  | 
 | 243 | + | 
 | 244 | +    exportBtn.addEventListener('click', exportImage);  | 
 | 245 | +    downloadBtn.addEventListener('click', downloadImage);  | 
 | 246 | + | 
 | 247 | +    return container;  | 
 | 248 | +  };  | 
 | 249 | + | 
 | 250 | +  // 确保UI添加到地图容器中  | 
 | 251 | +  const mapContainer =  | 
 | 252 | +    typeof options.id === 'string' ? document.getElementById(options.id) : options.id;  | 
 | 253 | + | 
 | 254 | +  if (mapContainer) {  | 
 | 255 | +    mapContainer.style.position = 'relative';  | 
 | 256 | +    const ui = createExportUI();  | 
 | 257 | +    mapContainer.appendChild(ui);  | 
 | 258 | +  }  | 
 | 259 | + | 
 | 260 | +  return scene;  | 
 | 261 | +};  | 
0 commit comments