小程序中使用CANVAS实现手写签名并写入模板图片中

2023-11-01

实测,开发者工具中滚动条位置会影响书写,显示会有些问题,并且会卡顿,安卓、苹果手机上测试正常

  index.js

const App = getApp();
 
Page({
 
    /**
     * 页面的初始数据
     */
    data: {
      curScrollTop : 0
    },
 
    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(options) {
 
    },
 
    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    onReady() {
 
    },
 
    /**
     * 生命周期函数--监听页面显示
     */
    onShow() {
      if(this.data.showBigResImgPop){
        this.setData({
          showBigResImgPop : false
        })
      }else{
        // this.init();
      }
    },
    
    
    
    /**
     * 写入签名生成图片
     */
    onPageScroll:function(e){ // 获取滚动条当前位置
      this.setData({
        curScrollTop : e.scrollTop
      })
      // console.log(this.data.curScrollTop)
    },
    writeSignatureDo(){
      this.setData({
        showWriteSignature : true,
      })
      // 写入签名生成图片
      this.writeSignature();
    },
    writeSignature(){
      if(!this.data._left && !this.data._top){
        console.log(1111)
        const query1 = wx.createSelectorQuery();
        query1.select('#writeSignatureCanvasBox').boundingClientRect((res)=>{
          // console.log(res)
          this.setData({
            _left : res.left,
            _top : res.top,
          })
        }).exec()
        
        const query = wx.createSelectorQuery();
        query.select('#writeSignatureCanvas')
        .fields({
          node: true,
          size: true
        })
        .exec((res) => {
          // console.log(res);
          // const canvas = res[0].node;
          // console.log('canvas初始宽高', canvas.width, canvas.height);
          this.setData({
            canvas : res[0].node,
            screenWidth : wx.getSystemInfoSync().screenWidth,
            screenWidthHalf : wx.getSystemInfoSync().screenWidth / 2,
          })
          // console.log('canvas初始宽高', this.data.canvas.width, this.data.canvas.height);
          
          // /* START 不设置 CANVAS宽高时,canvas.width=300,canvas.height=150,ctx.lineWidth可以对应设置 细 一些 */
          // // setNameMouseX : (e.touches[0].pageX - this.data._left + ((this.data.screenWidth - this.data.canvas.width) / 2)) * (this.data.canvas.width / this.data.screenWidth),
          // // setNameMouseY : (e.touches[0].pageY - this.data._top + ((this.data.screenWidthHalf - this.data.canvas.height) / 2)) * (this.data.canvas.height / this.data.screenWidthHalf),
          // /* END */
          
          // /* START 设置 CANVAS宽高时,触摸画线根据CANVAS宽高计算标准必须是 300 | 150,ctx.lineWidth可以对应设置 稍粗 一些 */
          // this.data.canvas.width = this.data.screenWidth;
          // this.data.canvas.height = this.data.screenWidthHalf;
          // // setNameMouseX : e.touches[0].pageX - this.data._left + ((this.data.screenWidth - 300) / 2),
          // // setNameMouseY : e.touches[0].pageY - this.data._top + ((this.data.screenWidthHalf - 150) / 2),
          // /* END */
          
          /* START 设置 CANVAS宽高 * dpr 时,触摸画线根据CANVAS宽高计算标准必须是 300 * dpr | 150 * dpr,ctx.lineWidth可以对应设置 粗 一些 */
          this.setData({
            dpr : wx.getSystemInfoSync().pixelRatio
          })
          this.data.canvas.width = this.data.screenWidth * this.data.dpr;
          this.data.canvas.height = this.data.screenWidthHalf * this.data.dpr;
          // setNameMouseX : e.touches[0].pageX * this.data.dpr - this.data._left * this.data.dpr + ((this.data.screenWidth * this.data.dpr - 300 * this.data.dpr) / 2),
          // setNameMouseY : e.touches[0].pageY * this.data.dpr - this.data._top * this.data.dpr + ((this.data.screenWidthHalf * this.data.dpr - 150 * this.data.dpr) / 2),
          // y轴滚动条影响手写内容处理
          //  - this.data.curScrollTop * this.data.dpr
          /* END */
          
          this.setData({
            writeSignatureCanvasW : this.data.screenWidth,
            writeSignatureCanvasH : this.data.screenWidthHalf,
          })
          
          // const ctx = canvas.getContext('2d');
          this.setData({
            ctx : this.data.canvas.getContext('2d')
          })
          
          this.data.ctx.strokeStyle = "#4FADF8";
          this.data.ctx.lineWidth = 14;
          this.data.ctx.clearRect(0, 0, this.data.canvas.width, this.data.canvas.height);
        })
      }else{
        console.log(2222)
        this.data.ctx.clearRect(0, 0, this.data.canvas.width, this.data.canvas.height);
      }
    },
    writeSignatureCanvasTouchStartEvent(e){
      // console.log(e)
      this.setData({
        // setNameMouseX : (e.touches[0].pageX - this.data._left + ((this.data.screenWidth - this.data.canvas.width) / 2)) * (this.data.canvas.width / this.data.screenWidth),
        // setNameMouseY : (e.touches[0].pageY - this.data._top + ((this.data.screenWidthHalf - this.data.canvas.height) / 2)) * (this.data.canvas.height / this.data.screenWidthHalf),
        
        // setNameMouseX : e.touches[0].pageX - this.data._left + ((this.data.screenWidth - 300) / 2),
        // setNameMouseY : e.touches[0].pageY - this.data._top + ((this.data.screenWidthHalf - 150) / 2),
        
        setNameMouseX : e.touches[0].pageX * this.data.dpr - this.data._left * this.data.dpr + ((this.data.screenWidth * this.data.dpr - 300 * this.data.dpr) / 2),
        setNameMouseY : e.touches[0].pageY * this.data.dpr - this.data._top * this.data.dpr + ((this.data.screenWidthHalf * this.data.dpr - 150 * this.data.dpr) / 2) - this.data.curScrollTop * this.data.dpr,
      })
      
    	this.data.ctx.beginPath();
    	this.data.ctx.moveTo(this.data.setNameMouseX,this.data.setNameMouseY);
    },
    writeSignatureCanvasTouchEndEvent(e){
      // console.log(e)
      this.setData({
        setNameMouseX : null,
        setNameMouseY : null,
      })
      this.setData({
        showResButton : true
      })
    },
    writeSignatureCanvasTouchMoveEvent(e){
      this.setData({
        // setNameMouseX : (e.touches[0].pageX - this.data._left + ((this.data.screenWidth - this.data.canvas.width) / 2)) * (this.data.canvas.width / this.data.screenWidth),
        // setNameMouseY : (e.touches[0].pageY - this.data._top + ((this.data.screenWidthHalf - this.data.canvas.height) / 2)) * (this.data.canvas.height / this.data.screenWidthHalf),
        
        // setNameMouseX : e.touches[0].pageX - this.data._left + ((this.data.screenWidth - 300) / 2),
        // setNameMouseY : e.touches[0].pageY - this.data._top + ((this.data.screenWidthHalf - 150) / 2),
        
        setNameMouseX : e.touches[0].pageX * this.data.dpr - this.data._left * this.data.dpr + ((this.data.screenWidth * this.data.dpr - 300 * this.data.dpr) / 2),
        setNameMouseY : e.touches[0].pageY * this.data.dpr - this.data._top * this.data.dpr + ((this.data.screenWidthHalf * this.data.dpr - 150 * this.data.dpr) / 2) - this.data.curScrollTop * this.data.dpr,
      })
      
    	this.data.ctx.lineTo(this.data.setNameMouseX,this.data.setNameMouseY);
    	this.data.ctx.stroke();
    },
    // 重写
    reSetWriteSignatureCanvas(){
      this.setData({
        showResButton : false
      })
      this.data.ctx.clearRect(0, 0, this.data.canvas.width, this.data.canvas.height);
    },
    // 确定
    setWriteSignatureCanvas(){
      this.setData({
        showWriteSignature : false,
        writeSignatureImg : this.data.canvas.toDataURL('image/png'),
      })
      this.reSetWriteSignatureCanvas();
      // 写入海报,生成最终图片
      this.makeResImg();
    },
    
    
    
    /**
     * 写入海报,生成最终图片
     */
    makeResImg() {
      if(this.data.posterCanvas){
        console.log(4444)
        this.makeResImgAfter();
      }else{
        console.log(3333)
        const query = wx.createSelectorQuery();
        query.select('#makeResCanvas')
        .fields({
          node: true,
          size: true
        })
        .exec((res) => {
          // // console.log(res);
          // const canvas = res[0].node;
          // // console.log('canvas初始宽高', canvas.width, canvas.height);
          // const ctx = canvas.getContext('2d');
          
          this.setData({
            posterCanvas : res[0].node,
          })
          
          this.setData({
            posterCtx : this.data.posterCanvas.getContext('2d'),
          })
          
          // const dpr = wx.getSystemInfoSync().pixelRatio;
          // console.log(dpr);
          // canvas.width = res[0].width * dpr;
          // canvas.height = res[0].height * dpr;
          // console.log(canvas.width , canvas.height)
          // ctx.scale(dpr, dpr);
          
          this.makeResImgAfter();
        })
      }
    },
    makeResImgAfter(){
      this.data.posterCtx.clearRect(0, 0, this.data.posterCanvas.width, this.data.posterCanvas.height);
      // 写入 生成图片 背景图片
      const posterBgImg = this.data.posterCanvas.createImage();
      posterBgImg.src = '../../images/form-img.png';
      posterBgImg.onload = () => {
        // console.log('背景图实际宽高', posterBgImg.width, posterBgImg.height);
        this.data.posterCanvas.width = posterBgImg.width;
        this.data.posterCanvas.height = posterBgImg.height;
        this.setData({
          // makeResCanvasW: posterBgImg.width,
          // makeResCanvasH: posterBgImg.height,
          // makeResCanvasW:750,
          // makeResCanvasH:750 / posterBgImg.width * posterBgImg.height,
          makeResCanvasW:0,
          makeResCanvasH:0,
        })
        // console.log('this.data.posterCanvas宽高设置与背景图一致', this.data.posterCanvas.width, this.data.posterCanvas.height);
        this.data.posterCtx.drawImage(posterBgImg, 0, 0, posterBgImg.width, posterBgImg.height);
        // 写入勾选项图片
        const checkImg = this.data.posterCanvas.createImage();
        checkImg.src = '../../images/check.png';
        checkImg.onload = () => {
          // 画入签名图片
          const reSetWriteSignatureImg = this.data.posterCanvas.createImage();
          reSetWriteSignatureImg.src = this.data.writeSignatureImg;
          reSetWriteSignatureImg.onload = () => {
            this.data.posterCtx.drawImage(reSetWriteSignatureImg, 1892, 2848, 350, 175);
            // 设置勾选项
            this.data.posterCtx.drawImage(checkImg, 558, 1895, 32, 24);
            this.data.posterCtx.drawImage(checkImg, 1443, 1895, 32, 24);
            this.data.posterCtx.drawImage(checkImg, 1443, 2047, 32, 24);
            // 写入文本
            this.data.posterCtx.fillStyle = '#4FADF8';
            this.data.posterCtx.textAlign = 'left';
            this.data.posterCtx.textBaseline = 'top';
            this.data.posterCtx.font = '46px "PingFangSC-Regular","STHeitiSC-Light","微软雅黑","Microsoft YaHei","sans-serif"';
            this.data.posterCtx.fillText('客户姓名',545,384);
            // 写入多行文本
            // this.writeTextOnCanvas(this.data.posterCtx, 42, 40, '写入多行文本写入多行文本写入多行文本写入多行文本写入多行文本写入多行文本' ,562, 1350);
            let add = '北京市北京市东城区东华门街道';
            add = '北京市北京市东城区东华门街道多四个字';
            if(add.length > 14){
              this.writeTextOnCanvas(this.data.posterCtx, 52, 30, add ,1716, 869);
            }else{
              this.data.posterCtx.fillText(add,1716,895);
            }
            this.data.posterCtx.fillText('企业详细地址',545,1064);
            let date = new Date()
            this.data.posterCtx.fillText(date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate(),1892,3035);
            
            // 生成最终图片
            this.setData({
              posterUrl: this.data.posterCanvas.toDataURL('image/png'),
            })
          }
        }
      }
    },
    // 查看大图
    showBigResImg(){
      this.setData({
        showBigResImgPop : true
      })
      wx.previewImage({
        current: this.data.posterUrl,
        urls: [this.data.posterUrl]
      });
    },
    // 写入多行文本
    //ctx_2d		getContext("2d") 对象
    //lineheight	段落文本行高
    //bytelength	设置单字节文字一行内的数量
    //text			写入画面的段落文本
    //startleft		开始绘制文本的 x 坐标位置(相对于画布)
    //starttop		开始绘制文本的 y 坐标位置(相对于画布)
    writeTextOnCanvas(ctx_2d, lineheight, bytelength, text ,startleft, starttop){
    	function getTrueLength(str){//获取字符串的真实长度(字节长度)
    		var len = str.length, truelen = 0;
    		for(var x = 0; x < len; x++){
    			if(str.charCodeAt(x) > 128){
    				truelen += 2;
    			}else{
    				truelen += 1;
    			}
    		}
    		return truelen;
    	}
    	function cutString(str, leng){//按字节长度截取字符串,返回substr截取位置
    		var len = str.length, tlen = len, nlen = 0;
    		for(var x = 0; x < len; x++){
    			if(str.charCodeAt(x) > 128){
    				if(nlen + 2 < leng){
    					nlen += 2;
    				}else{
    					tlen = x;
    					break;
    				}
    			}else{
    				if(nlen + 1 < leng){
    					nlen += 1;
    				}else{
    					tlen = x;
    					break;
    				}
    			}
    		}
    		return tlen;
    	}
    	for(var i = 1; getTrueLength(text) > 0; i++){
    		var tl = cutString(text, bytelength);
    		ctx_2d.fillText(text.substr(0, tl).replace(/^\s+|\s+$/, ""), startleft, (i-1) * lineheight + starttop);
    		text = text.substr(tl);
    	}
    },
    
    
 
    /**
     * 生命周期函数--监听页面隐藏
     */
    onHide() {
 
    },
 
    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload() {
 
    },
 
    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh() {
 
    },
 
    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom() {
 
    },
 
    /**
     * 用户点击右上角分享
     */
    onShareAppMessage() {
 
    }
})

 index.wxml

