首页/新闻资讯/正文详情

不翻转屏幕的情况下,uniapp实现横屏签名(强制竖屏)

发布时间:2026/11/14 23:41:31 来源:云帆数科 栏目:资讯中心
不翻转屏幕的情况下,uniapp实现横屏签名(强制竖屏)
不翻转屏幕的情况下uniapp实现横屏签名签名页面需强制竖屏否则有些用户手机锁屏未开时会导致页面翻转。强制竖屏//单页面强制 { path: , style: { navigationBarTitleText: , pageOrientation: portrait // 强制竖屏 } }, //全页面强制 globalStyle: { pageOrientation: portrait // 强制竖屏 },封装签名组件cat-signature.vuetemplate view view v-ifvisibleSync classcat-signature :class{ visible: show } touchmove.stop.preventmoveHandle view classmask/view view classcontent view styleposition: relative; canvas classfirstCanvas :canvas-idcanvasId nameautograph touchmovemove touchstartstart($event) touchendend touchcancelcancel longtaptap disable-scrolltrue errorerror / !-- 用于旋转输出的隐藏 canvas给一个足够大的固定尺寸 避免动态尺寸在某些端上 canvasToTempFilePath 取不到内容 -- canvas classrotateCanvas :canvas-idcanvasId _rotate / view classtipsClas flexW v-if!hasDh text签/text text字/text text区/text /view /view /view view classbtnClas view classbtns view classbtn flexHA tapclose text classtopText取/text text classbottomText消/text /view view classbtn closeBtn flexHA tapclear text classtopText重/text text classbottomText签/text /view view classbtn _save flexHA tapsave text classtopText保/text text classbottomText存/text /view /view /view /view view classtipsClas tipsOutsideClas flexW v-iftipShow text请/textnbsp; text先/textnbsp; text签/textnbsp; text名/text /view /view /template script let content null; let touchs []; let canvasw 0; let canvash 0; // 笔迹边界用于导出时裁掉多余白边 let ink null; function resetInk() { ink { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity, has: false }; } resetInk(); //获取系统信息 uni.getSystemInfo({ success: function(res) { //重签清除画布的宽高 canvasw res.windowWidth*0.84; canvash res.windowHeight } }); export default { name: CatSignature, props: { visible: { type: Boolean, default: false }, canvasId: { type: String, default: firstCanvas } }, data() { return { show: false, visibleSync: false, signImage: , hasDh: false, tipShow:false, timer:null, countdown:2 }; }, watch: { visible(val) { this.visibleSync val; this.show val; // 打开时重置笔迹边界 if (val) resetInk(); this.getInfo(); } }, created(options) { this.visibleSync this.visible; this.getInfo(); setTimeout(() { this.show this.visible; }, 100); }, methods: { getInfo() { //获得Canvas的上下文 content uni.createCanvasContext(this.canvasId, this); //设置线的颜色 content.setStrokeStyle(#000); //设置线的宽度 content.setLineWidth(3); //设置线两端端点样式更加圆润 content.setLineCap(round); //设置两条线连接处更加圆润 content.setLineJoin(round); }, // close() { this.show false; this.hasDh false; this.$emit(close); }, moveHandle() {}, // 更新笔迹边界 updateInk(point) { if (!ink.has) { ink.minX ink.maxX point.x; ink.minY ink.maxY point.y; ink.has true; } else { if (point.x ink.minX) ink.minX point.x; if (point.x ink.maxX) ink.maxX point.x; if (point.y ink.minY) ink.minY point.y; if (point.y ink.maxY) ink.maxY point.y; } }, // 画布的触摸移动开始手势响应 start(e) { let point { x: e.touches[0].x, y: e.touches[0].y }; touchs.push(point); this.updateInk(point); this.hasDh true; }, // 画布的触摸移动手势响应 move: function(e) { let point { x: e.touches[0].x, y: e.touches[0].y }; touchs.push(point); this.updateInk(point); if (touchs.length 2) { this.draw(touchs); } }, // 画布的触摸移动结束手势响应 end: function(e) { //清空轨迹数组 for (let i 0; i touchs.length; i) { touchs.pop(); } }, // 画布的触摸取消响应 cancel: function(e) { // console.log(触摸取消 e) }, // 画布的长按手势响应 tap: function(e) { // console.log(长按手势 e) }, error: function(e) { // console.log(画布触摸错误 e) }, //绘制 draw: function(touchs) { let point1 touchs[0]; let point2 touchs[1]; content.moveTo(point1.x, point1.y); content.lineTo(point2.x, point2.y); content.stroke(); content.draw(true); touchs.shift(); }, //清除操作 clear: function() { //清除画布 content.clearRect(0, 0, canvasw, canvash); content.draw(true); resetInk(); this.hasDh false; this.$emit(clear); }, save() { let that this; if (!this.hasDh) { this.tipShowtrue; this.timersetInterval(() { if(this.countdown0) { this.countdown--; }else { clearInterval(this.timer); this.timernull; this.countdown2; this.tipShowfalse; } },1000) return; } uni.showLoading({ mask: true }); // 只导出笔迹所在区域避免整屏白边 const pad 16; // 四周留一点白边避免笔画贴边 let x 0, y 0, cw canvasw, ch canvash; if (ink ink.has) { x Math.max(0, ink.minX - pad); y Math.max(0, ink.minY - pad); cw Math.min(canvasw, ink.maxX pad) - x; ch Math.min(canvash, ink.maxY pad) - y; } if (cw 20) cw 20; if (ch 20) ch 20; const dpr uni.getSystemInfoSync().pixelRatio || 2; setTimeout(() { // 1. 裁出笔迹区域导出为临时图片 uni.canvasToTempFilePath({ canvasId: this.canvasId, x: x, y: y, width: cw, height: ch, destWidth: cw * dpr, destHeight: ch * dpr, success: function(res) { // 2. 把图片旋转 90° 画到隐藏 canvas输出横向图片 that.exportRotated(res.tempFilePath); }, fail: function(err) { console.log(err); uni.hideLoading(); } }, this ); }, 100); }, // 把裁剪后的签字图输出为横向图片竖着写的旋转 90°本来就横着的只裁白边 exportRotated(srcPath) { let that this; uni.getImageInfo({ src: srcPath, success(img) { const w img.width; const h img.height; // 隐藏 canvas 固定 800×800输出超限时等比缩小 const maxDim 780; const s Math.min(1, maxDim / Math.max(w, h)); const dw Math.round(w * s); const dh Math.round(h * s); // 笔迹明显高于宽说明用户是横握手机写的需要逆时针转 90° 变横向 // 否则本来就是横向笔迹保持原方向 const needRotate h w * 1.15; const outW needRotate ? dh : dw; const outH needRotate ? dw : dh; const rctx uni.createCanvasContext(that.canvasId _rotate, that); // 白底避免透明背景在部分场景变黑 rctx.setFillStyle(#ffffff); rctx.fillRect(0, 0, outW, outH); if (needRotate) { // 用户视角的上是屏幕的右屏幕右侧要变成图片顶部 rctx.translate(0, dw); rctx.rotate(-Math.PI / 2); } rctx.drawImage(srcPath, 0, 0, dw, dh); rctx.draw(false, () { setTimeout(() { uni.canvasToTempFilePath({ canvasId: that.canvasId _rotate, x: 0, y: 0, width: outW, height: outH, destWidth: outW, destHeight: outH, success(r2) { uni.hideLoading(); that.signImage r2.tempFilePath; that.$emit(save, r2.tempFilePath); that.hasDh false; that.show false; }, fail(err) { console.log(rotate export fail, err); uni.hideLoading(); // 旋转失败兜底用裁剪后的原图保证至少能上传 that.signImage srcPath; that.$emit(save, srcPath); that.hasDh false; that.show false; } }, that ); }, 150); }); }, fail(err) { console.log(getImageInfo fail, err); uni.hideLoading(); // 兜底旋转失败用裁剪后的原图 that.signImage srcPath; that.$emit(save, srcPath); that.hasDh false; that.show false; } }); } } }; /script style langscss .cat-signature.visible { visibility: visible; } .tipsClas { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) rotate(90deg); font-size: 100rpx; margin: auto; color: #888; z-index: 99; text { margin: 0 60rpx; } } .tipsOutsideClas { font-size: 30rpx; background: #333; color: #fff; padding:20rpx 30rpx; border-radius: 8rpx; transform: translate(-50%, -45%) rotate(90deg); text { margin: 0; } } .cat-signature { display: block; position: fixed; top: 0; left: 0; right: 0; bottom: 0; overflow: hidden; z-index: 11; height: 100vh; visibility: hidden; .mask { display: block; opacity: 0; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #fff; } .content { display: block; position: absolute; top:0; right: 0; width: 84%; z-index: 9; .firstCanvas { background-color: #fff; width: 100%; height: 100vh; } // 旋转输出的隐藏 canvas不能用 display:none否则 uni.canvasToTempFilePath 取不到内容。 // 固定 800×800导出时按实际需要的区域裁剪。 .rotateCanvas { position: absolute; left: -9999px; top: -9999px; width: 800px; height: 800px; background-color: #fff; } } } .btnClas { position: absolute; left: 0; top: 0; border-right:1rpx solid #eeeeee;; z-index: 9; .btns { background: #fff; border-radius:0 0 10rpx 10rpx; justify-content: space-around; padding:0 27rpx; position: relative; display: flex; height: 100vh; flex-direction: column; z-index: 99; .btn { width: 68rpx; text-align: center; font-size: 30rpx; height: 240rpx; line-height: 240rpx; background-color: #999; color: #fff; border-radius: 6rpx; position: relative; text { transform: rotate(90deg); position: absolute; } .topText { bottom: 30rpx; } .bottomText { top: 30rpx; } } .closeBtn { background-color: #f9ae3d; } ._save { background-color: rgb(67, 117, 255); } } } .visible .mask { display: block; opacity: 1; } /style页面使用调用catSignature canvasIdmycanvas closecloseSignature savesaveSignature :visiblesignatureShow / import catSignature from /pagesA/components/cat-signature.vue; components: { catSignature }, data() { return { signatureShow:false//签名弹窗 }; }, // 取消签名 closeSignature() { this.signatureShow false; }, // 确认签名 saveSignature(e) { this.signatureShow false; if(e) { uni.showLoading({ // title: 上传中, mask: true }); let that this; uni.uploadFile({ url: url,//上传接口 filePath: e, header: { Authorization: token }, name: file, fileType: image, success: (uploadFileRes) { let imgData JSON.parse(uploadFileRes.data);//后端返回的图片直接使用即可 } }); }else { this.$u.toast(签名失败) } },

