小程序跳转H5实现长截图功能;vue-cli3通过rem适配

本文介绍了如何在微信小程序中利用H5页面实现一键长图功能。通过vue-cli搭建H5项目,使用html2canvas插件进行截图,并通过rem适配不同机型。在H5页面中处理参数传递、动态表头匹配、截图样式等问题,同时解决在微信小程序中打开H5页面时的兼容性和性能问题。最终,通过打包部署,实现从微信小程序跳转到H5长图页面并成功截图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、需求:
  微信小程序部分页面需要一键长图的功能。
  通过html2canvas插件可以实现,具体可参考微信小程序实现一键长图并保存图片到相册。由于该插件只能在H5项目中使用,则需要截图的小程序页面点击后跳转到H5页面,把所需的token及接口参数带过去,在H5页面进行长截图并保存或转发,点击左上角返回即回到小程序。
在这里插入图片描述

二、思路:
  首先,考虑需要长截图的页面根据需求可能会迭代增加,新建了一个vue项目,基于vue-cli脚手架创建了一个项目;
  其次,H5页面最重要的就是适配,决定使用rem,根据相关资料发现使用postcss-pxtorem和lib-flexible可以实现vue项目自动将px转成rem ,进行相关下载,配置,在写具体页面时可直接使用px。
  最后,打包部署到服务上,微信小程序通过web-view加载该H5页面,在H5页面中引入html2canvas插件实现页面长截图。

 1. 搭建项目,通过rem适配机型
 2. 页面请求、路由跳转、插件引入、rem配置、跨域问题
 3. 截图样式,滚动、提示
 4. 小程序跳转H5传参,H5接收参数
 5. 动态表头匹配问题、截图时新结构的添加
 6. 取消截图,通过点击触发实现
 7. 项目打包部署,替换小程序中跳转的服务地址
 8. git创建仓库,上传代码

三、代码:
H5项目
首先安装这两个包
npm install amfe-flexible --save
npm install postcss-pxtorem --save-dev
在这里插入图片描述
app.vue

<template>
  <div id="app">
    <router-view></router-view>    
  </div>
</template>

<script>
export default {
   
  name: "app",
  data () {
   
    return {
   
      // token: ''
    }
  },
  created() {
   
    let params = window.location.href.split("?")[1]
    let token  = params.substring(params.lastIndexOf("=")+1)
    sessionStorage.setItem('token', token)
  }
};
</script>

<style>
*{
   
  margin: 0;
  padding: 0;
}
html,body{
   
  width: 100%;
  height: 100%;
}
#app {
   
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
  width: 100%;
  height: 100%;
  overflow-x:hidden;
}
</style>

main,js

import Vue from "vue";
import App from "./App.vue";
import {
   
  Toast,
} from "vant";
import "amfe-flexible/index.js";
import router from "./router";
import axios from 'axios'
import html2canvas from 'html2canvas'
Vue.prototype.$html2canvas = html2canvas

Vue.prototype.$http = axios
// import Echarts from 'echarts'
// Vue.prototype.echarts = Echarts
// Vue.use(Echarts)

Vue.use(Toast);

Vue.config.productionTip = false;

new Vue({
   
  router,
  render: h => h(App)
}).$mount("#app");

untils/request.js

import axios from 'axios'

const service = axios.create({
   
  // 请求基础路径
  // baseURL: process.env.VUE_APP_BASE_API,
  baseURL: '/jupiter/i',
  timeout: 5000 // 请求超时时间5秒
})

// 请求拦截器 给请求头设置token
service.interceptors.request.use(
  request => {
   
    // 携带token
    let token = sessionStorage.getItem('token')
    if (token) {
   
      request.headers['authorization'] = token
    }
    if (request.method === 'post') {
   
      request.params = {
   }
    }
    // eslint-disable-next-line no-unused-expressions
    error => {
   
      return Promise.reject(error)
    }
    return request
  }
)

// response interceptor
service.interceptors.response.use(
  response => {
   
    const res = response.data
    console.log('axios的res', res)
    const {
   status} = res
    switch (status) {
   
      // token失效!
      case 710:
        console.log('token失效,请返回小程序')
        break
      case 0:
        console.log('请返回小程序')
        break
      // 统一处理200和错误message
      case 200:
        return res.data
      default:
        console.log
    }
  },
  // 作用 catch的处理
  error => {
   
    const {
    response } = error
    if (response && response.status === 404) {
   
      return Promise.reject(error)
    }
    if (response && response.status === 500) {
   
      return Promise.reject(error)
    }
    if (response && response.status === 405) {
   
      return Promise.reject(error)
    }
    return Promise.reject(error)
  }
)

export default service

api/test.js

import service from '../untils/request.js';

// 列表
export function boxDataList (data) {
   
    return service({
   
        url: '/box/day/boxData/list',
        method: 'get',
        params: data
    })
}
// 大盘数据
export function boxDataMax (data) {
   
    return service({
   
        url: '/box/day/boxData/max',
        method: 'get',
        params: data
    })
}

vue.config.js

module.exports = {
   
  publicPath: '/',
  css: {
   
    loaderOptions: {
   
      postcss: {
   
        plugins: [
          require("postcss-pxtorem")({
   
            // 把px单位换算成rem单位
            rootValue: 75, // vant官方使用的是75
            selectorBlackList: ["vant", "mu"], // 忽略转换正则匹配项
            propList: ["*"]
          })
        ]
      }
    }
  },
  devServer: {
   
    open: true, //是否自动弹出浏览器页面
    host: "0.0.0.0",
    port: "8081",
    https: false,
    hotOnly: false,
    proxy: {
   
      "/jupiter/i": {
   
        target: "https://testdata.aaa.com",
        ws: true, //代理websockets
        changeOrigin: true, // 虚拟的站点需要更管origin
        pathRewrite: {
   
          //重写路径 比如'/api/aaa/ccc'重写为'/aaa/ccc'
          "^/": ""
        }
      }
    }
  }
};

router.index.js

import Vue from "vue";
import VueRouter from "vue-router";

Vue.use(VueRouter);

const router = new VueRouter({
   
  mode: 'history',
  base: '/',
  routes: [
    {
   
      path: '/dayList',
      name: '日榜',
      component: () => import('./../components/dayList.vue')
    },
    // {
   
    //   path: "/home",
    //   name: "年榜",
    //   component: () => import("./../components/Home.vue")
    // },
  ]
});

export default router;

components/dayList.vue

<template>
  <div class="dayListBox" @click="cancel">
    <div ref="area">
      <div class="logoBox" style="display: none">
        <img src="../assets/1.png" alt="">
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值