<button bindtap="writeSignatureDo" style="background-color: #0FC393;">我要签名</button>
<view wx:for="{{5}}">
  <view>1111</view>
  <view>2222</view>
  <view>3333</view>
  <view>5555</view>
  <view>6666</view>
  <view>7777</view>
  <view>8888</view>
  <view>9999</view>
</view>
<button bindtap="writeSignatureDo" style="background-color: #0FC393;">我要签名</button>
<image wx:if="{{writeSignatureImg}}" src="{{writeSignatureImg}}" mode="widthFix"></image>
 
<!--  -->
 
<view>
 <canvas type="2d" id="makeResCanvas"  style="width: {{makeResCanvasW}}rpx;height: {{makeResCanvasH}}rpx;"></canvas>
 <image bindtap="showBigResImg" wx:if="{{posterUrl}}" src="{{posterUrl}}" mode="widthFix" style="width: 100%;"></image>
</view>
 
<view class="flex-dir-column flex-x-center flex-y-center" style="width: 100%; height: 100%; background-color: rgba(0,0,0,.5); position: fixed; left: 0; top: 0; {{showWriteSignature ? 'display: flex !important;' : 'display: none !important;'}}">
  <view style="text-align: center; color: #fff; margin-bottom: 30rpx;">请写入签名</view>
  <view id="writeSignatureCanvasBox">
    <canvas type="2d" id="writeSignatureCanvas" catch:touchstart="writeSignatureCanvasTouchStartEvent" catch:touchend="writeSignatureCanvasTouchEndEvent" catch:touchmove="writeSignatureCanvasTouchMoveEvent" style="width: {{writeSignatureCanvasW}}px;height: {{writeSignatureCanvasH}}px; background-color: #fff;"></canvas>
  </view>
  <view class="dis-flex flex-x-center flex-y-center" style="width: 50%; height: 80rpx; margin-top: 30rpx;">
    <button catchtap="reSetWriteSignatureCanvas" wx:if="{{showResButton}}" type="default" style="height: 80rpx;line-height: 80rpx;">重写</button>
    <button catchtap="setWriteSignatureCanvas" wx:if="{{showResButton}}" type="default" style="height: 80rpx;line-height: 80rpx;">确定</button>
  </view>
