微信小程序 Canvas 签字 #95

简介: 微信小程序 Canvas 签字 #95

最近迫于签字结果返回太慢,所以需要把旋转图片由原先后端处理改为前端处理,查阅文档,研究一番,发现小程序上旋转,主要是通过canvas的translate、rotate完成。

Canvas坐标系统,由上图可得,Canvas 2D 环境中坐标系统和 Web 的坐标系统是一致的,有以下几个特点:

  1. 坐标原点 (0,0) 在左上角
  2. X坐标向右方增长
  3. Y坐标向下方延伸

伪代码


wx.canvasToTempFilePath({
    x: 0,
    y: 0,
    canvasId: 'myCanvas',
    success: (res) => {
        wx.getImageInfo({
            src: res.tempFilePath,
            success: (imageRes) => {
                const height = imageRes.height;
                const width = imageRes.width;
                this.setState({
                    canvasHeight: width,
                    canvasWidth: height
                });
                const context2 = wx.createCanvasContext('myCanvas2', this.$scope);
                context2.translate(height / 2, width / 2);
                context2.rotate(270 * Math.PI / 180);
                context2.drawImage(imageRes.path, -width / 2, -height / 2, width, height);
                context2.draw(false, () => {
                    this.getTempFilePath();
                });
            }
        });
    },
    fail: (error) => {
        console.error('canvasToTempFilePathfail', error);
    }
}, this);
// 获取图片url,安卓有性能问题,所以需要延迟
getTempFilePath(errorCount = 5) {
    setTimeout(() => {
        const { signInfo } = this.props;
        const { signers, signerNames } = this.state;
        wx.canvasToTempFilePath({
            x: 0,
            y: 0,
            canvasId: 'myCanvas2',
            success: (res) => {
                const signPic = this.fileTobase64(res.tempFilePath);
            },
            fail: (err) => {
                if(errorCount < 7) {
                    this.getTempFilePath(++errorCount);
                }
                console.error('canvasToTempFilePathfail', err);
            }
        }, this);
    }, errorCount * 100);
}
fileTobase64 = path => {
    return 'data:image/jpeg;base64,' + Taro.getFileSystemManager().readFileSync(path, 'base64');
};
render() {
    return (
        <Canvas
            canvasId="myCanvas"
            style={{ width: '305px', height: wx.getSystemInfoSync().windowHeight + 'px' }}
            id="myCanvas"
            disableScroll="false"
            onTouchStart={(e) => this.touchStart(e)}
            onTouchMove={(e) => this.touchMove(e)}
        />
        <Canvas
            canvasId="myCanvas2"
            id="myCanvas2"
            disableScroll="false"
            style={{ width: canvasWidth + 'px', height: canvasHeight + 'px' }}
        />
    );
}


旋转角度代码


wx.getImageInfo({
    src: path,
    success: (res) => {
        let canvasContext = wx.createCanvasContext('my-canvas', _this);
        // 下面按比例写死宽度高度是为了压缩图片提升上传速度,可按实际需求更改
        let rate = res.height / res.width;
        let width = 500;
        let height = 500 * rate;
        // 根据orientation值处理图片
        switch (res.orientation) { 
            case 'up':
                // 不需要旋转
                _this.setData({
                    canvasWidth: width,
                    canvasHeight: height,
                });
                canvasContext.drawImage(path, 0, 0, width, height);
                break;
            case 'down':
                // 需要旋转180度
                _this.setData({
                    canvasWidth: width,
                    canvasHeight: height,
                });
                canvasContext.translate(width / 2, height / 2);
                canvasContext.rotate(180 * Math.PI / 180);
                canvasContext.drawImage(path, -width / 2, -height / 2, width, height);
                break;
            case 'left':
                // 顺时针旋转270度
                _this.setData({
                    canvasWidth: height,
                    canvasHeight: width,
                });
                canvasContext.translate(height / 2, width / 2);
                canvasContext.rotate(270 * Math.PI / 180);
                canvasContext.drawImage(path, -width / 2, -height / 2, width, height);
                break;
            case 'right':
                // 顺时针旋转90度
                _this.setData({
                    canvasWidth: height,
                    canvasHeight: width,
                });
                canvasContext.translate(height / 2, width / 2);
                canvasContext.rotate(90 * Math.PI / 180);
                canvasContext.drawImage(path, -width / 2, -height / 2, width, height);
                break;
        }
    }
});


Canvas 2d


