美文网首页小程序微信小程序(应用号)微信小程序
微信小程序:截图组件welCropper,实现原理及其使用

微信小程序:截图组件welCropper,实现原理及其使用

作者: tomfriwel | 来源:发表于2017-09-22 10:29 被阅读5275次
    封面 截图

    最近做项目的时候,需要做一个截图功能。用了一个别人写的截图工具,发现截出的图质量下降了,但是我们图片要用来做识别, 需要保证截出的图质量不下降。而且也不支持通过拖动来调整截图框的大小。所以这个截图工具无法满足需求。因为所以,就自己动手写了一个截图组件。

    下面介绍一下实现原理和使用方法。

    实现原理

    组件wxml的层次结构图如下:

    hierarchy.png
    • original canvas 用来绘制原图大小的图片,这样能保证截图后的质量不会下降,这个canvas是隐藏的。
    • movable-areamovable-view的容器,是官方提供的拖拽移动组件,用来移动截取框的四个角。这个组件支持多个点同时移动。
    • scale canvas用来绘制适应屏幕比例大小的图片(aspectFit),因为通常原图大小是超过屏幕长宽的。(一开始白线框和图片都在这一层,但后来发现每次移动都要绘制一次图片,这样会造成卡顿、性能下降。所以就想到通过增加一个move canvas来专门绘制白线框来降低绘制图片带来的资源消耗,因为图片是静止的,不需要重复绘制。)
    • move canvas是根据四个movable-view的位置绘制出截图框。

    最后截图,通过四个点的位置计算出截图框的位置,然后放大对应原图大小的位置,得到在原图中的(x, y, width, height),最后通过官方提供的canvas接口截图。

    wx.canvasToTempFilePath({
      x: x,
      y: y,
      width: w,
      height: h,
      destWidth: w,
      destHeight: h,
      canvasId: 'originalCanvas',
      success: function (res) {
      }
    )}
    

    旋转原理

    设置旋转圆点
    旋转

    特点

    • 保证截图质量不会被压缩(也可以选择压缩图)
    • 截图框能够通过拖拽四个角来调整选区大小

    使用

    假设我们的应用文件结构如下:

    
    ./
    ├── app.js
    ├── app.json
    ├── app.wxss
    ├── pages
    │   └── index
    │       ├── index.js
    │       ├── index.json
    │       ├── index.wxml
    │       └── index.wxss
    └── welCropper
        ├── welCropper.js
        ├── welCropper.wxml
        └── welCropper.wxss
    

    调用组件时,需要传入cropperDatacropperMovableItemscropperChangableData,因为数据和事件都是绑定在Page上的,所以要避免使用组件里面已经被占用的命名。
    /pages/index/index.wxml

    <!-- 引入组件 -->
    <import src="/welCropper/welCropper.wxml" />
    
    <!-- 调用组件 -->
    <template is="welCropper" data="{{data:cropperData, cropperMovableItems:cropperMovableItems, cropperChangableData:cropperChangableData}}"></template>
    
    <!-- 用于选择图片,传入cropper中 -->
    <button bindtap='selectTap'>select image</button>
    

    /pages/index/index.js

    // 获取显示区域长宽
    const device = wx.getSystemInfoSync()
    const W = device.windowWidth
    const H = device.windowHeight - 50
    
    let cropper = require('../../welCropper/welCropper.js');
    
    console.log(device)
    
    Page({
        data: {
        },
        onLoad: function () {
            var that = this
            // 初始化组件数据和绑定事件
            cropper.init.apply(that, [W, H]);
        },
        selectTap() {
            var that = this
    
            wx.chooseImage({
                count: 1, // 默认9
                sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
                sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
                success(res) {
                    const tempFilePath = res.tempFilePaths[0]
                    console.log(tempFilePath)
                    
                    // 将选取图片传入cropper,并显示cropper
                    // mode=rectangle 返回图片path
                    // mode=quadrangle 返回4个点的坐标,并不返回图片。这个模式需要配合后台使用,用于perspective correction
                    let modes = ["rectangle", "quadrangle"]
                    let mode = modes[0]   //rectangle, quadrangle
                    that.showCropper({
                        src: tempFilePath,
                        mode: mode,
                        sizeType: ['original', 'compressed'],   //'original'(default) | 'compressed'
                        callback: (res) => {
                            if (mode == 'rectangle') {
                                console.log("crop callback:" + res)
                                wx.previewImage({
                                    current: '',
                                    urls: [res]
                                })
                            }
                            else {
                                wx.showModal({
                                    title: '',
                                    content: JSON.stringify(res),
                                })
    
                                console.log(res)
                            }
    
                            // that.hideCropper() //隐藏,我在项目里是点击完成就上传,所以如果回调是上传,那么隐藏掉就行了,不用previewImage
                        }
                    })
                }
            })
        }
    })
    
    

    最后引入组件的样式
    /pages/index/index.wxss

    @import "/welCropper/welCropper.wxss";
    

    注意

    • 因为wx.canvasToTempFilePath输出的是.png图片,截出来的图有可能远远大于原图(比如3通道图变成4通道的图)

    源代码

    如果出现什么bug、问题或者建议可以告诉我,我会尽量改进。

    效果图

    效果动图mode=rectangle 效果动图mode=quadrangle 效果图mode=rectangle

    如果将movable-view显示出来是这样的:

    显示movable-view后 mode=quadrangle

    相关文章

      网友评论

      • gefucai:能不能设置截图框的尺寸啊,比如选择2寸,3寸,截图框根据比例调整,截图框不能拖动啊
        tomfriwel:@ge_efbd 正方形的话代码的beta页面有。其他比例没有。我这个比例操作不灵活,github有一个截图的,功能比较多,你可以找找
      • 林义满:回复了,你看到了吗?:smile:
      • 林义满:我看到你有写正在制作 正方形,什么时候能做啊亲,
        林义满:你有微信吗?
        林义满:@tomfriwel 哈哈,很多小朋友都需要你的这个正方形,我给你点动力吧
        tomfriwel:@林义满 拖延症晚期患者:joy:
      • cc833def6ed1:这个插件怎样怎么加弹出框啊,还有就是你这个原图点击没效果啊
        tomfriwel:@18512187845 你直接问吧,如果有截图可以到github去提问
        cc833def6ed1:@tomfriwel 你微信多少,我加你
        tomfriwel:@18512187845 没效果是什么意思?点击后的确不会有什么界面上的反馈,只会按钮变绿
      • 8f2a14652c38:有没有人试过在ipad mini使用这个控件,我的小程序用了之后,在ipad mini里面无法截图,只显示图片,截图框等都没有显示出来
        tomfriwel:因为iPad是最近才能使用小程序的,我也没有测试过,所以目前也不太清楚。你也可以尝试自己调试一下。我会看看的
      • cc833def6ed1:怎样将四个角的圆圈去掉
        tomfriwel:@18512187845 组件wxss里可以设置opacity
      • 高杉_55cd:哥,怎么实现左右移动截图区域
        tomfriwel:@高杉_55cd 点四个角拖放选区
      • 3aa68f9c7ff2:大哥,能不能 配置 正方形 比例
        3aa68f9c7ff2:@tomfriwel 期待你的更新, 我修改了很久都不行
        tomfriwel:看看
        3aa68f9c7ff2:头像都是用正方形的
      • d026ef3ab211:您好 在带有虚拟按键的安卓机 会出现cropper button栏不显示的情况
        d026ef3ab211:@tomfriwel 对,推荐改为顶部,可以少很多事情.(比心)
        tomfriwel:底部的操作按键?
      • 68e94e5ea9bc:你好,我试了下,截图框子不能拖动截图 ,要选一块地放截图不得行
        tomfriwel:@大明湖畔城管 这个本来就是不能移动的,你可以两根手指同时按住两个点进行拖动
        68e94e5ea9bc:@tomfriwel 能截图 不能移动截图框 操作很别扭
        tomfriwel:@大明湖畔城管 你是说不能移动截图框?还是不能截图?

      本文标题:微信小程序:截图组件welCropper,实现原理及其使用

      本文链接:https://www.haomeiwen.com/subject/zgltextx.html