相关推荐

macOS 窗口管理 Loop:三步装好,分屏技巧一次到位
macOS 窗口管理 Loop:三步装好,分屏技巧一次到位

macOS 窗口管理 Loop:三步装好,分屏技巧一次到位 【免费下载链接】Loop Window management made elegant. 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 终端比旁边的文档宽了那么一点点,拖了半天边框还是对不齐。窗口摆错… · 2026/11/15 20:25:57

Jasna 免费视频马赛克修复:1080p 整段 34 秒出片,GPU 全自动
Jasna 免费视频马赛克修复:1080p 整段 34 秒出片,GPU 全自动

Jasna 免费视频马赛克修复:1080p 整段 34 秒出片,GPU 全自动 【免费下载链接】jasna Video restoration tool 项目地址: https://gitcode.com/GitHub_Trending/ja/jasna 用 Jasna 做视频马赛克修复,丢进去一段带打码的 1080p 片子&… · 2026/11/15 20:25:56

Claude-Relay-Service 实战:构建企业级 AI 服务统一网关
Claude-Relay-Service 实战:构建企业级 AI 服务统一网关

Claude-Relay-Service 实战:构建企业级 AI 服务统一网关 当企业或开发团队需要在多个 AI 模型服务间灵活切换时,传统方案往往面临配置复杂、成本不可控、安全风险高等痛点。面对 Claude、OpenAI、Gemini、Droid 等多源异构的 AI API,如何构建… · 2026/11/15 12:52:51