export default class Signature extends Component<IProps, IState> {
    constructor(props: IProps | Readonly<IProps>) {
        super(props);
        this.state = {
        };
    }
    componentDidMount() {
        // 放到下一个时间切片执行
        wx.nextTick(() => {
            const query = wx.createSelectorQuery();
            query
                .select('#myCanvas')
                .fields({ node: true, size: true })
                .exec(res => {
                    if (res && res[0]) {
                        this.initCanvas(res);
                    } else {
                        wx.nextTick(() => {
                            query
                                .select('#myCanvas')
                                .fields({ node: true, size: true })
                                .exec(res => {
                                    if (res && res[0]) this.initCanvas(res);
                                });
                        });
                    }
                });
        });
    }
    initCanvas = (res: any) => {
        const canvas = res[0].node;
        const ctx = canvas.getContext('2d');
        const dpr = wx.getSystemInfoSync().pixelRatio;
        canvas.width = res[0].width * dpr;
        canvas.height = res[0].height * dpr;
        this.context = ctx;
        this.context.lineWidth = 4.5;
        ctx.scale(dpr, dpr);
    };
    // 手指触摸动作开始
    touchStart = (e: any) => {
        this.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y);
    };
    // 手指触摸后移动
    touchMove = (e: any) => {
        this.context.lineTo(e.changedTouches[0].x, e.changedTouches[0].y);
        this.context.stroke();
        this.isClear = false;
        this.context.draw(true);
        this.context.moveTo(e.changedTouches[0].x, e.changedTouches[0].y);
    };
    // 清空画布
    clearCanvas = () => {
        this.signPath = '';
        this.isClear = true;
        this.context.draw();
        this.context.lineWidth = 4.5;
    };
    btnConfirm() {
        const query = wx.createSelectorQuery();
        query
            .select('#myCanvas')
            .fields({ node: true, size: true })
            .exec(res => {
                const canvas = res[0].node;
                wx.canvasToTempFilePath(
                    {
                        x: 0,
                        y: 0,
                        canvas,
                        success: (res: { tempFilePath: string }) => {
                            this.signPath = res.tempFilePath;
                        },
                        fail: () => {}
                    },
                    this.$scope
                );
            });
    }
    render() {
        return (
            <Canvas
                type="2d"
                style={{ width: '100%', height: '100%' }}
                id="myCanvas"
                disableScroll={false}
                onTouchStart={this.touchStart}
                onTouchMove={this.touchMove}
            />
        );
    }
}

自定义组件,没有 方法,放在 执行,如果 获取不到 实例,则通过 ,放到下一个时间切片获取。onReadydidmoutdidmoutCanvaswx.nextTick

如果不是自定义组件,页面组件,则通过 方法获取, 方案,该方案有很大的问题,无法清除画布,微信小程序官方 BUG,截止到 ,还未解决。onReadyCanvas 2d2021.06.03

目录
相关文章
|
6月前
|
前端开发 小程序 JavaScript
微信小程序canvas手写签字
微信小程序canvas手写签字
91 0
|
6月前
|
前端开发 小程序
微信小程序canvas画布绘制base64图片并保存图片到相册中
微信小程序canvas画布绘制base64图片并保存图片到相册中
196 0
|
1月前
|
前端开发 小程序 JavaScript
小程序 canvas 生成海报 一次搞掂
小程序 canvas 生成海报 一次搞掂
28 1
|
1月前
|
前端开发 小程序 JavaScript
微信小程序 canvas 备忘
微信小程序 canvas 备忘
36 0
|
4月前
|
前端开发 小程序
【微信小程序-原生开发】实用教程20 - 生成海报(实战范例为生成活动海报,内含生成指定页面的小程序二维码,保存图片到手机,canvas 系列教程)
【微信小程序-原生开发】实用教程20 - 生成海报(实战范例为生成活动海报,内含生成指定页面的小程序二维码,保存图片到手机,canvas 系列教程)
414 0
|
6月前
|
前端开发 小程序
微信小程序绘制canvas时在不同 设备上的大小不同的问题
微信小程序绘制canvas时在不同 设备上的大小不同的问题
256 0
|
6月前
|
前端开发 小程序
【微信小程序5】利用canvas实现纯色背景抠图功能
【微信小程序5】利用canvas实现纯色背景抠图功能
326 0
|
1月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
526 7
|
1月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
647 1
|
1月前
|
小程序 前端开发 测试技术
微信小程序的开发完整流程是什么?
微信小程序的开发完整流程是什么?
115 7