兄弟们,一行代码都不需要敲,直接复制张贴,就能用

兄弟们,一行代码都不需要敲,直接复制张贴,就能用

  • 点击展示签名的组件 sign-canvas.vue 跳转到 配置了横屏属性的 写签名页 canvas-template.vue

  • 签好名后点击 确定, 触发上一页面的监听事件,处理返回签名对象包括 签名的本地图片url

  • 横屏签名

  1. 跳转到画布页面的,通过监听把数据传回上一个页面

先看看全部流程图


展示签名页: 对<sign-canvas>组件的使用

# 签名展示页面 代码
<template><u-form-item label-position="top" label="主/协人员(签名)"><view class="flex"><sign-canvas placeholder="主查签名" @createCanvas="createCanvas" :options="signList[1]"></sign-canvas><sign-canvas placeholder="协查签名" @createCanvas="createCanvas" :options="signList[2]"></sign-canvas></view></u-form-item>
</template><script>export default {data() {return {signList: {1: {id: null,img: null,index: 1},// 这儿的 id 是为了当修改表单时,通过判断 id 存在 来删除你重复签名的上一次图片的2: {id: null,img: null,index: 2},//img 就是签名好的图片地址;index 和 key值对应就行,看下面onShow代码中会解释},}},methods: {//点击跳转到画布页面 canvas-templatecreateCanvas(item) {let url = `/pages/canvas-template/canvas-template?img=${item.img}&index=${item.index}`;uni.navigateTo({url});},},//监听点击写画布的确定按钮 事件onShow() {uni.$on('updateData',(res) => {//res== {img: 画布转好图片的地址,index:定位的下标}this.signList[res.index].img = res.img//把图片回显到对应的位置 img1,这儿也体现了 index 的作用//可以在这儿调用上传图片接口 和 通过item.id 是否存在 删除原来上一张图片接口})},onUnload() {uni.$off('updateData')},}
</script>
<style scoped>.flex {display: flex;width: 100%;align-items: center;justify-content: space-between;padding-bottom: 20rpx;}
</style>

展示签名的组件<sign-canvas>----组件封装的位置 和在这个位置的好处


封装的展示组件sign-canvas放在 根目录中的 components/sign-canvas/sign-canvas.vue 中
注: 这样就不需要单独引入组件 和 注册组件 了
注: 如果位置没有这样放就需要自己单独引入 import 和 注册了

贴出 sign-canvas 完整代码

<template><view style="display: flex;"><view class="qm" @click="createCanvas(options)"><span v-if='!options.img'>{{placeholder}}</span><img v-else class='qmimg' :src="options.img" alt=""></view></view>
</template><script>export default {name:"sign-canvas",data() {return {};},props:{placeholder:{type: String,default:'个性签名'},options: {//options: {id: null,img:null,index: 2}type: Object,required:true}},methods: {createCanvas(options){this.$emit('createCanvas',options)}}}
</script><style scoped>.qm {width: 300rpx;height: 200rpx;background-color: rgb(245, 245, 245);display: flex;color: #169ef9;align-items: center;justify-content: center;font-weight: 600;margin-right: 30px;}.qmimg {width: 300rpx;height: 200rpx;}
</style>

canvas-template.vue 页面

  • 因为改页面是横屏签名 所有需要在 page.json 进行横屏 配置 贴出代码
# page.json
{"path" : "pages/canvas-template/canvas-template","style" : {"navigationBarTitleText": "个人签名","enablePullDownRefresh": false,"pageOrientation": "landscape"}
}

贴出 canvas-template.vue 页面代码

<template><view class="container"><!-- 背景模板 --><view class="bg_wrap"><img class="bg_model" v-if="options.SAVE_PATH" :src="options.SAVE_PATH" mode=""></img></view><!-- 画布 --><view class="canvas_wrap"><canvas class="mycanvas" canvas-id="simple_canvas" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas><!-- #ifdef APP-PLUS || H5 --><u-toast ref="uToast" :rotat="true"/><cover-view class="button-line"><cover-view class="button-style save-button btn" @tap="canvasToImg">保存</cover-view><cover-view class="button-style clear-button btn" @tap="clearCanvas">重新绘制</cover-view><cover-view class="button-style cancel-button btn" @tap="hide">关闭</cover-view></cover-view><!-- #endif --><!-- #ifdef MP-WEIXIN --><u-toast ref="uToast" /><cover-view class="btn btn-reset" @click="clearCanvas"> 重新绘制 </cover-view><cover-view class="btn btn-ok" @click="canvasToImg"> &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;确&nbsp;&nbsp;认&nbsp;&nbsp;&nbsp;&nbsp; </cover-view><!-- #endif --></view><!-- #ifndef MP-WEIXIN --><!-- 竖屏转横屏 --><canvas class="mycanvas" canvas-id="recoverCanvas" style="z-index: -1;"></canvas><!-- 横屏装竖屏 --><canvas class="mycanvas" :style="{ 'z-index': -1, width: `${windowWidth}px`, height: `${(windowWidth * windowWidth) / windowHeight}px` }" id="rotatCanvas" canvas-id="rotatCanvas"></canvas><!-- #endif --></view>
</template><script> export default {data() {return {options: {},windowWidth: null, //屏宽windowHeight: null, //屏高ctx: null, //画笔drawCount: 1, //第几次绘画img:''}},onUnload() {  uni.$off('updateData') },methods: {hide() {uni.navigateBack({ delta: 1 });},//触摸开始touchstart(e) {//第一次绘画,清除placeholderif (this.drawCount == 0) this.ctx.draw()this.initPen()this.drawCount++this.ctx.beginPath();this.ctx.moveTo(e.changedTouches[0].x, e.changedTouches[0].y)},//触摸移动touchmove(e) {// console.log(e.changedTouches[0])this.ctx.lineTo(e.changedTouches[0].x, e.changedTouches[0].y)this.ctx.stroke()this.ctx.draw(true)this.ctx.moveTo(e.changedTouches[0].x, e.changedTouches[0].y)},//触摸结束touchend() {},//清空画布clearCanvas() {// this.ctx.draw(false)this.initPlaceholder()},//确认画布canvasToImg() {if (this.drawCount == 0) {return this.$refs.uToast.show({ title: '签名不能为空!', type: 'warning' })}uni.canvasToTempFilePath({canvasId: 'simple_canvas',success: res => {// console.log(res)// this.img = res.tempFilePath// return falselet obj = {}// #ifdef APP-PLUSres.tempFilePath = plus.io.convertLocalFileSystemURL(res.tempFilePath);obj = { img: res.tempFilePath, index: this.options.index }uni.$emit('updateData', obj)uni.navigateBack({ delta: 1 });// #endif // #ifdef H5this.rotat(res.tempFilePath);// obj = { img: res.tempFilePath, index: this.options.index }// uni.$emit('updateData', obj)// uni.navigateBack({ delta: 1 });// #endif// #ifdef MP-WEIXINobj = { img: res.tempFilePath, index: this.options.index }uni.$emit('updateData', obj)uni.navigateBack({ delta: 1 });// #endif}})},// #ifdef H5// 将图片选装rotat(e) {let rotatCtx = uni.createCanvasContext('rotatCanvas', this); //创建绘图对象// 重新定位中心点console.log((this.windowWidth * this.windowWidth) / this.windowHeight,'111')rotatCtx.translate(0, (this.windowWidth * this.windowWidth) / this.windowHeight);// 将画布逆时针旋转90度rotatCtx.rotate((270 * Math.PI) / 180);// 将签字图片绘制进入CanvasrotatCtx.drawImage(e, 0, 0, (this.windowWidth * this.windowWidth) / this.windowHeight, this.windowWidth);// 保存后旋转后的结果rotatCtx.draw(true);setTimeout(() => {// 生成图片并回调uni.canvasToTempFilePath({canvasId: 'rotatCanvas',success: res => {console.log(window.URL.createObjectURL(new Blob([res.tempFilePath])),'window.URL.createObjectURL(new Blob([res.tempFilePath]))')const obj = { img: res.tempFilePath, index: this.options.index }uni.$emit('updateData', obj)uni.navigateBack({ delta: 1 });},complete: com => {console.log(com,'H5画布旋转');}},);}, 500);},async recoverRotate(img) {return new Promise((resove, reject) => {let rotatCtx = uni.createCanvasContext('recoverCanvas', this); //创建绘图对象uni.getImageInfo({src: img,// src:`https://tse1-mm.cn.bing.net/th/id/R-C.8c372fd892b3bd371eb3a1df8bd7fc88?rik=4KxekfOQD28FKA&riu=http%3a%2f%2fwww.desktx.com%2fd%2ffile%2fwallpaper%2fscenery%2f20170303%2fdfe53a7300794009a029131a062836d5.jpg&ehk=6ayU5y%2fwtGnzhu7g%2bJimm2REgEbHGczl9Mkbg3I1%2b5I%3d&risl=&pid=ImgRaw&r=0`,success: (res) => {console.log(res, 'res----initImg')// this.dddd = res.path// this.rotat(res.path, true);rotatCtx.translate(this.windowWidth, 0);// // 将画布sun时针旋转90度rotatCtx.rotate((90 * Math.PI) / 180);// // 将签字图片绘制进入Canvasconsole.log(this.windowHeight,this.windowWidth,'---')rotatCtx.drawImage(res.path, 0, 0, this.windowHeight, this.windowWidth);rotatCtx.draw(true)setTimeout(() => {uni.canvasToTempFilePath({canvasId: 'recoverCanvas',success: res => {resove(res.tempFilePath)},complete: com => {// console.log(com);}},);}, 500);}})})},// #endif//绘制图像到画布。async initImg() {console.log(this.options.img, 'initImg', decodeURIComponent(this.options.img))let img = decodeURIComponent(this.options.img)// #ifdef H5img = await this.recoverRotate(img)// #endifuni.getImageInfo({src: img,// src:`https://tse1-mm.cn.bing.net/th/id/R-C.8c372fd892b3bd371eb3a1df8bd7fc88?rik=4KxekfOQD28FKA&riu=http%3a%2f%2fwww.desktx.com%2fd%2ffile%2fwallpaper%2fscenery%2f20170303%2fdfe53a7300794009a029131a062836d5.jpg&ehk=6ayU5y%2fwtGnzhu7g%2bJimm2REgEbHGczl9Mkbg3I1%2b5I%3d&risl=&pid=ImgRaw&r=0`,success: (res) => {console.log(res, 'res----initImg')// #ifdef H5// this.dddd = res.path// this.rotat(res.path, true);// this.ctx.translate(this.windowWidth, 0);// // 将画布sun时针旋转90度// this.ctx.rotate((90 * Math.PI) / 180); // // 将签字图片绘制进入Canvasthis.ctx.drawImage(res.path, 0, 0, this.windowWidth, this.windowHeight);this.ctx.draw(true)// #endif// #ifndef H5console.log(this.windowWidth,this.windowHeight,'this.windowWidth,this.windowHeight')this.ctx.drawImage(res.path, 0, 0, this.windowWidth, this.windowHeight) // 设置图片坐标及大小,括号里面的分别是(图片路径,x坐标,y坐标,width,height)this.ctx.save(); //保存this.ctx.draw() //绘制// #endif},fail(err) {console.log(err, 'err-----initImg')}})},//初始化画布initCanvas(position) {console.log('创建画布')this.ctx = uni.createCanvasContext("simple_canvas", this); //创建画布this.initPen()//判断是否有地址if (!this.validatenull(this.options.img)) { //youconsole.log('绘制图像到画布')this.initImg()} else { //wuconsole.log('展示提示消息')this.initPlaceholder(); //提示消息}},//初始化画笔initPen() {this.ctx.lineWidth = 10; //画笔粗细this.ctx.lineCap = "round"; //画笔圆滑this.ctx.lineJoin = "round";this.ctx.setShadow(0, 0, 0.5, '#000000'); //设置阴影},//初始化 提示文字initPlaceholder() {this.drawCount = 0; //重置绘画次数this.ctx.setFontSize(20); //设置字体的字号this.ctx.setTextBaseline('top'); //提示文字的水平对齐this.ctx.setTextAlign('center'); //提示文字的对齐this.ctx.setFillStyle('#616165'); //设置填充色// #ifdef APP-PLUS || H5this.ctx.translate(this.windowWidth / 2, this.windowHeight / 2);this.ctx.rotate(2 * Math.PI / 4);this.ctx.fillText('请设置个性签名', 0, 0); //填充的文本// #endif// #ifdef MP-WEIXINthis.ctx.fillText('请设置个性签名', this.windowWidth / 2, this.windowHeight / 2); //填充的文本// #endifconsole.log(this.ctx, 'this.ctx')this.$nextTick(() => {this.ctx.draw()})// this.ctx.restore();this.initPen()// this.ctx.lineWidth = 10;//画笔粗细// this.ctx.lineCap = "round";//画笔圆滑// this.ctx.lineJoin = "round";},// 判断是否为空validatenull(val) {console.log(typeof val, val,'-----')if (typeof val == 'boolean') { return false; }if (typeof val == 'number') { return false; }if (val instanceof Array) {if (val.length == 0) return true;} else if (val instanceof Object) {if (JSON.stringify(val) === '{}') return true;} else {if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true;return false;}return false;},//初始化页面async initPage() {let windowConfig = uni.getSystemInfoSync();// #ifdef MP-WEIXINconsole.log(windowConfig,'windowConfig'); this.windowWidth = windowConfig.windowWidth; this.windowHeight = windowConfig.windowHeight;// #endif// #ifndef MP-WEIXINconsole.log(windowConfig,'windowConfig'); this.windowWidth = windowConfig.screenWidth; this.windowHeight = windowConfig.screenHeight;// #endif// console.log(uni.getSystemInfoSync(), 'uni.getSystemInfoSync()')// console.log(this.windowWidth, this.windowHeight, '屏宽高')},},async onLoad(options) {//#ifdef APP-PLUS// plus.screen.lockOrientation('landscape-primary'); //锁定横屏// plus.navigator.setFullscreen(true); //隐藏状态栏(应用全屏:只能隐藏状态栏,标题栏和虚拟返回键都还可以显示)// plus.screen.lockOrientation('default'); //#endif// #ifndef MP-WEIXIN// #endifconsole.log('onLoad', options)options.SAVE_PATH = (options.SAVE_PATH&&decodeURIComponent(options.SAVE_PATH)) || ''/**options* img: 是否有图片*/this.options = optionsconsole.log(this.options,'this.options')this.options.index = options.index || 1this.initPage()//获取 屏宽、高this.initCanvas()//初始化画布},onReady() {// #ifdef H5//禁用移动端手机下拉 问题document.body.addEventListener('touchmove',function(evt) {if (!evt._isScroller) {evt.preventDefault()}},{ passive: false })// #endif}}
</script><style lang="scss" scoped>.container {background-color: white;width: 100%;height: 100%;width: 100vw;height: 100vh;position: fixed;top: 0rpx;left: 0rpx;z-index: 9999;.bg_model,.canvas_wrap{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; z-index: 9; }.canvas_wrap{ z-index: 99}}.mycanvas {width: 100vw;height: 100vh;// background-color: #FFFFFF;position: fixed;left: 0rpx;top: 0rpx;z-index: 2;}/* #ifdef APP-PLUS || MP-WEIXIN */.btn {min-width: 180rpx;position: absolute;bottom: 10rpx;padding: 8rpx;text-align: center;border: 1rpx solid #4965B3;// font-size: $fontsize;border-radius: 8rpx;box-sizing: border-box;z-index: 999;}/* #endif */.btn-reset {background-color: #FFFFFF;right: 230rpx;color: #4965B3;}.btn-ok {right: 30rpx;background-color: #4965B3;color: #fff;}/* #ifdef H5 */.button-line {position: fixed;transform: rotate(90deg);bottom: 340rpx;left: -288rpx;width: 100%;display: flex;align-items: center;justify-content: space-around;z-index: 999;.button-style {color: #ffffff;width: 240rpx;text-align: center;line-height: 80rpx;border-radius: 10rpx;}.save-button {background-color: #02b340;}.clear-button {background-color: #ffa500;}.cancel-button {background-color: #e10b2b;}}/deep/.uni-page-head { display: none !important;z-index: -1 !important; } /* #endif */
</style>

完事了,同志们 卡卡的就ok了

小程序 个性签名,uni app 开发 横屏相关推荐

  1. java计算机毕业设计基于安卓Android/微信小程序的游泳馆管理系统APP

    项目介绍 游泳馆管理系统小程序,主要对首页.个人中心.会员管理.场馆类型管理.泳池类型管理.饮食类型管理.场馆信息管理.泳池信息管理.饮食信息管理.泳池预订管理.购买信息管理.会员等级管理.会员充值管 ...

  2. java计算机毕业设计基于安卓Android/微信小程序的自来水收费系统APP

    项目介绍 网络的广泛应用给生活带来了十分的便利.所以把自来水收费管理与现在网络相结合,利用java技术建设自来水收费系统app,实现自来水收费的信息化.则对于进一步提高自来水收费管理发展,丰富自来水收 ...

  3. uni app 开发微信小程序及上线体验

    uni app 开发微信小程序及上线体验 项目创建及微信小程序AppId的申请 本次开发的是电商类的微信小程序,这里用到的是HBuilderX这个编辑器.之前用的Visual Studio Code ...

  4. PHP开发B2C商城 微信小程序商城系统源码+数据库,轻量级前后端分离的电商系统,支持微信小程序 + H5+ 公众号 + APP

    项目介绍 一款轻量级.高性能.前后端分离的电商系统,支持微信小程序 + H5+ 公众号 + APP,前后端源码完全开源,看见及所得,完美支持二次开发,可学习可商用,让您快速搭建个性化独立商城. 完整代 ...

  5. 毕业季基于spring的基于安卓APP的基于ssm框架的基于微信小程序的管理系统设计与开发(开题+源码+讲解+论文)

    毕业设计考察的是同学的专业知识的运用能力,除了对技能的考核,还看重你的创新思维,这里面设计到内容繁琐复杂. 对于还未毕业没有过项目开发经验的同学是有些难度的,一个程序的开发小到1两个月,大至几个月甚至 ...

  6. hbuilderx 小程序分包_很酷的HBuilderX和uni-app,开发一次既能生成小程序又能生成App...

    很酷的HBuilderX和uni-app,开发一次既能生成小程序又能生成App 创业者福利,做一次小程序和APP都有了 更流畅 由于基于C++架构而非eclipse或webkit架构,HX在启动速度. ...

  7. uniapp开发:瀑布流 灵活配置 简单易用 兼容vue2vue3小程序、H5、app等多端

    概要 支持的平台 使用方式 属性说明 事件说明 组件方法 refresh的使用示例 隐藏单项图片示例 完整示例 温馨提示 关注我,不迷路 概要 custom-waterfalls-flow是一个瀑布流 ...

  8. 提高微信小程序的应用速度的常见方式有哪些? 小程序怎么实现下拉刷新? 简述微信小程序原理? 小程序的发布流程(开发流程)分析下微信小程序的优劣势?小程序授权登录流程? 小程序支付如何实现

    小程序部分常见面试题 提高微信小程序的应用速度的常见方式有哪些? 提高页面加载速度 用户行为预测 减少默认data的大小 组件化方案 分包预下载 小程序与原生App相比优缺点? 优点: 基于微信平台开 ...

  9. web前端学习(三):微信小程序基于H5规范,开发Android应用程序

    前言: 微信小程序开发框架的目标是通过尽可能简单,高效的方式让开发者可以在微信中开发具有原生APP体验的服务. 整个小程序框架系统分为两部分,逻辑层,视图层,小程序提供了自己的视图层描述语言, WXM ...

最新文章

  1. 谷歌迂回入华:Waymo无人车抢先进驻上海!
  2. python怎么读取txt文件第二行-Python:如何选择文本文件的第一行,以及第二行……?...
  3. [转]清除mysql表中数据
  4. tomcat加白名单_超详细的tomcat管理页面各类型配置总结
  5. linux 间隔定时器,Linux间隔定时器的使用 探索一
  6. 程序员,35岁就可能被替换的职业,遇到好的领导多么重要
  7. 云小课 | 区块链关键技术之一:共识算法
  8. 观察者模式(发布--订阅模式)
  9. 派生类从基类继承的过程
  10. 为了让你的网页能在更多的服务器上正常地显示,还是加上“SET NAMES UTF8”吧...
  11. ORACLE11G常用函数
  12. python各种库下载地址:
  13. UEditor(四)——表情包
  14. 5个AIDA64激活密钥
  15. 安卓手机的APP图标尺寸规范和图标命名规范
  16. 无限级分销管理系统的设计与实现
  17. 设置时区serverTimezone
  18. 林光常颠覆传统的养生观 ,养生必读
  19. 高德地图实现昼夜、卫星图切换
  20. Shop项目后台--4.所有订单的订单详情/admin/order/list.jsp

热门文章

  1. Python小括号、中括号、大括号和尖括号的含义
  2. 关于Python函数的双括号()()
  3. 实训作业2-光敏电阻,人体感应灯
  4. java限制只能修改一次订单_面试官再问你怎么修改订单,就把这篇甩给他
  5. 老鸟手把手教你利用linux技能追求女孩子
  6. 中国独立游戏界的 “骑士” 开启大航海时代 | Google Play 开发者故事
  7. PS图层混合算法之一(不透明度,正片叠底,颜色加深,颜色减淡)
  8. 互联网+教育创业之家教平台分析
  9. AD PCB实用常用快捷键总结
  10. 未来最赚钱的17大行业:云计算居首