96SEO 2026-06-07 03:44 0
前言:别再为横屏签名抓狂了
说实话,移动端的 H5 签名功Neng本来就不容易。
geng别提还有横屏需求,真是让人头大。

哈哈,今天咱们就聊聊怎么把签名板搞成横着的,让用户在手机上写个字也Neng舒服。
咱就是说这篇文章会把关键点拆得稀巴烂,你随时Ke以 copy 粘贴到项目里。
一、需求先摆平:到底要干嘛先把需求写清楚。
1)用户打开页面后点个按钮弹出签名弹窗。
2)弹窗必须是横屏,全宽全高,占满视口。
3)用户手指在 canvas 上划动,实时绘制轨迹。
4)提供“清除”和“确认”两个操作。
5)确认后把图片返回给父组件,甚至Ke以直接保存到相册。
听起来不复杂,对吧?其实坑hen多,尤其是横屏适配和坐标修正这块儿。
二、技术选型:Canvas + 原生事件 vs 第三方库Ru果你想自己玩儿原始的 canvas,那得自己写笔迹平滑、压力感应之类的逻辑——代码量大,还容易出 bug。
不过好在现在有成熟的库,比如 signature_pad、jSignature、smooth-signature。
这些库Yi经封装好了绘制、清除、导出图片的功Neng,只剩下横屏这一步要自行处理。
我这里用的是Zui流行的 signature_pad,配合 Vue/uni‑app Neng快速搞定 UI 和交互。
三、横屏关键点:让画布转个身 1)使用 CSS transform 旋转容器
.sign-wrapper{
width:100vh; /* 宽度用视口高度 */
height:100vw; /* 高度用视口宽度 */
transform:rotate; /* 直接顺时针转 90° */
transform-origin:top left; /* 轴心放左上角,防止错位 */
overflow:hidden;
}
别忘了把内部的 button 也一起 rotate,不然文字倒着kan可不好使。
2)Viewport meta 必须配合
不加这个,有些 Android 浏览器会自动缩放,把画布拉伸成奇怪形状。害!
3)监听方向变化动态切换
window.addEventListener=>{
// 手动触发一次布局geng新
setTimeout=>{ adjustCanvasSize; },300);
});
function adjustCanvasSize{
const w = window.innerHeight;
const h = window.innerWidth;
const canvas = document.getElementById;
canvas.width = w;
canvas.height = h;
}
这样即使用户手动转了屏,也Neng保持横向布局。懂吧?你懂的~
四、实现步骤:从零到有签名弹窗 1)HTML 结构简洁明了
2)CSS 把弹窗撑满并旋转
.sign-modal{
position:fixed;
top:0;left:0;
width:100vw;height:100vh;
background:rgba;
display:flex;
align-items:center;
justify-content:center;
}
.btn-group{
position:absolute;
bottom:-40px; /* 因为容器被 rotate,往下调一点 */
}
.btn-group button{
margin:0 8px;
}
3)JS 初始化 SignaturePad 并处理横屏尺寸
import SignaturePad from 'signature_pad';
export default {
data{
return {
showSign:false,
imgUrl:'',
pad:null
}
},
watch:{
showSign{
if{
this.$nextTick;
}
}
},
methods:{
initPad{
const canvas=document.getElementById;
// 根据当前视口计算宽高
canvas.width=window.innerHeight;
canvas.height=window.innerWidth;
// Ru果Yi经有实例先销毁
if this.pad.off;
this.pad=new SignaturePad(canvas,{
backgroundColor:'rgba'
});
// 修正触摸坐标
const rect=canvas.getBoundingClientRect;
canvas.addEventListener('touchstart',e=>{
const touch=e.touches;
const x=touch.clientY-rect.top; // swap X/Y
const y=rect.right-touch.clientX; // invert X
this.pad._strokeBegin;
e.preventDefault;
},{passive:false});
// 同理处理 touchmove / touchend...
},
clear{
this.pad.clear;
},
cancel{
this.showSign=false;
},
confirm{
if){
alert;
return;
}
// 导出为 base64 PNG
const data=this.pad.toDataURL;
// Ru果需要横向保存,再Zuo一次 Canvas rotate
const img=new Image;
img.onload==>{
const off=document.createElement;
off.width=img.height;
off.height=img.width;
const ctx=off.getContext;
ctx.translate;
ctx.rotate;
ctx.drawImage;
this.imgUrl=off.toDataURL;
// 把结果抛给父组件
this.$emit;
this.showSign=false;
};
img.src=data;
}
}
}
4)父组件如何接收图片并展示
methods:{
receiveImg{
this.signaturePath=url;
},
clearSig{
this.signaturePath='';
}
}
五、常见坑 & 调试小技巧
- **坐标错位**:因为容器旋转后触摸坐标和 canvas 坐标不一致。Zui直接的办法是把 touch 的 clientX/Y 换位并取反,如上面的代码所示。别忘了加 `e.preventDefault` 防止页面滚动。
- **iOS Safari 的双指缩放**:即便加了 `user-scalable=no`,有时候还是会出现缩放手势。Ke以在 `touchmove` 时强制 `e.preventDefault` 来拦截。
- **高清渲染**:普通 canvas 在高 DPI 屏幕上会显得模糊。Ke以在初始化时乘以 `devicePixelRatio` 再Zuo等比缩放:
const ratio = window.devicePixelRatio || 1;
canvas.width = width * ratio;
canvas.height = height * ratio;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
const ctx = canvas.getContext;
ctx.scale;
- **内存泄漏**:每次打开弹窗dou重新实例化 SignaturePad,会导致旧实例残留。记得在 `beforeDestroy` 或者关闭弹窗时调用 `pad.off` 并置空变量。
六、性Neng & 兼容性小建议
#1: 尽量避免频繁创建 DOM 节点,尤其是 Canvas,每次打开弹窗只需要 resize,而不是重新创建元素。
#2: Android 系统碎片化严重,建议在真机上多测几款浏览器,尤其是触摸事件的 `changedTouches` 是否完整。
#3: Ru果业务要求必须保存到相册,请使用 uni‑app 提供的 `saveImageToPhotosAlbum` 接口;否则直接返回 base64 给后台即可,不必多此一举。
#4: 若项目对体积敏感,Ke以只引入 signature_pad 的核心文件,而不要整个 npm 包全部打进去,用 webpack 的 `externals` 或者手动挑文件压缩体积。
#5: 对于老旧 iOS 的 Safari,部分新版 API不支持,就只Neng退回 `toDataURL` 再转 Blob,这里就不展开啦,懂得dou懂~
七、收尾:轻松搞定移动端 H5 横屏签名 🎉🎉🎉AFAIK,这套方案Yi经帮我解决了所有项目中的横屏签名需求,你们以后再也不用去找网上那种“只Neng竖屏”的 demo 折腾啦。
Ru果还有其他细节想聊,比如怎么把水印文字跟随签名一起旋转,或者怎么把多页合同分段签署,douKe以随时找我砸锅卖铁,我这边还有不少踩坑经验Ke以分享哦!哈哈~祝大家 coding 愉快~ 🙌🙌🙌
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback