




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第微信小程序?qū)崿F(xiàn)橫屏和豎屏簽名功能本文實(shí)例為大家分享了微信小程序?qū)崿F(xiàn)橫屏和豎屏簽名的具體代碼,供大家參考,具體內(nèi)容如下
wxml
view
canvascanvas-id="firstCanvas"id="firstCanvas"bindtouchstart="bindtouchstart"bindtouchmove="bindtouchmove"/canvas
view
buttontype="warn"bindtap="clear"
清除
/button
buttontype="primary"
bindtap="export"
確定
/button
/view
/view
wxss
#firstCanvas{
width:750rpx;
height:600rpx;
background-color:#fff;
}
js
constapp=getApp()
Page({
data:{
context:null,
index:0,
height:0,
width:0
/**記錄開始點(diǎn)*/
bindtouchstart:function(e){
this.data.context.moveTo(e.changedTouches[0].x,e.changedTouches[0].y)
/**記錄移動(dòng)點(diǎn),刷新繪制*/
bindtouchmove:function(e){
this.data.context.lineTo(e.changedTouches[0].x,e.changedTouches[0].y);
this.data.context.stroke();
this.data.context.draw(true);
this.data.context.moveTo(e.changedTouches[0].x,e.changedTouches[0].y);
/**清空畫布*/
clear:function(){
this.data.context.clearRect(0,0,this.data.width,this.data.height);
this.data.context.draw();
this.data.context.setStrokeStyle('#00ff00')
this.data.context.setLineWidth(2)
this.data.context.setFontSize(20)
letstr="簽名區(qū)域";
this.data.context.fillText(str,Math.ceil((this.data.width-this.data.context.measureText(str).width)/2),Math.ceil(this.data.height/2)-20)
this.data.context.draw()
base64(url,type){
returnnewPromise((resolve,reject)={
wx.getFileSystemManager().readFile({
filePath:url,
encoding:'base64',
success(res){
resolve('data:img/'+type.toLocaleLowerCase()+':base64,'+res.data)
},
fail(){
reject()
}
})
})
/**導(dǎo)出圖片*/
export:function(){
constthat=this;
this.data.context.draw(false,wx.canvasToTempFilePath({
x:0,
y:0,
width:that.data.width,
height:that.data.height,
destWidth:that.data.width,
destHeight:that.data.height,
fileType:'jpg',
canvasId:'firstCanvas',
success(res){
leturl=res.tempFilePath
that.base64(url,'jpg').then(res={
console.log('base64數(shù)據(jù)流',res);
varpages=getCurrentPages();
varprevPage=pages[pages.length-2];//上一個(gè)頁面
//直接調(diào)用上一個(gè)頁面的setData()方法,把數(shù)據(jù)存到上一個(gè)頁面中去
prevPage.setData({
sign:{
sign:res,
}
})
wx.navigateBack({//返回
delta:1
})
})
},
fail(){
wx.showToast({
title:'導(dǎo)出失敗',
icon:'none',
duration:2000
})
}
}))
onShow:function(){
letquery=wx.createSelectorQuery();
constthat=this;
query.select('#firstCanvas').boundingClientRect();
query.exec((rect)={
letwidth=rect[0].width;
letheight=rect[0].height;
that.setData({
width,
height
});
constcontext=wx.createCanvasContext('firstCanvas')
that.setData({
context:context
})
that.data.context.setLineWidth(2)
that.data.context.setLineCap('round')
});
})
效果
橫屏
view
view
imagecatchtap="selectColorEvent"src="{{selectColor==='black''../../public/image/index/sign/color_black_selected.png':'../../public/image/index/sign/color_black.png'}}"class="{{selectColor==='black''color_select':''}}black-select"data-color="black"
data-color-value="#1A1A1A"/image
imagecatchtap="selectColorEvent"src="{{selectColor==='red''../../public/image/index/sign/color_red_selected.png':'../../public/image/index/sign/color_red.png'}}"class="{{selectColor==='red''color_select':''}}red-select"data-color="red"
data-color-value="#ca262a"/image
buttoncatchtap="retDraw"重寫/button
buttoncatchtap="saveCanvasAsImg"保存/button
buttoncatchtap="previewCanvasImg"預(yù)覽/button
buttoncatchtap="uploadCanvasImg"上傳/button
buttoncatchtap="subCanvas"完成/button
/view
view
canvasdisable-scroll="true"bindtouchstart="uploadScaleStart"bindtouchmove="uploadScaleMove"
bindtouchend="uploadScaleEnd"bindtap="mouseDown"canvas-id="handWriting"
/canvas
/view
view
view手寫板/view
/view
/view
wxss
page{
background:#fbfbfb;
height:auto;
overflow:hidden;
.wrapper{
width:100%;
height:95vh;
margin:30rpx0;
overflow:hidden;
display:flex;
align-content:center;
flex-direction:row;
justify-content:center;
font-size:28rpx;
.handWriting{
background:#fff;
width:100%;
height:95vh;
.handRight{
display:inline-flex;
align-items:center;
.handCenter{
border:4rpxdashed#e9e9e9;
flex:5;
overflow:hidden;
box-sizing:border-box;
.handTitle{
transform:rotate(90deg);
flex:1;
color:#666;
.handBtnbutton{
font-size:28rpx;
.handBtn{
height:95vh;
display:inline-flex;
flex-direction:column;
align-items:center;
flex:1;
.delBtn,
.saveBtn,
.previewBtn,
.uploadBtn,
.subBtn{
width:160rpx!important;
height:70rpx;
border:2rpxsolid#eeeeee;
transform:rotate(90deg);
color:#666;
.delBtn{
position:absolute;
bottom:850rpx;
.saveBtn{
position:absolute;
bottom:660rpx;
.previewBtn{
position:absolute;
bottom:470rpx;
.uploadBtn{
position:absolute;
bottom:280rpx;
.subBtn{
position:absolute;
bottom:52rpx;
display:inline-flex;
transform:rotate(90deg);
background:#218FFC;
color:#fff;
margin-bottom:30rpx;
text-align:center;
justify-content:center;
.black-select{
width:60rpx;
height:60rpx;
position:absolute;
top:30rpx;
left:25rpx;
.black-select.color_select{
width:90rpx;
height:90rpx;
top:30rpx;
left:10rpx;
.red-select{
width:60rpx;
height:60rpx;
position:absolute;
top:140rpx;
left:25rpx;
.red-select.color_select{
width:90rpx;
height:90rpx;
top:120rpx;
left:10rpx;
}
js
Page({
data:{
canvasName:'handWriting',
ctx:'',
canvasWidth:0,
canvasHeight:0,
transparent:1,//透明度
selectColor:'black',
lineColor:'#1A1A1A',//顏色
lineSize:1.5,
//筆記倍數(shù)
lineMin:0.5,
//最小筆畫半徑
lineMax:4,
//最大筆畫半徑
pressure:1,
//默認(rèn)壓力
smoothness:60,
//順滑度,用60的距離來計(jì)算速度
currentPoint:{},
currentLine:[],
//當(dāng)前線條
firstTouch:true,//第一次觸發(fā)
radius:1,//畫圓的半徑
cutArea:{top:0,right:0,bottom:0,left:0},//裁剪區(qū)域
bethelPoint:[],
//保存所有線條生成的貝塞爾點(diǎn);
lastPoint:0,
chirography:[],//筆跡
currentChirography:{},//當(dāng)前筆跡
signImg:'signImg',
linePrack:[]//劃線軌跡,生成線條的實(shí)際點(diǎn)
onLoad(options){
this.setData({
signImg:s,
})
letcanvasName=this.data.canvasName
letctx=wx.createCanvasContext(canvasName)
this.setData({
ctx:ctx
})
varquery=wx.createSelectorQuery();
query.select('.handCenter').boundingClientRect(rect={
this.setData({
canvasWidth:rect.width,
canvasHeight:rect.height
})
/*將canvas背景設(shè)置為白底,不設(shè)置
導(dǎo)出的canvas的背景為透明*/
//console.log(this,'hahah');
this.setCanvasBg('#fff');
}).exec();
//筆跡開始
uploadScaleStart(e){
if(e.type!='touchstart')returnfalse;
letctx=this.data.ctx;
ctx.setFillStyle(this.data.lineColor);
//初始線條設(shè)置顏色
ctx.setGlobalAlpha(this.data.transparent);
//設(shè)置半透明
letcurrentPoint={
x:e.touches[0].x,
y:e.touches[0].y
}
letcurrentLine=this.data.currentLine;
currentLine.unshift({
time:newDate().getTime(),
dis:0,
x:currentPoint.x,
y:currentPoint.y
})
this.setData({
currentPoint,
//currentLine
})
if(this.data.firstTouch){
this.setData({
cutArea:{top:currentPoint.y,right:currentPoint.x,bottom:currentPoint.y,left:currentPoint.x},
firstTouch:false
})
}
this.pointToLine(currentLine);
//筆跡移動(dòng)
uploadScaleMove(e){
if(e.type!='touchmove')returnfalse;
if(e.cancelable){
//判斷默認(rèn)行為是否已經(jīng)被禁用
if(!e.defaultPrevented){
e.preventDefault();
}
}
letpoint={
x:e.touches[0].x,
y:e.touches[0].y
}
//測試裁剪
if(point.ythis.data.cutArea.top){
this.data.cutArea.top=point.y;
}
if(point.y0)this.data.cutArea.top=0;
if(point.xthis.data.cutArea.right){
this.data.cutArea.right=point.x;
}
if(this.data.canvasWidth-point.x=0){
this.data.cutArea.right=this.data.canvasWidth;
}
if(point.ythis.data.cutArea.bottom){
this.data.cutArea.bottom=point.y;
}
if(this.data.canvasHeight-point.y=0){
this.data.cutArea.bottom=this.data.canvasHeight;
}
if(point.xthis.data.cutArea.left){
this.data.cutArea.left=point.x;
}
if(point.x0)this.data.cutArea.left=0;
this.setData({
lastPoint:this.data.currentPoint,
currentPoint:point
})
letcurrentLine=this.data.currentLine
currentLine.unshift({
time:newDate().getTime(),
dis:this.distance(this.data.currentPoint,this.data.lastPoint),
x:point.x,
y:point.y
})
//this.setData({
//
currentLine
//})
this.pointToLine(currentLine);
//筆跡結(jié)束
uploadScaleEnd(e){
if(e.type!='touchend')return0;
letpoint={
x:e.changedTouches[0].x,
y:e.changedTouches[0].y
}
this.setData({
lastPoint:this.data.currentPoint,
currentPoint:point
})
letcurrentLine=this.data.currentLine
currentLine.unshift({
time:newDate().getTime(),
dis:this.distance(this.data.currentPoint,this.data.lastPoint),
x:point.x,
y:point.y
})
//this.setData({
//
currentLine
//})
if(currentLine.length2){
varinfo=(currentLine[0].time-currentLine[currentLine.length-1].time)/currentLine.length;
//$("#info").text(info.toFixed(2));
}
//一筆結(jié)束,保存筆跡的坐標(biāo)點(diǎn),清空,當(dāng)前筆跡
//增加判斷是否在手寫區(qū)域;
this.pointToLine(currentLine);
varcurrentChirography={
lineSize:this.data.lineSize,
lineColor:this.data.lineColor
};
varchirography=this.data.chirography
chirography.unshift(currentChirography);
this.setData({
chirography
})
varlinePrack=this.data.linePrack
linePrack.unshift(this.data.currentLine);
this.setData({
linePrack,
currentLine:[]
})
retDraw(){
this.data.ctx.clearRect(0,0,700,730)
this.data.ctx.draw();
//設(shè)置canvas背景
this.setCanvasBg("#fff");
//畫兩點(diǎn)之間的線條;參數(shù)為:line,會(huì)繪制最近的開始的兩個(gè)點(diǎn);
pointToLine(line){
this.calcBethelLine(line);
return;
//計(jì)算插值的方式;
calcBethelLine(line){
if(line.length=1){
line[0].r=this.data.radius;
return;
}
letx0,x1,x2,y0,y1,y2,r0,r1,r2,len,lastRadius,dis=0,time=0,curveValue=0.5;
if(line.length=2){
x0=line[1].x
y0=line[1].y
x2=line[1].x+(line[0].x-line[1].x)*curveValue;
y2=line[1].y+(line[0].y-line[1].y)*curveValue;
//x2=line[1].x;
//y2=line[1].y;
x1=x0+(x2-x0)*curveValue;
y1=y0+(y2-y0)*curveValue;;
}else{
x0=line[2].x+(line[1].x-line[2].x)*curveValue;
y0=line[2].y+(line[1].y-line[2].y)*curveValue;
x1=line[1].x;
y1=line[1].y;
x2=x1+(line[0].x-x1)*curveValue;
y2=y1+(line[0].y-y1)*curveValue;
}
//從計(jì)算公式看,三個(gè)點(diǎn)分別是(x0,y0),(x1,y1),(x2,y2);(x1,y1)這個(gè)是控制點(diǎn),控制點(diǎn)不會(huì)落在曲線上;實(shí)際上,這個(gè)點(diǎn)還會(huì)手寫獲取的實(shí)際點(diǎn),卻落在曲線上
len=this.distance({x:x2,y:y2},{x:x0,y:y0});
lastRadius=this.data.radius;
for(letn=0;nline.length-1;n++){
dis+=line[n].dis;
time+=line[n].time-line[n+1].time;
if(disthis.data.smoothness)break;
}
this.setData({
radius:Math.min(time/len*this.data.pressure+this.data.lineMin,this.data.lineMax)*this.data.lineSize
});
line[0].r=this.data.radius;
//計(jì)算筆跡半徑;
if(line.length=2){
r0=(lastRadius+this.data.radius)/2;
r1=r0;
r2=r1;
//return;
}else{
r0=(line[2].r+line[1].r)/2;
r1=line[1].r;
r2=(line[1].r+line[0].r)/2;
}
letn=5;
letpoint=[];
for(leti=0;ii++){
lett=i/(n-1);
letx=(1-t)*(1-t)*x0+2*t*(1-t)*x1+t*t*x2;
lety=(1-t)*(1-t)*y0+2*t*(1-t)*y1+t*t*y2;
letr=lastRadius+(this.data.radius-lastRadius)/n*i;
point.push({x:x,y:y,r:r});
if(point.length==3){
leta=this.ctaCalc(point[0].x,point[0].y,point[0].r,point[1].x,point[1].y,point[1].r,point[2].x,point[2].y,point[2].r);
a[0].color=this.data.lineColor;
//letbethelPoint=this.data.bethelPoint;
//console.log(a)
//console.log(this.data.bethelPoint)
//bethelPoint=bethelPoint.push(a);
this.bethelDraw(a,1);
point=[{x:x,y:y,r:r}];
}
}
this.setData({
currentLine:line
})
//求兩點(diǎn)之間距離
distance(a,b){
letx=b.x-a.x;
lety=b.y-a.y;
returnMath.sqrt(x*x+y*y);
ctaCalc(x0,y0,r0,x1,y1,r1,x2,y2,r2){
leta=[],vx01,vy01,norm,n_x0,n_y0,vx21,vy21,n_x2,n_y2;
vx01=x1-x0;
vy01=y1-y0;
norm=Math.sqrt(vx01*vx01+vy01*vy01+0.0001)*2;
vx01=vx01/norm*r0;
vy01=vy01/norm*r0;
n_x0=vy01;
n_y0=-vx01;
vx21=x1-x2;
vy21=y1-y2;
norm=Math.sqrt(vx21*vx21+vy21*vy21+0.0001)*2;
vx21=vx21/norm*r2;
vy21=vy21/norm*r2;
n_x2=-vy21;
n_y2=vx21;
a.push({mx:x0+n_x0,my:y0+n_y0,color:"#1A1A1A"});
a.push({c1x:x1+n_x0,c1y:y1+n_y0,c2x:x1+n_x2,c2y:y1+n_y2,ex:x2+n_x2,ey:y2+n_y2});
a.push({c1x:x2+n_x2-vx21,c1y:y2+n_y2-vy21,c2x:x2-n_x2-vx21,c2y:y2-n_y2-vy21,ex:x2-n_x2,ey:y2-n_y2});
a.push({c1x:x1-n_x2,c1y:y1-n_y2,c2x:x1-n_x0,c2y:y1-n_y0,ex:x0-n_x0,ey:y0-n_y0});
a.push({c1x:x0-n_x0-vx01,c1y:y0-n_y0-vy01,c2x:x0+n_x0-vx01,c2y:y0+n_y0-vy01,ex:x0+n_x0,ey:y0+n_y0});
a[0].mx=a[0].mx.toFixed(1);
a[0].mx=parseFloat(a[0].mx);
a[0].my=a[0].my.toFixed(1);
a[0].my=parseFloat(a[0].my);
for(leti=1;ia.length;i++){
a[i].c1x=a[i].c1x.toFixed(1);
a[i].c1x=parseFloat(a[i].c1x);
a[i].c1y=a[i].c1y.toFixed(1);
a[i].c1y=parseFloat(a[i].c1y);
a[i].c2x=a[i].c2x.toFixed(1);
a[i].c2x=parseFloat(a[i].c2x);
a[i].c2y=a[i].c2y.toFixed(1);
a[i].c2y=parseFloat(a[i].c2y);
a[i].ex=a[i].ex.toFixed(1);
a[i].ex=parseFloat(a[i].ex);
a[i].ey=a[i].ey.toFixed(1);
a[i].ey=parseFloat(a[i].ey);
}
returna;
bethelDraw(point,is_fill,color){
letctx=this.data.ctx;
ctx.beginPath();
ctx.moveTo(point[0].mx,point[0].my);
if(undefined!=color){
ctx.setFillStyle(color);
ctx.setStrokeStyle(color);
}else{
ctx.setFillStyle(point[0].color);
ctx.setStrokeStyle(point[0].color);
}
for(leti=1;ipoint.length;i++){
ctx.bezierCurveTo(point[i].c1x,point[i].c1y,point[i].c2x,point[i].c2y,point[i].ex,point[i].ey);
}
ctx.stroke();
if(undefined!=is_fill){
ctx.fill();//填充圖形(后繪制的圖形會(huì)覆蓋前面的圖形,繪制時(shí)注意先后順序)
}
ctx.draw(true)
selectColorEvent(event){
console.log(event)
varcolor=event.currentTarget.dataset.colorValue;
varcolorSelected=event.currentTarget.dataset.color;
this.setData({
selectColor:colorSelected,
lineColor:color
})
//設(shè)置背景函數(shù)
//設(shè)置canvas背景色
不設(shè)置
導(dǎo)出的canvas的背景為透明
//@params:字符串
color
setCanvasBg(color){
/*將canvas背景設(shè)置為白底,不設(shè)置
導(dǎo)出的canvas的背景為透明*/
//rect()參數(shù)說明
矩形路徑左上角的橫坐標(biāo),左上角的縱坐標(biāo),矩形路徑的寬度,矩形路徑的高度
//這里是canvasHeight-4是因?yàn)橄逻吷w住邊框了,所以手動(dòng)減了寫
this.data.ctx.rect(0,0,this.data.canvasWidth,this.data.canvasHeight-4);
//ctx.setFillStyle('red')
this.data.ctx.setFillStyle(color)
this.data.ctx.fill()
//設(shè)置填充
this.data.ctx.draw()
//開畫
//保存到相冊
saveCanvasAsImg(){
wx.canvasToTempFilePath({
canvasId:'handWriting',
fileType:'png',
quality:1,//圖片質(zhì)量
success(res){
//console.log(res.tempFilePath,'canvas生成圖片地址');
wx.saveImageToPhotosAlbum({
filePath:res.tempFilePath,
success(res){
wx.showToast({
title:'已保存到相冊',
duration:2000
});
}
})
}
})
//預(yù)覽
previewCanvasImg(){
wx.canvasToTempFilePath({
canvasId:'handWriting',
fileType:'jpg',
quality:1,//圖片質(zhì)量
success(res){
//console.log(res.tempFilePath,'canvas生成圖片地址');
wx.previewImage({
urls:[res.tempFilePath],//預(yù)覽圖片數(shù)組
})
}
})
//上傳
uploadCanvasImg(){
wx.canvasToTempFilePath({
canvasId:'handWriting',
fileType:'png',
quality:1,//圖片質(zhì)量
success(res)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 活動(dòng)項(xiàng)目合作合同協(xié)議書
- 天氣預(yù)報(bào)兒童課件
- 中國硫酸胍項(xiàng)目創(chuàng)業(yè)投資方案
- 校園快遞合作合同協(xié)議書
- 抖音小店合同協(xié)議書
- 2025年焦煤項(xiàng)目調(diào)研分析報(bào)告
- 工程勞務(wù)合同和協(xié)議書
- 合伙開水果合同協(xié)議書
- 大米供貨合同協(xié)議書范本
- 運(yùn)動(dòng)館合伙合同協(xié)議書
- 2025年耐熱玻璃器皿行業(yè)深度研究報(bào)告
- 2025年中考物理答題技巧與模式專題08壓強(qiáng)與浮力的??茧y點(diǎn)綜合計(jì)算(學(xué)生版+解析)
- 護(hù)理影像學(xué)試題及答案總結(jié)
- DB65-T 4623-2022 分散式風(fēng)電接入電力系統(tǒng)管理規(guī)范
- 水電使用合同協(xié)議書
- 退休終止勞動(dòng)合同協(xié)議書
- 血液透析機(jī)試題及答案
- NB/T 11646-2024井工煤礦采空區(qū)自然發(fā)火監(jiān)測預(yù)警技術(shù)規(guī)范
- 實(shí)驗(yàn)室質(zhì)量管理體系與試題
- 嬰幼兒期的食物過敏識(shí)別與管理考核試題及答案
- 江蘇省宿遷市2024年中考道德與法治真題試卷含解析答案
評(píng)論
0/150
提交評(píng)論