低价电工证难不难考证 实操考试网上查询怎么查
低价电工证难不难考证 实操考试网上查询怎么查

低价电工证难不难考证 实操考试网上查询怎么查 实操考试心里没底怕挂科,这是很多准备考电工证的小伙伴最真实的状态。特别是选择低价电工证的你,可能担心培训质量、考试内容是否匹配,甚至不知道网上查询怎么查结果。今天就从南阳卧龙区一名在职建筑工人的… · 2026/11/15 20:25:39

漳平电工证怎么报内部消息曝光 工地太忙根本没时间复习考试
漳平电工证怎么报内部消息曝光 工地太忙根本没时间复习考试

漳平电工证怎么报内部消息曝光 工地太忙根本没时间复习考试 工地太忙根本没时间复习考试,你是不是也经常这样想?作为一线施工人员,谁不想早点拿到电工证,既能证明自己,又能多拿点工资?但报名流程复杂、考试内容多、复习时间紧张,这些都成了摆在眼前的… · 2026/11/15 20:25:39

电工证别人能注销吗全国通用吗
电工证别人能注销吗全国通用吗

电工证别人能注销吗全国通用吗 不知道去哪报名怕被中介坑?你不是一个人。在河南许昌,像张师傅这样的建筑工人,每天都在和特种作业证打交道。而最近他最担心的事情是: 电工证别人能注销吗… · 2026/11/15 20:25:39

