当前位置: 首页 > news >正文

获取iframe中canvas画面

截屏commit信息 https://github.com/goplus/builder/commit/566a8a3e4c7cf61cab2c5f5eec5c7d0bd723b6d6(同时也复用到了录屏中https://github.com/goplus/builder/commit/06cd95c434fe5a4ff90792e4d5c36b7b76aa73c9)

目标:获取 XBuildr 游戏画面插入到海报中

考虑到是否同源会影响资源获取策略,于是我先try了iframe.contentWindow.document看看,结果是同源的

接着我用开发者工具找到了游戏画面为 id: game-canvas 

然后取 runner 里面添加了截屏方法并且一层层往上暴露

ProjectRunner (统一接口)
├── ProjectRunnerV2 (直接管理iframe)
└── ProjectRunnerV1 └── IframeDisplay (实际管理iframe)
// 添加截图方法
const takeScreenshot = async () => {const iframeWindow = iframe.value?.contentWindow as IframeWindow | nullif (!iframeWindow) {throw new Error('iframe未准备好')}// 获取iframe内的game-canvas元素const gameCanvas = iframeWindow.document.querySelector('#game-canvas') as HTMLCanvasElementif (!gameCanvas) {throw new Error('未找到game-canvas元素')}// 直接从canvas获取图像数据const dataURL = gameCanvas.toDataURL('image/png')return {dataURL,width: gameCanvas.width,height: gameCanvas.height}
}// 暴露截图方法
defineExpose({takeScreenshot
})

然后在project.vue运行过程中通过事件应用

const handleScreenshot = useMessageHandle(async () => {try {// 获取项目运行器引用const projectRunner = projectRunnerRef.valueif (!projectRunner) {throw new Error('项目运行器未准备好')}// 使用项目运行器的截图方法const screenshot = await projectRunner.takeScreenshot()if (!screenshot) {throw new Error('截图方法返回空结果')}// 设置截图数据screenshotDataUrl.value = screenshot.dataURLscreenshotWidth.value = screenshot.widthscreenshotHeight.value = screenshot.heightconsole.log('成功从游戏canvas获取截图', screenshot.width, 'x', screenshot.height)isScreenshotModalVisible.value = true} catch (error) {console.error('截图失败:', error)throw error}},{ en: 'Failed to take screenshot', zh: '截屏失败' }
)

可以简化为

// 统一的截图服务
class ScreenshotService {static async takeScreenshot(iframeElement: HTMLIFrameElement) {const iframeWindow = iframeElement.contentWindowconst gameCanvas = iframeWindow.document.querySelector('#game-canvas')return gameCanvas.toDataURL('image/png')}
}// 在需要的地方直接调用
const screenshot = await ScreenshotService.takeScreenshot(iframeRef.value)

http://www.dtcms.com/a/331436.html

相关文章:

  • 爬虫数据存储全攻略:从 Robots 协议到文件存储
  • C++11新特性深度解析
  • Linux软件下载菜单脚本
  • Effective C++ 条款41:理解隐式接口和编译期多态
  • 系统设计——DDD领域模型驱动实践
  • 深入浅出词向量(Word2Vec):从理论到实践
  • 数据结构初阶(13)排序算法-选择排序(选择排序、堆排序)(动图演示)
  • 【Java 后端】Spring Boot 集成 JPA 全攻略
  • HTTPS 工作原理
  • 电池充放电测试仪厂家:技术深耕与场景驱动的行业进阶
  • Java使用Apache POI读取Excel文件
  • Vue浅学
  • 深入解析 GitHub Actions 工作流文件编写:从入门到实战
  • 简单的 HTTPS 学习
  • 第四天-创建一个Classic CAN(经典CAN2.0)/CANFD的系统描述ARXML文件
  • 读From GPT-2 to gpt-oss: Analyzing the Architectural Advances
  • IPv6互联网地址解析
  • 从合规到卓越:全星QMS如何成为制造企业的质量战略引擎
  • linux 软硬链接详解
  • 《算法导论》第 25 章:所有结点对的最短路径问题
  • 计算机视觉CS231n学习(8)
  • 12 ABP Framework 租户管理
  • 介绍一下 自动驾驶 感知多任务训练模型设计
  • 面试题:如何用Flink实时计算QPS
  • 第4节 神经网络从公式简化到卷积神经网络(CNN)的进化之路
  • 第三章、GRU(门控循环网络,Gated Recurrent Unit)
  • redis中分布式锁的应用
  • 【js】让项目支持倾听和朗读AI技术
  • RTC时钟倒计时数码管同步显示实现(STC8)
  • AI模型选型:租快艇还是造航母?