</view>

素材图片:

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小程序中使用CANVAS实现手写签名并写入模板图片中 的相关文章

  • AJAX 安全问题

    我希望能够解决一些关于 AJAX 安全性的问题 这是我试图理解的一个场景 假设我正在使用 AJAX 向页面请求一些半敏感材料 例如 我将把用户的 ID 传递给一个 php 文件 并返回一些关于他们自己的信息 现在 是什么阻止人们模拟此 Ja
  • 当内部元素滚动位置到达顶部/底部时防止父元素滚动?

    我有一个小 浮动工具箱 一个带有position fixed overflow auto 效果很好 但是 当在该框内滚动 使用鼠标滚轮 并到达底部或顶部时 父元素 接管 滚动请求 工具框后面的文档滚动 这很烦人 而不是用户 要求的 我正在使
  • 在 Node.js 中生成带条形码的 pdf

    我在用https github com devongovett pdfkit https github com devongovett pdfkit生成 PDF 文件 我可以简单地使用类似的方法 app get get pdf req re
  • 为什么省略分号会破坏这段代码?

    或者换句话说 为什么分号插入失败 导致下面的代码被破坏 function Foo Foo prototype bar function console log bar lt missing semicolon function Foo pr
  • 如何将值发布到输入框中?

    Intro I would like to get the current time after clicking at click and POST the value into input text box Note 假设包含引导样式表
  • jQuery:查找具有特定自定义属性的元素

    我只想找到具有特定自定义属性值的元素 例如 我想找一个div其具有属性data divNumber 6 var number 6 var myDiv data divNumber number 我尝试使用http api jquery co
  • 如何在React Native的MapView中设置标记

    我想在React Native中的MapView上设置一个标记 但是通过官方文档找不到任何信息MapView https facebook github io react native docs mapview html content 如
  • 我可以在 GWT 中使用第三方 Javascript 库吗

    例如穆工具 用 js 编码对我来说很舒服 但显然不适合所有人 你当然可以 最好的事情就是给自己写一些好看的JavaScript 覆盖类型 http code google com webtoolkit doc latest DevGuide
  • EmberJS:对象作为查询参数来刷新模型

    我遵循了查询参数指南 http guides emberjs com v1 11 0 routing query params http guides emberjs com v1 11 0 routing query params 而且效
  • 正则表达式中连字符的这种用法有效吗?

    NB I only想知道它是否是正则表达式定义中未转义连字符的有效应用 它是not关于匹配电子邮件 连字符或反斜杠的含义 量词或其他任何内容的问题 另外 请注意 链接的答案并没有真正讨论转义 未转义连字符之间的有效性问题 通常我会像这样声明
  • jquery 中的函数返回未定义[重复]

    这个问题在这里已经有答案了 我在 jquery 中调用的函数返回未定义 我检查了该函数 当我对其进行调试时 它返回正确的数据 function addToPlaylist component type add to pl value pl
  • Firefox Addon 中的 JQuery 导致多个警告

    我在 Firefox 插件中使用 jquery 但我不断收到大量警告消息 如下所示 anonymous function does not always return a value System JS WARNING resource g
  • ES6 模块范围

    我有代码 lib js var a a export var b b main js console log a a variable is not available in a global scope import b from lib
  • Firebase + Node.js:错误:找不到 XMLHttpRequest 兼容性库

    Firebase Node js On iOS 安装的 Node js npm 安装 firebase save 节点测试 js 其中 test js 是一个非常简单的连接到 Firebase 的脚本 var firebase requir
  • Google 地图 API - 地图未显示 - 没有错误

    我正在尝试将地图从 Google API 加载到 div 中 但是 地图未加载 并且没有输出任何错误 这是代码 google maps var geocoder map function codeAddress address geocod
  • 当php脚本通过ajax运行时显示进度条

    我有一个通过 ajax 向服务器提交值的表单
  • onPress 方法中箭头函数与普通函数的行为

    正在学习 Native React 并学习更多关于 javascript 的知识 所以我仍然不明白它的行为的很多事情 我使用 TouchableOpacity 及其 onPress 属性创建了一个按钮组件 为了让它工作 我必须发送我想要执行
  • 如何在 TypeScript 中使用 navigation.replace ?

    我试图在我的代码中使用它 const navigation useNavigation navigation replace AllFriends 但我不断收到错误消息 Property replace does not exist on
  • 将引导程序弹出框保留在视口内

    我正在尝试使用带有按钮的侧边栏创建一个菜单 每个按钮都有一个指定的包含相关数据的弹出窗口 不幸的是 其中一个弹出窗口可能包含任意数量的行 并且在某些情况下它可能部分位于视口之外 See http jsfiddle net bfd9f 1 h
  • JavaScript 阶乘防止无穷大

    我一直在 JavaScript 中使用这个函数来计算阶乘数 var f function factorial n if n 0 n 1 return 1 if f n gt 0 return f n return f n factorial

