最近项目组要求做一个移动端手写签名的组件,效果图如下
去查了很多资料,也借鉴了很多别人写好的例子,最终完成,记录一下
因为需要横屏签名,所以有监听手机屏幕,如果是手机屏幕锁定的情况下就通过代码旋转页面div实现横屏效果,如果手机屏幕自己旋转了,那就直接正常显示
项目签名的canvas是在sign-canvas组件的基础上修改的https://github.com/richerdyoung/vue-sign-canvas,同时横屏显示借鉴了关于移动端页面强制竖屏https://www.cnblogs.com/daniao11417/p/9524374.html 文章,旋转base64是参考canvas实现手写签名并旋转base64图片https://www.shangmayuan.com/a/5e1c769abd854f489ea8baf6.html文章,修修补补最后做出了上图效果,记录一下,格式上面小细节还不太完善,后面再修改
packages文件直接去https://github.com/richerdyoung/vue-sign-canvas链接下载后复制过来就可以了,复制之后去自己项目的main.js进行组件全局注册,注册完成在自己页面使用即可
//全局注册 main.js import SignCanvas from 'sign-canvas'; Vue.use(SignCanvas)
这个是main.vue中我改动后的代码
const l = this.canvas.offsetLeft;
const t = this.canvas.offsetTop;加了这两个去矫正手指落点偏差
bindEvent() {
// pc事件
//鼠标按下 => 下笔
this.canvas.addEventListener("mousedown", e => {
e && e.preventDefault() && e.stopPropagation();
this.writeBegin({
x: e.offsetX || e.clientX,
y: e.offsetY || e.clientY
});
});
//书写过程 => 下笔书写
this.canvas.addEventListener("mousemove", e => {
e && e.preventDefault() && e.stopPropagation();
this.config.isWrite && this.writing({ x: e.offsetX, y: e.offsetY });
});
//鼠标松开 => 提笔
this.canvas.addEventListener("mouseup", e => {
e && e.preventDefault() && e.stopPropagation();
this.writeEnd({ x: e.offsetX, y: e.offsetY });
});
//离开书写区域 => 提笔离开
this.canvas.addEventListener("mouseleave", e => {
e && e.preventDefault() && e.stopPropagation();
this.writeEnd({ x: e.offsetX, y: e.offsetY });
});
// app事件
//手指按下 => 下笔
this.canvas.addEventListener("touchstart", e => {
e && e.preventDefault() && e.stopPropagation();
const touch = e.targetTouches[0];
// 这个是为了解决移动端手指落点偏移问题
const l = this.canvas.offsetLeft;
const t = this.canvas.offsetTop;
// const t=0
this.writeBegin({
x: touch.pageX - l || touch.clientX - l,
y: touch.pageY - t || touch.clientY - t
});
});
//手指移动 => 下笔书写
this.canvas.addEventListener("touchmove", e => {
e && e.preventDefault() && e.stopPropagation();
const touch = e.targetTouches[0];
const l = this.canvas.offsetLeft;
const t = this.canvas.offsetTop;
// const t=0
this.config.isWrite &&
this.writing({ x: touch.pageX - l, y: touch.pageY - t });
});
//手指移动结束 => 提笔离开
this.canvas.addEventListener("touchend", e => {
e && e.preventDefault() && e.stopPropagation();
const tcs = e.targetTouches;
const ccs = e.changedTouches;
const touch =
(tcs && tcs.length && tcs[0]) || (ccs && ccs.length && ccs[0]);
const l = this.canvas.offsetLeft;
const t = this.canvas.offsetTop;
// const t=0
this.writeEnd({ x: touch.pageX - l, y: touch.pageY - t });
});
},
这个是签名的页面index.vue,用来展示签完的名字
<template>
<div class="sign b-white">
<van-nav-bar title="我的签名" left-arrow @click-left="onClickLeft"/>
<div class="img">
<img :src="src" alt class="myImg" v-if="src">
</div>
<div class="btn" @click="btnClick">{{src?'重签':'签名'}}</div>
</div>
</template>
<script>
import { mobileURL } from '@/config/baseURL'
export default {
data() {
return {
src: ""
};
},
methods: {
btnClick() {
this.$router.push(`${mobileURL}/sign/mySign`);
this.src = "";
},
onClickLeft() {
// this.$router.go(-1)
}
},
created() {
// console.log(this.$route.query.img);
if (this.$route.query.img) {
this.src = this.$route.query.img;
}
}
};
</script>
<style lang="less">
.sign {
height: 100vh;
padding: 10px;
.img {
width: 100%;
height: 175px;
margin-top: 10px;
border: 1px solid #eee;
border-radius: 5px;
background: #fff;
.myImg {
width: 100%;
height: 100%;
}
}
.btn {
padding: 5px 10px;
width: 90%;
height: 30px;
line-height: 30px;
border: 2px solid #eee;
border-radius: 10px;
text-align: center;
margin: 20px auto;
cursor: pointer;
background: #1890ff;
color: #fff;
}
}
</style>
这个是签名页面,使用了canvas组件,同时做了横屏处理
签完名也可以下载到本地,按钮我注释了,js代码还在,可以自己选择,样式方面也可以根据自己要求调整。
备注:强制横屏那里,原本我的思路是选择整个html,但是旋转完canvas手指落点就完全不对了,调整起来比较麻烦,所以我就canvas依然是竖的,但是我把里面的其他所有元素放在一个div里面用js代码旋转了,这样看起来就是整个屏幕旋转,凑合这用吧