uniapp开发微信小程序使用takeSnapshot截图保存分享

截图功能实现

核心技术说明

takeSnapshot 是微信官方提供的截图 API,用于截取当前页面中指定元素的内容。

重要提醒:

  • 微信小程序默认使用 WebView 渲染模式
  • takeSnapshot 只在 Skyline 渲染模式 下生效
  • 需要手动配置 Skyline 渲染引擎才能使用此功能

📖 参考文档 : takeSnapshot API 文档

配置步骤

1. 启用 Skyline 渲染引擎

manifest.json"mp-weixin" 配置中添加:

json 复制代码
{
  "mp-weixin": {
    "rendererOptions": {
      "skyline": {
        "defaultDisplayBlock": true,
        "disableABTest": true,
        "sdkVersionBegin": "3.0.1",
        "sdkVersionEnd": "15.255.255"
      }
    },
    "style": "v2",
    "componentFramework": "glass-easel"
  }
}

配置说明:

  • defaultDisplayBlock: 控制元素默认显示模式
  • disableABTest: 禁用 A/B 测试
  • sdkVersionBegin/End: 定义支持的微信 SDK 版本范围
  • style: "v2": 使用 v2 样式版本,支持现代化技术栈
  • componentFramework: 使用 glass-easel 组件框架

📖 参考文档 : Skyline 渲染引擎迁移指南

2. 配置页面渲染模式

pages.config.ts 中为需要截图的页面添加 Skyline 配置:

typescript 复制代码
{
  path: "sub-share/create-message-img-wx",
  style: {
    navigationBarTitleText: "分享页面",
    navigationStyle: "custom",
    renderer: "skyline",           // 启用 Skyline 渲染
    componentFramework: "glass-easel"
  }
}

实现代码

3. 页面截图实现

vue 复制代码
<template>
  <!-- 截图容器 -->
  <snapshot id="snapshotImg" class="screenshot-container">
    <!-- 你的页面内容 -->
    <view class="content">
      <!-- 这里放置需要截图的内容 -->
    </view>
  </snapshot>
</template>

<script setup lang="ts">
// 截图方法
const takeHiddenSnapshot = () => {
  uni
    .createSelectorQuery()
    .select("#snapshotImg")
    .node()
    .exec((res) => {
      if (!res || !res[0] || !res[0].node) {
        console.error("页面节点查询失败:", res);
        return;
      }
      const node = res[0].node;
      node.takeSnapshot({
        type: "arraybuffer",
        format: "png",
        success: ({ data }) => {
          console.log("隐藏页面截图成功", data);
          const fs = wx.getFileSystemManager();
          const filePath = `${wx.env.USER_DATA_PATH}/hidden_poster.png`;
          fs.writeFileSync(filePath, data, "binary");

          // 本地调试使用
          // saveImage(filePath); //保存图片
          // shareImage(filePath); //分享图片

          // 真机&体验版&线上 使用
          wxImageUploadBinary(filePath) //上传图片
            .then((uploadData) => {
              operationImage("share", uploadData.imageUrl);
            })
            .catch((error) => {
              console.error("截图上传失败:", error);
              reject(error);
            });
        },
        fail: (err) => {
          console.error("隐藏页面截图失败:", err);
          reject(err);
        },
      });
    });
};

const operationImage = (type, filePath) => {
  uni.downloadFile({
    url: filePath,
    success: (res) => {
      if (res.statusCode === 200) {
        console.log("下载成功");
        if (type === "share") {
          shareImage(res.tempFilePath);
        } else {
          saveImage(res.tempFilePath);
        }
      }
    },
    fail: (err) => {
      console.error("下载文件失败:", err);
    },
  });
};

const shareImage = (filePath) => {
  //分享图片
  wx.showShareImageMenu({
    path: filePath,
  });
};
const saveImage = (filePath) => {
  //保存图片
  wx.saveImageToPhotosAlbum({
    filePath,
    success: () => {
      console.log("图片已保存到相册");
      resolve(filePath);
    },
    fail: (err) => {
      console.error("保存失败:", err);
      reject(err);
    },
  });
};

