如何在Google Sheets中基于数据集自动在图片上映射绘制数据点

你希望基于Google Sheets数据集自动在这张底图上绘制对应格网点位的需求完全可以实现,你目前预先建好六边形格网中心像素坐标映射表、通过匹配拿到待绘制点位像素坐标的思路是完全可行的,剩下的绘制环节可以根据你的数据规模选以下两种方案:
示例效果参考

示例数据对应标注效果:
- #1 - 坐标(7,8) 对应点位
- #2 - 坐标(8,7) 对应点位
方案1:零代码实现(适合点位数量<100、不需要频繁更新数据的场景)
不需要写代码,用Sheets内置的散点图叠加底图就能实现:
- 第一步:固定底图尺寸
点击顶部菜单栏「插入」-「图片」-「在单元格上方插入图片」,上传你的六边形格网底图,右键图片选择「大小和位置」,输入你当初做像素坐标映射时使用的底图宽高像素值,锁定图片比例和位置,避免后续错位。 - 第二步:校正Y轴坐标
注意普通图像的像素坐标Y轴是从上到下计数的,但Google Sheets散点图的Y轴默认是从下到上计数,需要加一列辅助值做校正,公式为:校正Y坐标 = 底图总像素高度 - 原始像素Y坐标 - 第三步:叠加散点图层
选中所有点位的像素X坐标列、校正后的Y坐标列,插入散点图,在图表编辑器中调整参数:- 将图表背景、图表区边框都设为100%透明
- 隐藏所有网格线、坐标轴、坐标轴刻度、图例
- 把散点的大小、颜色调整为你需要的样式(比如示例中的红色圆点)
- 拖动调整散点图的绘图区尺寸,和下方的底图完全重合,此时所有散点就会精准落在对应六边形格网的中心位置
- 第四步:添加点位标签
如果需要显示#1、#2这类点位编号,在散点图设置中打开「数据标签」,标签来源选择你存储点位编号的列即可,最后可以把图表和底图组合成一个整体,方便导出使用。
方案2:Apps Script自动生成成品图(适合点位多、需要频繁更新数据的场景)
用脚本直接在底图上绘制点位,不需要手动对齐图层,每次更新数据后一键运行就能生成标注完成的成品图:
- 第一步:把你使用的六边形格网底图上传到Google Drive,右键点击文件-「获取链接」,从链接中提取文件ID(即链接中
d/和/view之间的字符串) - 第二步:打开存储数据的Google Sheets,点击顶部菜单栏「扩展程序」-「Apps Script」进入脚本编辑器,粘贴以下代码,把开头的配置参数替换成你自己的实际值:
function drawPointsOnHexMap() { // ========== 以下参数替换为你自己的内容 ========== const BASE_MAP_FILE_ID = "替换为你的底图在Google Drive中的文件ID"; const DATA_SHEET_NAME = "替换为你的数据所在的工作表名称"; const POINT_FILL_COLOR = "#ff2c2c"; // 点位填充色,这里是示例红色 const POINT_RADIUS = 7; // 点位半径,单位:像素 const SHOW_LABEL = true; // 是否显示点位编号 const LABEL_FONT_SIZE = 11; // 点位编号字体大小 // 数据列配置:按你的表结构调整,序号从0开始,0对应A列、1对应B列,以此类推 const COL_LABEL = 0; // 点位编号所在列 const COL_PIXEL_X = 2; // 像素X坐标所在列 const COL_PIXEL_Y = 3; // 像素Y坐标所在列 // ========== 以上参数替换为你自己的内容 ========== // 读取底图和数据 const baseMapBlob = DriveApp.getFileById(BASE_MAP_FILE_ID).getBlob(); const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(DATA_SHEET_NAME); const lastRow = sheet.getLastRow(); const rawData = sheet.getRange(2, 1, lastRow - 1, sheet.getLastColumn()).getValues(); // 临时用幻灯片做绘图画布,尺寸和底图完全一致 const tempDeck = SlidesApp.create("temp_hex_map_draw"); const tempSlide = tempDeck.getSlides()[0]; const tempImg = tempSlide.insertImage(baseMapBlob); const mapWidth = tempImg.getWidth(); const mapHeight = tempImg.getHeight(); tempSlide.getPageElements().forEach(el => el.remove()); tempDeck.setPageSize(mapWidth, mapHeight); tempSlide.insertImage(baseMapBlob, 0, 0, mapWidth, mapHeight); // 循环绘制所有点位 rawData.forEach(row => { const x = row[COL_PIXEL_X]; const y = row[COL_PIXEL_Y]; const label = row[COL_LABEL]; if (!x || !y) return; // 画圆点 const pointShape = tempSlide.insertShape( SlidesApp.ShapeType.ELLIPSE, x - POINT_RADIUS, y - POINT_RADIUS, POINT_RADIUS * 2, POINT_RADIUS * 2 ); pointShape.getFill().setSolidFill(POINT_FILL_COLOR); pointShape.getLine().setTransparent(); // 画编号标签 if (SHOW_LABEL && label) { const labelText = tempSlide.insertText( label.toString(), x + POINT_RADIUS + 3, y - LABEL_FONT_SIZE / 2 ); labelText.getTextStyle().setFontSize(LABEL_FONT_SIZE).setBold(true); } }); // 导出成品图到Drive根目录 const outputImg = tempSlide.getAs("image/png"); DriveApp.createFile(outputImg.setName("标注完成_六边形格网地图.png")); // 删除临时幻灯片文件 DriveApp.getFileById(tempDeck.getId()).setTrashed(true); }
- 第三步:保存脚本,点击运行按钮,第一次运行会弹出Google账号授权提示,按流程完成授权即可,脚本运行结束后,你的Google Drive根目录就会生成已经标注好所有点位的PNG格式成品图。
注意:如果运行后发现点位整体偏移,先确认你做像素坐标映射时使用的底图尺寸,和上传到Drive的底图尺寸完全一致,尺寸匹配的情况下点位不会出现错位。
内容的提问来源于stack exchange,提问作者plerpsandplerps
相关产品推荐
相关产品推荐

