uniapp横屏签字功能
在开发微信小程序或者uniapp的时候经常会遇见需要签字功能,以下代码直接使用即可,注意的是这个不是组件,而是单独的一个签字画面
使小程序中的页面支持屏幕旋转的方法是:在 app.json 的 window 段中设置 "pageOrientation": "auto" ,
或在页面page.json 文件中配置 "pageOrientation": "auto"
注意微信小程序当中签字安卓版本底色为黑色的解决方法
mounted() {
this.canvasCtx = uni.createCanvasContext("canvas_sign", this);
this.canvasCtx.lineWidth = 6;
this.canvasCtx.lineCap = "round";
this.canvasCtx.lineJoin = "round";
this.canvasCtx.setStrokeStyle("#000");
this.canvasCtx.setFillStyle('#fff');
this.canvasCtx.fillRect(0, 0, uni.upx2px(750), uni.upx2px(1200));
},
1、主题部分 这段就是简简单单的布局,你们可以使用其他的布局方式
<template>
<view class="page-content" style="width:700rpx;height: 100%;">
<view class="form" style="width:700rpx;height: 100%;">
<view class="form-content" style="width:700rpx;height: 100%;background-color:#fff;">
<canvas style="width:700rpx;height: 100%;background-color:#fff;" class="form-content__canvas"
canvas-id="canvas_sign" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"
disable-scroll="true"></canvas>
</view>
<view class="form-footer">
<button class="form-footer__reset" @click="autographClick(1)">重置</button>
<button class="form-footer__save" @click="autographClick(2)">保存</button>
</view>
</view>
</view>
</template>
注意 在微信小程序当中,canvas签字在安卓版本背景底色为透明度,导致为黑色,但是在苹果可使用,这个问题解决办法就是设置背景底色。记得要做清空,否则不生效
<script>
export default {
data() {
return {
canvasCtx: null,
points: [],
hasSign: false,
isInit: false
};
},
mounted() {
this.canvasCtx = uni.createCanvasContext("canvas_sign", this);
this.canvasCtx.lineWidth = 6;
this.canvasCtx.lineCap = "round";
this.canvasCtx.lineJoin = "round";
this.canvasCtx.setStrokeStyle("#000");
this.canvasCtx.setFillStyle('#fff');
this.canvasCtx.fillRect(0, 0, uni.upx2px(750), uni.upx2px(1200));
},
methods: {
touchstart: function(e) {
e.preventDefault();
if (!this.isInit) {
this.isInit = true;
this.autographClick(1);
}
let startX = e.changedTouches[0].x;
let startY = e.changedTouches[0].y;
let startPoint = {
X: startX,
Y: startY
};
this.points.push(startPoint);
this.canvasCtx.beginPath();
},
touchmove: function(e) {
e.preventDefault();
let moveX = e.changedTouches[0].x;
let moveY = e.changedTouches[0].y;
let movePoint = {
X: moveX,
Y: moveY
};
this.points.push(movePoint);
let len = this.points.length;
if (len >= 2) {
this.draw();
this.canvasCtx.stroke();
}
},
touchend: function() {
this.points = [];
this.canvasCtx.draw(true);
},
draw: function() {
let point1 = this.points[0];
let point2 = this.points[1];
this.points.shift();
this.canvasCtx.moveTo(point1.X, point1.Y);
this.canvasCtx.lineTo(point2.X, point2.Y);
this.canvasCtx.stroke();
this.canvasCtx.draw(true);
this.hasSign = true;
},
autographClick(type) {
let that = this;
if (type === 1) {
this.hasSign = false;
uni.getSystemInfo({
success: function(res) {
let canvas = uni.createSelectorQuery().select(".form-content__canvas");
canvas.boundingClientRect().exec(function(data) {
let canvasw = Math.ceil(data[0].width);
let canvash = Math.ceil(data[0].height);
that.canvasCtx.clearRect(0, 0, canvasw, canvash);
that.canvasCtx.fillRect(0, 0, uni.upx2px(750), uni.upx2px(1200));
that.canvasCtx.draw(true);
});
}
});
} else {
if (!this.hasSign) {
uni.showToast({
title: "签名不能为空",
icon: "none",
duration: 2000
});
return;
}
uni.getSystemInfo({
success: function(res) {
let canvas = uni.createSelectorQuery().select(".form-content__canvas");
canvas.boundingClientRect().exec(function(data) {
console.log(data)
let canvasw = Math.ceil(data[0].width);
let canvash = Math.ceil(data[0].height);
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: canvasw,
height: canvash,
destWidth: canvasw,
destHeight: canvash,
fileType: "jpg",
canvasId: "canvas_sign",
success: function(res) {
console.log(res)
let base64Data = uni.getFileSystemManager()
.readFileSync(res.tempFilePath, "base64");
if (type === 2) {
that.base64ToPath(base64Data);
}
},
fail: function(err) {
console.log("图片导出失败:", err);
}
});
});
}
});
}
},
base64ToPath(tempFile) {
uni.showLoading({
title: "正在上传中..."
});
setTimeout(() => {
uni.showToast({
title: "生成签名成功",
duration: 2000,
icon: "none"
});
}, 1000);
console.log(tempFile, '签字图片')
uni.navigateBack({
delta: 1,
success: function() {
uni.$emit('paramChanged', tempFile);
}
})
}
}
};
</script>
css布局
<style lang="scss" scoped>
@function tovmin($rpx) {
@return #{$rpx * 100 / 750}vmin;
}
.page-content {
width: 100%;
height: 100%;
.form {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
.form-content {
width: 100%;
height: 100%;
&__canvas {
height: calc(100vh - tovmin(20) - tovmin(120) - constant(safe-area-inset-bottom));
height: calc(100vh - tovmin(20) - tovmin(120) - env(safe-area-inset-bottom));
width: 100vw;
}
}
.form-footer {
padding-top: tovmin(20);
height: calc(tovmin(120) + constant(safe-area-inset-bottom));
height: calc(tovmin(120) + env(safe-area-inset-bottom));
width: 100%;
display: flex;
flex-direction: row;
background: #FFFFFF;
box-shadow: 0 tovmin(4) tovmin(20) tovmin(2) rgba(183, 183, 183, 0.20);
button {
width: 20vw;
height: tovmin(88);
line-height: tovmin(88);
border-radius: tovmin(48);
text-align: center;
font-size: tovmin(36);
font-weight: bold;
}
button::after {
border: none;
}
&__reset {
color: #008AFE;
border: tovmin(1) solid #008AFE;
}
&__save {
background-image: linear-gradient(135deg, #1BC5FF 0%, #008AFE 100%);
}
&__preview {
color: #008AFE;
border: tovmin(1) solid #008AFE;
}
}
}
}
</style>