H5 长按dom保存为图片

34 篇文章 0 订阅
13 篇文章 1 订阅


在这里插入图片描述

npm: longpress-save2img-h5

核心逻辑

在 H5 实现一个长按 dom 节点,将当前节点保存为图片的功能,核心步骤如下

  • 实现长按功能
  • dom 转 canvas

长按功能

  1. 封装为一个class类,以保证能在页面中调用多个实例进行多个dom盒子的转换canvas;
  2. 定义为从开始触摸屏幕touchstart 到 结束触摸屏幕 touchend 连续 700ms 视为长按;

dom 转 canvas

我们选择 html2canvas 来实现这个功能,它是非常强大的!感谢开源社区,感谢大佬!

当然并不是所有的页面元素都可以进行转换的,下面是不支持的情况:

  • 不支持 iframe
  • 不支持跨域图片(可以先将线上图片转换成 base64,然后用 base64 作为图片路径)
  • 不支持 flash
  • 不支持 transform、transition 过渡、animation 动画(备注:transform 初始布局是可以的,但是不能参与动画类的操作)

因此在测试代码中也加入了一些场景的测试,比如 transformtransitioncanvasanimation

代码

核心代码

longPressSave2Img.js

import html2canvas from 'html2canvas'

// 长按 dom 保存 dom 为图片
class LongPress {
  constructor(el, cb) {
    this.element = el
    this.timer = null
    this.init(cb)
  }

  init (cb) {
    this.touchStart(cb)
    this.touchEnd()
  }

  // 开始触摸
  touchStart(cb) {
    this.element.addEventListener('touchstart', function (e) {
      e.preventDefault()
      this.timer = setTimeout(() => {
        cb?.()
      }, 700)
    }, { passive: false })
  }

  // 结束触摸
  touchEnd () {
    this.element.addEventListener('touchend', function (e) {
      e.preventDefault()
      clearTimeout(this.timer)
      this.timer = null
    }, { passive: false })
  }

  // htmlToCanvas
  htmlToCanvas({ mime, encoderOptions, ...html2canvasOpts }, cb) {
    html2canvas(this.element, html2canvasOpts).then(canvas => {
      try {
        const imgUrl = canvas.toDataURL(mime, encoderOptions); // 此方法可以设置截图质量(0-1)
        cb?.({
          flag: 1,
          data: imgUrl
        })
      } catch (err) {
        cb?.({
          flag: 0,
          message: err.message
        })
      }
    });
  }
}

export default LongPress

测试代码

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>绘制图片</title>
  <style>
      canvas {
          border: 1px solid red;
      }
      #box1 {
          width: 300px;
      }
      .base {
          transform: translate(100px);
          width: 100px;
          height: 100px;
          display: inline-block;
          background-color: #0EA9FF;
          border-width: 5px;
          border-style: solid;
          border-color: #5daf34;
          transition-property: width,height,background-color,border-width;
          transition-duration: 2s;
          transition-timing-function: ease-in;
          transition-delay: 500ms;
      }

      @-ms-keyframes boke /* -ms-为了兼容IE 浏览器*/
      {
          0%   {background: green;}
          25%  {background: yellow;}
          50%  {background: blue;}
          100% {background: red;}
      }

      @-moz-keyframes boke /* -moz-为了兼容Firefox 浏览器*/
      {
          0%   {background: green;}
          25%  {background: yellow;}
          50%  {background: blue;}
          100% {background: red;}
      }

      @-webkit-keyframes boke /* -webkit-为了兼容Safari 和 Chrome 浏览器*/
      {
          0%   {background: red;}
          25%  {background: yellow;}
          50%  {background: blue;}
          100% {background: green;}
      }

      @-o-keyframes boke /*-o-为了兼容 Opera浏览器 */
      {
          0%   {background: red;}
          25%  {background: yellow;}
          50%  {background: blue;}
          100% {background: green;}
      }

      div {
          animation-name: boke;
          animation-duration: 5s;
          animation-timing-function: linear;
          animation-delay: 2s;
          animation-iteration-count: infinite;
          animation-direction: alternate;
          animation-play-state: running;
      }

      html, body{
          margin: 0;
          padding: 0;
      }
  </style>
</head>

<body>
<div id="box1">
  <div class="base"></div>
  <h5>transition配合transform一起使用</h5>
  <canvas id="box-canvas"></canvas>
</div>
<div id="box2">
  <div>box 2</div>
  <div>box 2</div>
  <div>box 2</div>
  <div>box 2</div>
</div>
<script>
</script>
</body>
</html>
js
import LongPressSave2Img from './longPressSave2ImgCallback'
import photo from "./static/吕布.jpeg";

// 创建高清 Canvas
function createHDCanvas (w=300,h=150) {
  var ratio = window.devicePixelRatio || 1;
  var canvas = document.getElementById('box-canvas');
  canvas.width = w * ratio; // 实际渲染像素
  canvas.height = h * ratio; // 实际渲染像素
  canvas.style.width = `${w}px`; // 控制显示大小
  canvas.style.height = `${h}px`; // 控制显示大小
  // setTransform() 允许您缩放、旋转、移动并倾斜当前的环境
  canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
  return canvas;
}

// 画一个canvas
const drawCanvas = () => {
  var canvas = createHDCanvas(300,190)
  var context = canvas.getContext("2d");
  var img = new Image();
  img.src = photo;
  img.onload = function () {
    context.drawImage(img,0,0,300,190)
  }
}
drawCanvas()

// ===================

const el = document.querySelector('#box1')
const long1 = new LongPressSave2Img(el, () => {
  console.log('longPress then');
  const r = window.confirm("要保存为图片吗?");
  if(r === true){
    long1.htmlToCanvas({ mime: 'image/jpeg' }, ({ flag, data }) => {
      if (flag) {
        console.log("base64编码数据:", data);
        const a = document.createElement('a')
        a.href = data
        a.download = 'base64编码数据'
        a.click()
      }
    })
  }
})

const el2 = document.querySelector('#box2')
const long2 = new LongPressSave2Img(el2, () => {
  console.log('longPress then');
  const r = window.confirm("要保存为图片吗?");
  if(r === true){
    long2.htmlToCanvas({}, ({ flag, data }) => {
      if (flag) {
        console.log("base64编码数据:", data);
        const a = document.createElement('a')
        a.href = data
        a.download = 'base64编码数据'
        a.click()
      }
    })
  }
})
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__畫戟__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值