随机推荐

  • 简述前端MVVM框架

    一张图说明 1 一句话总结 vm层 视图模型层 通过接口从后台m层 model层 请求数据 vm层继而和v view层 实现数据的双向绑定 2 mvc和mvvm的关系 c 控制层 被换成了vm viewmodel 层 MVVM是Model
  • TypeScript 总结

    文章目录 TypeScript 总结 概述 运行ts文件 方式一 方式二 基础 声明变量 类型 数组 元组 联合类型 取值限制 枚举类型 any unknown void undefined 类型适配 面向对象 函数 普通函数 箭头函数 可
  • 2.2-base-num-str

    for i in range 9 0 1 for j in range 1 i 1 print f j i str i j ljust 2 end print 1 9 9 2 9 18 3 9 27 4 9 36 5 9 45 6 9 54
  • 网络设备自动化运维工具——ansible入门笔记

    Ansible概述 Ansible是一款自动化运维工具 基于Python开发 集合了众多运维工具 Puppet CFengine Chef SaltStack 的优点 实现了批量系统配置 批量程序部署 批量运行命令等功能 Ansible是基
  • 管理者一定要戒掉这五个毛病,否则迟早被淘汰出局

    在职场中 很多人都想升职加薪 但是不是每个人都有能力当一个好的领导 有的人不断的为之努力 有的好不容易当上了领导 可以结果时间不长反而被辞退 并不是他们不够努力 而是当员工和领导有很大的差别 你的思维要及时调整 如果思维还停留在以前 那么只
  • rsyslog无法发送日志到server端问题定位

    问题描述 网络正常的情况下 代码端中使用openlog无法正常将日志发往syslog服务器 即使使用logger也无法正常发送 环境 ARM设备充当client端 pc虚拟机Ubuntu充当server端 验证方式 通过wireshark抓
  • 基于AF的HTTP

    搬搬砖头而已 iOS 基于AF的HTTP请求类 OKHTTPRequestManager h OKHTTPRequestManager h LL Created by Morris on 2020 9 22 Copyright 2020 L
  • 蓝桥杯训练——最小乘积(基本型)

    试题 算法训练 最小乘积 基本型 资源限制 时间限制 1 0s 内存限制 512 0MB 问题描述 给两组数 各n个 请调整每组数的排列顺序 使得两组数据相同下标元素对应相乘 然后相加的和最小 要求程序输出这个最小值 例如两组数分别为 1
  • Java设计模式——单例模式

    文章目录 为什么要用单例模式 单例模式 饿汉式 DCL 静态内部类 为什么要用单例模式 单例对象 Singleton 是一种常用的设计模式 在Java应用中 单例对象能保证在一个JVM中 该对象只有一个实例存在 这样的模式有几个好处 某些类
  • 大数相加和大数相乘

    1 大数相加 int或者long类型的数据往往满足不了数据容量的要求 这时需要用到数组或者字符串进行操作 考虑到数据的位数并不是一个确定的值 运用string来处理可以简化思维 在进行运算之前 需要明确下面几点要求 1 将两组数据中位数大的
  • vue单页面给页面添加锚点实现锚点跳转

    使用Element scrollIntoView 详情情查看 scrollIntoView 参数 alignToTop可选 一个Boolean值 如果为true 元素的顶端将和其所在滚动区的可视区域的顶端对齐 相应的 scrollIntoV
  • 虚拟专用网拨号出现错误提示:没有设置允许基本路由封装GRE协议数据包通过-原因解决方法

    今天给用户配置虚拟专用网拨号到单位的服务器 操作系统为win10 执行拨号后 提示上面的信息经过百度搜索 发现这个问题和网络运营商有关系 因为你使用的是移动或联通宽带 服务商阻止了虚拟专用网通道 只要换电信宽带就好了 恰巧就是使用了联通的移
  • C语言工资管理系统

    include
  • 03.前后端分离中台框架 zhontai 项目代码生成器的使用

    zhontai 项目 基于 Net7 x Vue 等技术的前后端分离后台权限管理系统 想你所想的开发理念 希望减少工作量 帮助大家实现快速开发 后端地址 https github com zhontai Admin Core 前端地址 ht
  • flutter实现APP版本更新(全局弹窗overlay实现)

    升级说明 Android 应用内更新下载 安装 iOS 跳转到appstore下载安装 注 可以通过热更新技术进行升级 我不会 引用插件 获取当前版本 package info 0 4 3 2 版本内更新 ota update 2 4 1
  • Mac下终端(Terminal)中打开某应用的技巧

    Mac下一般都是点击某一个应用的图标 或者在Alfred中键入应用名称打开该应用 但有时候在终端执行某些代码 此时想打开程序 以上操作都不流畅 所以琢磨能否在终端下直接打开某些程序 比如要 编辑路径下的shell脚本文件 但又不想使用vim
  • 基于Stable Diffusion的AIGC服饰穿搭实践

    本文主要介绍了基于Stable Diffusion技术的虚拟穿搭试衣的研究探索工作 文章展示了使用LoRA ControlNet Inpainting SAM等工具的方法和处理流程 并陈述了部分目前的实践结果 通过阅读这篇文章 读者可以了解
  • python爬虫学习笔记-requests高级

    简历模板下载拓展 import requests from lxml import etree import os headers User Agent Mozilla 5 0 Macintosh Intel Mac OS X 10 15
  • http与websocket

    http与websocket HTTP 是一个在计算机世界里专门在两点之间传输文字 图片 音频 视频等超文本数据的约定和规范 WebSocket是HTML5出的东西 协议 也就是说HTTP协议没有变化 或者说没关系 但HTTP是不支持持久连
  • 小程序中使用CANVAS实现手写签名并写入模板图片中

    实测 开发者工具中滚动条位置会影响书写 显示会有些问题 并且会卡顿 安卓 苹果手机上测试正常 index js const App getApp Page 页面的初始数据 data curScrollTop 0 生命周期函数 监听页面加载