丽水市哪里考电工证好良心建议:工地太忙根本没时间复习考试怎么办
丽水市哪里考电工证好良心建议:工地太忙根本没时间复习考试怎么办

丽水市哪里考电工证好良心建议:工地太忙根本没时间复习考试怎么办 工地太忙根本没时间复习考试,这句话说出了太多一线电工的真实写照。你是不是也经常因为项目赶工期,连抽空复习的时间都没有?其实,电工证考试不是靠天赋,而是靠方法。 良心建议… · 2026/11/15 20:25:39

贾汪区电工证报考地点在哪考?实操考试心里没底怕挂科
贾汪区电工证报考地点在哪考?实操考试心里没底怕挂科

贾汪区电工证报考地点在哪考?实操考试心里没底怕挂科 实操考试心里没底怕挂科,这是很多准备报考贾汪区电工证的学员最真实的感受。尤其是第一次参加这类考试的人,往往对流程、内容、甚至考场规则都不太清楚,心里没底是正常的,但关键是要掌握正确的方法和… · 2026/11/15 20:25:39

你学历不高也能报电工证?网上电工证报考入口和电子证书全攻略
你学历不高也能报电工证?网上电工证报考入口和电子证书全攻略

你学历不高也能报电工证?网上电工证报考入口和电子证书全攻略 你学历不高怕报不上名?别担心,现在网上电工证报考入口已经非常便捷,而且电子证书也越来越普及。只要符合基本条件,你照样可以拿到国家承认的电工证。下面我用漯河一位转岗从业者的经历,手把… · 2026/11/15 20:24:38

长春初级电工证怎么考?通过率揭秘全在这里
长春初级电工证怎么考?通过率揭秘全在这里

长春初级电工证怎么考?通过率揭秘全在这里 之前考的证在外省能不能转过来?这几乎是每个想从事电工工作的人都会问的问题。特别是那些在外地打拼多年、手里握着一张“外地电工证”的人,到了长春想继续干这一行,第一反应就是“我的证能用吗?”。今天我们就… · 2026/11/15 0:00:50

国内电工证报考条件与考试时间
国内电工证报考条件与考试时间

低压电工证怎么考?学历不高也能报名,官方报名入口全在这 你是不是经常听说“电工证是入行门槛”,但又担心自己学历不够、经验不足,根本报不了名?别急,今天就带你从零了解【国内电工证】的报考流程、考试内容,还有怎么在 官方报名入口… · 2026/11/15 0:00:50

电工作业时如何断电?电子证书到底能不能全国通用?
电工作业时如何断电?电子证书到底能不能全国通用?

电工作业时如何断电?电子证书到底能不能全国通用? 实操考试心里没底怕挂科,特别是电工作业时如何断电这一操作,不仅关系到你能不能拿到证书,更关系到以后能不能顺利上岗。很多人觉得这不过就是“断个电”,但其实这里面的门道可不少,稍有不慎就可能出错… · 2026/11/15 0:00:50

长春初级电工证怎么考?通过率揭秘全在这里
长春初级电工证怎么考?通过率揭秘全在这里

长春初级电工证怎么考?通过率揭秘全在这里 之前考的证在外省能不能转过来?这几乎是每个想从事电工工作的人都会问的问题。特别是那些在外地打拼多年、手里握着一张“外地电工证”的人,到了长春想继续干这一行,第一反应就是“我的证能用吗?”。今天我们就… · 2026/11/15 0:00:50

国内电工证报考条件与考试时间
国内电工证报考条件与考试时间

低压电工证怎么考?学历不高也能报名,官方报名入口全在这 你是不是经常听说“电工证是入行门槛”,但又担心自己学历不够、经验不足,根本报不了名?别急,今天就带你从零了解【国内电工证】的报考流程、考试内容,还有怎么在 官方报名入口… · 2026/11/15 0:00:50

电工作业时如何断电?电子证书到底能不能全国通用?
电工作业时如何断电?电子证书到底能不能全国通用?

电工作业时如何断电?电子证书到底能不能全国通用? 实操考试心里没底怕挂科,特别是电工作业时如何断电这一操作,不仅关系到你能不能拿到证书,更关系到以后能不能顺利上岗。很多人觉得这不过就是“断个电”,但其实这里面的门道可不少,稍有不慎就可能出错… · 2026/11/15 0:00:50

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 1:51:20

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 4:02:19

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/15 3:02:05

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码