// 上传图片到服务器
const wxImageUploadBinary = (filePath) => {
  const uploadUrl = `xxxxxxxxxxxx/image/upload`; //上传地址
  return new Promise((resolve, reject) => {
    uni.uploadFile({
      url: uploadUrl,
      filePath: filePath, //文件
      name: "image", //后端接收key
      header: {},
      success: (res) => {
        if (res.statusCode === 200) {
          try {
            const result = JSON.parse(res.data);
            if (result.success) {
              resolve(result);
            } else {
              reject(new Error(result.message || "上传失败"));
            }
          } catch (error) {
            reject(new Error("响应解析失败"));
          }
        } else {
          reject(new Error(`上传失败: ${res.statusCode}`));
        }
      },
      fail: (error) => {
        reject(error);
      },
    });
  });
};

</script>


<style lang="scss" scoped>
.screenshot-container {
  width: 100%;
  min-height: 100vh;
  background-color: #f5f5f5;
}

.content {
  padding: 20rpx;
  // 你的样式
}
</style>

重要注意事项

⚠️ Skyline 渲染引擎兼容性问题

  1. 样式兼容性:

    • display: flex 支持有限
    • position: sticky 不完全支持
    • backdrop-filter: blur 不支持
    • overflow-scrolling: touch 处理方式不同
  2. 全局影响:

    • 启用 Skyline 后,所有页面的 button 组件样式可能受影响
    • 需要添加自定义样式覆盖默认样式
    • 建议只在必要的页面启用 Skyline 渲染
  3. 布局差异:

    • Skyline 与 WebView 在文本渲染、间距计算等方面存在差异
    • 可能出现意外的空行或间距问题
    • 需要针对 Skyline 添加特殊样式重置

📱 真机调试说明

  1. 本地路径限制:

    • wx.env.USER_DATA_PATH 在真机上有访问限制
    • 生产环境建议上传到服务器获取在线地址
    • 开发环境可直接使用本地路径
  2. 性能优化:

    • 截图文件建议压缩后上传
    • 大图片可能导致内存问题
    • 及时清理临时文件

🔧 故障排除

常见问题及解决方案:

  1. takeSnapshot 报错:

    • 确认页面已配置 renderer: "skyline"
    • 检查 manifest.json 中的 Skyline 配置
    • 确保微信开发者工具版本支持 Skyline
  2. 截图内容不完整:

    • 检查 snapshot 容器的尺寸设置
    • 确认内容已完全加载
    • 避免使用 position: fixed 等特殊定位
  3. 样式异常:

    • 为 Skyline 页面添加专门的样式重置
    • 使用 :style 而非 class 进行动态样式控制
    • 测试不同版本微信客户端的兼容性

项目特定配置

本项目使用了以下技术栈配置,确保截图功能的稳定性:

  • style: "v2" - 支持现代化 CSS 特性
  • form-data 格式文件上传
  • 多环境构建支持(开发/测试/生产)

API 参考


相关推荐
FlowGram3 小时前
Flowgram 物料库建设思考与实践
前端
用户22152044278003 小时前
Promise实例方法和async、await语法糖
前端·javascript
snows_l4 小时前
MacOS 通过Homebrew 安装nvm
前端·macos
前端开发爱好者4 小时前
下一代全栈框架:Deno + Vite 的结合体!
前端·javascript·后端
CUGGZ4 小时前
前端部署,又有新花样?
前端·javascript
Zz_waiting.4 小时前
Javaweb 14.4 Vue3 视图渲染技术
前端·javascript·vue.js
前端开发爱好者4 小时前
一键 i18n 国际化神库!适配 Vue、React!
前端·javascript·vue.js
前端开发爱好者4 小时前
Vite 移动端调试利器!开发效率飙升 300%!
前端·javascript·vue.js
BillKu5 小时前
容器元素的滚动条回到顶部
前端·javascript·vue.js