10 changed files with 623 additions and 1 deletions
@ -0,0 +1,66 @@ |
|||
// subpages/index/checkOutConfirm/index/index.js
|
|||
Page({ |
|||
|
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() { |
|||
|
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
|
|||
} |
|||
}) |
@ -0,0 +1,11 @@ |
|||
{ |
|||
"navigationStyle": "custom", |
|||
"usingComponents": { |
|||
"navigationBar": "/components/navigationBar/navigationBar", |
|||
"van-image": "@vant/weapp/image/index", |
|||
"van-button": "@vant/weapp/button/index", |
|||
"van-tab": "@vant/weapp/tab/index", |
|||
"van-tabs": "@vant/weapp/tabs/index", |
|||
"van-divider": "@vant/weapp/divider/index" |
|||
} |
|||
} |
@ -0,0 +1,2 @@ |
|||
<!--subpages/index/checkOutConfirm/index/index.wxml--> |
|||
<navigationBar title="退房确认" isSowArrow titleAlign="center"></navigationBar> |
@ -0,0 +1 @@ |
|||
/* subpages/index/checkOutConfirm/index/index.wxss */ |
@ -0,0 +1,446 @@ |
|||
// subpages/index/checkOutConfirm/sign/sign.js
|
|||
|
|||
|
|||
Page({ |
|||
data: { |
|||
canvasName: 'signCanvas', |
|||
ctx: '', |
|||
canvas: '', |
|||
canvasWidth: 0, |
|||
canvasHeight: 0, |
|||
transparent: 1, |
|||
selectColor: 'black', |
|||
lineColor: '#1A1A1A', |
|||
lineSize: 1.5, |
|||
lineMin: 0.5, |
|||
lineMax: 4, |
|||
pressure: 1, |
|||
smoothness: 60, |
|||
currentPoint: {}, |
|||
currentLine: [], |
|||
firstTouch: true, |
|||
radius: 1, |
|||
cutArea: { top: 0, right: 0, bottom: 0, left: 0 }, |
|||
bethelPoint: [], |
|||
lastPoint: 0, |
|||
chirography: [], |
|||
currentChirography: {}, |
|||
linePrack: [], |
|||
isDraw: false, |
|||
upPageNumber: 0, |
|||
offCanvas: '', |
|||
offCtx: '', |
|||
dpr: '' |
|||
}, |
|||
|
|||
onLoad: function (options) { |
|||
this.data.dpr = wx.getSystemInfoSync().pixelRatio |
|||
const query = wx.createSelectorQuery() |
|||
query |
|||
.select('.handCenter') |
|||
.boundingClientRect(rect => { |
|||
this.data.canvasWidth = rect.width * this.data.dpr |
|||
this.data.canvasHeight = rect.height * this.data.dpr |
|||
}) |
|||
.exec() |
|||
const query1 = wx.createSelectorQuery() |
|||
query1 |
|||
.select('#signCanvas') |
|||
.fields({ node: true, size: true }) |
|||
.exec(res => { |
|||
const canvas = res[0].node |
|||
this.data.ctx = canvas.getContext('2d') |
|||
canvas.width = this.data.canvasWidth |
|||
canvas.height = this.data.canvasHeight |
|||
|
|||
this.data.canvas = canvas |
|||
|
|||
this.data.ctx.scale(this.data.dpr, this.data.dpr) |
|||
this.setCanvasBg('#fff') |
|||
}) |
|||
const query2 = wx.createSelectorQuery() |
|||
query2 |
|||
.select('#offCanvas') |
|||
.fields({ node: true, size: true }) |
|||
.exec(res => { |
|||
const canvas = res[0].node |
|||
const ctx = canvas.getContext('2d') |
|||
canvas.width = this.data.canvasHeight |
|||
canvas.height = this.data.canvasWidth |
|||
this.data.offCanvas = canvas |
|||
this.data.offCtx = ctx |
|||
this.data.offCtx.scale(this.data.dpr, this.data.dpr) |
|||
}) |
|||
}, |
|||
|
|||
retDraw() { |
|||
this.data.ctx.clearRect(0, 0, 700, 730) |
|||
this.setCanvasBg('#fff') |
|||
this.data.isDraw = false |
|||
this.data.currentPoint = {} |
|||
}, |
|||
|
|||
pointToLine(line) { |
|||
this.calcBethelLine(line) |
|||
return |
|||
}, |
|||
|
|||
uploadScaleStart(e) { |
|||
if (e.type != 'touchstart') return false |
|||
let ctx = this.data.ctx |
|||
ctx.fillStyle = this.data.lineColor |
|||
ctx.globalAlpha = this.data.transparent |
|||
let currentPoint = { |
|||
x: e.touches[0].x, |
|||
y: e.touches[0].y |
|||
} |
|||
let currentLine = this.data.currentLine |
|||
currentLine.unshift({ |
|||
time: new Date().getTime(), |
|||
dis: 0, |
|||
x: currentPoint.x, |
|||
y: currentPoint.y |
|||
}) |
|||
this.setData({ |
|||
currentPoint |
|||
}) |
|||
if (this.data.firstTouch) { |
|||
this.setData({ |
|||
cutArea: { |
|||
top: currentPoint.y, |
|||
right: currentPoint.x, |
|||
bottom: currentPoint.y, |
|||
left: currentPoint.x |
|||
}, |
|||
firstTouch: false |
|||
}) |
|||
} |
|||
this.pointToLine(currentLine) |
|||
}, |
|||
|
|||
uploadScaleMove(e) { |
|||
if (e.type != 'touchmove') return false |
|||
if (e.cancelable) { |
|||
|
|||
if (!e.defaultPrevented) { |
|||
e.preventDefault() |
|||
} |
|||
} |
|||
let point = { |
|||
x: e.touches[0].x, |
|||
y: e.touches[0].y |
|||
} |
|||
|
|||
if (point.y < this.data.cutArea.top) { |
|||
this.data.cutArea.top = point.y |
|||
} |
|||
if (point.y < 0) this.data.cutArea.top = 0 |
|||
|
|||
if (point.x > this.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.y > this.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.x < this.data.cutArea.left) { |
|||
this.data.cutArea.left = point.x |
|||
} |
|||
if (point.x < 0) this.data.cutArea.left = 0 |
|||
|
|||
this.setData({ |
|||
lastPoint: this.data.currentPoint, |
|||
currentPoint: point |
|||
}) |
|||
let currentLine = this.data.currentLine |
|||
currentLine.unshift({ |
|||
time: new Date().getTime(), |
|||
dis: this.distance(this.data.currentPoint, this.data.lastPoint), |
|||
x: point.x, |
|||
y: point.y |
|||
}) |
|||
// this.setData({
|
|||
// currentLine
|
|||
// })
|
|||
this.pointToLine(currentLine) |
|||
}, |
|||
|
|||
uploadScaleEnd(e) { |
|||
if (e.type != 'touchend') return 0 |
|||
let point = { |
|||
x: e.changedTouches[0].x, |
|||
y: e.changedTouches[0].y |
|||
} |
|||
this.setData({ |
|||
lastPoint: this.data.currentPoint, |
|||
currentPoint: point |
|||
}) |
|||
let currentLine = this.data.currentLine |
|||
currentLine.unshift({ |
|||
time: new Date().getTime(), |
|||
dis: this.distance(this.data.currentPoint, this.data.lastPoint), |
|||
x: point.x, |
|||
y: point.y |
|||
}) |
|||
// this.setData({
|
|||
// currentLine
|
|||
// })
|
|||
if (currentLine.length > 2) { |
|||
var info = |
|||
(currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length |
|||
} |
|||
|
|||
this.pointToLine(currentLine) |
|||
var currentChirography = { |
|||
lineSize: this.data.lineSize, |
|||
lineColor: this.data.lineColor |
|||
} |
|||
var chirography = this.data.chirography |
|||
chirography.unshift(currentChirography) |
|||
this.setData({ |
|||
chirography |
|||
}) |
|||
var linePrack = this.data.linePrack |
|||
linePrack.unshift(this.data.currentLine) |
|||
this.setData({ |
|||
linePrack, |
|||
currentLine: [] |
|||
}) |
|||
this.data.isDraw = true |
|||
}, |
|||
|
|||
calcBethelLine(line) { |
|||
if (line.length <= 1) { |
|||
line[0].r = this.data.radius |
|||
return |
|||
} |
|||
let x0, |
|||
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 |
|||
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 |
|||
} |
|||
|
|||
len = this.distance({ x: x2, y: y2 }, { x: x0, y: y0 }) |
|||
lastRadius = this.data.radius |
|||
for (let n = 0; n < line.length - 1; n++) { |
|||
dis += line[n].dis |
|||
time += line[n].time - line[n + 1].time |
|||
if (dis > this.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 |
|||
|
|||
if (line.length <= 2) { |
|||
r0 = (lastRadius + this.data.radius) / 2 |
|||
r1 = r0 |
|||
r2 = r1 |
|||
} else { |
|||
r0 = (line[2].r + line[1].r) / 2 |
|||
r1 = line[1].r |
|||
r2 = (line[1].r + line[0].r) / 2 |
|||
} |
|||
let n = 5 |
|||
let point = [] |
|||
for (let i = 0; i < n; i++) { |
|||
let t = i / (n - 1) |
|||
let x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2 |
|||
let y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2 |
|||
let r = lastRadius + ((this.data.radius - lastRadius) / n) * i |
|||
point.push({ x: x, y: y, r: r }) |
|||
if (point.length == 3) { |
|||
let a = 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 |
|||
this.bethelDraw(a, 1) |
|||
point = [{ x: x, y: y, r: r }] |
|||
} |
|||
} |
|||
this.setData({ |
|||
currentLine: line |
|||
}) |
|||
}, |
|||
|
|||
distance(a, b) { |
|||
let x = b.x - a.x |
|||
let y = b.y - a.y |
|||
return Math.sqrt(x * x + y * y) |
|||
}, |
|||
|
|||
ctaCalc(x0, y0, r0, x1, y1, r1, x2, y2, r2) { |
|||
let a = [], |
|||
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 (let i = 1; i < a.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) |
|||
} |
|||
return a |
|||
}, |
|||
|
|||
bethelDraw(point, is_fill, color) { |
|||
let ctx = this.data.ctx |
|||
ctx.beginPath() |
|||
ctx.moveTo(point[0].mx, point[0].my) |
|||
if (undefined != color) { |
|||
ctx.fillStyle = color |
|||
ctx.strokeStyle = color |
|||
} else { |
|||
ctx.fillStyle = point[0].color |
|||
ctx.strokeStyle = point[0].color |
|||
} |
|||
for (let i = 1; i < point.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() |
|||
} |
|||
}, |
|||
|
|||
setCanvasBg(color) { |
|||
this.data.ctx.rect(0, 0, this.data.canvasWidth, this.data.canvasHeight - 4) |
|||
this.data.ctx.fillStyle = color |
|||
this.data.ctx.fill() |
|||
}, |
|||
|
|||
subCanvas() { |
|||
if (Object.keys(this.data.currentPoint).length == 0) { |
|||
wx.showModal({ |
|||
title: "提示", |
|||
content: "签名内容不能为空!", |
|||
showCancel: false |
|||
}); |
|||
} else { |
|||
console.log('========sub') |
|||
let imgSrc = this.data.canvas.toDataURL('image/png', 1) |
|||
console.log(imgSrc); |
|||
wx.showLoading({ |
|||
title: '正在跳转', |
|||
}) |
|||
setTimeout(function () { |
|||
wx.hideLoading() |
|||
wx.navigateTo({ |
|||
url: '/subpages/index/checkOutConfirm/index/index', |
|||
}) |
|||
}, 1500) |
|||
} |
|||
|
|||
}, |
|||
}) |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"usingComponents": {} |
|||
} |
@ -0,0 +1,18 @@ |
|||
<!--subpages/index/checkOutConfirm/sign/sign.wxml--> |
|||
|
|||
|
|||
<view class="container"> |
|||
<view class="handleBtn py-3 me-2"> |
|||
<button bindtap="retDraw" class="clear" type="default">重写</button> |
|||
<button bindtap="subCanvas" class="confirm" type="primary">完成</button> |
|||
</view> |
|||
<view class="handCenter"> |
|||
<canvas class="handWriting" disable-scroll="true" bindtouchstart="uploadScaleStart" bindtouchmove="uploadScaleMove" bindtouchend="uploadScaleEnd" type="2d" id="signCanvas"></canvas> |
|||
</view> |
|||
<view class="handRight"> |
|||
<view class="handTitle">请签字</view> |
|||
</view> |
|||
</view> |
|||
<view style="position:absolute;left:0rpx;top:0;"> |
|||
<canvas type="2d" id="offCanvas" style="width: 100%; height: 100vh;"></canvas> |
|||
</view> |
@ -0,0 +1,66 @@ |
|||
/* subpages/index/checkOutConfirm/sign/sign.wxss */ |
|||
|
|||
|
|||
.container { |
|||
width: 100%; |
|||
height: 100vh; |
|||
padding: 30rpx 0; |
|||
overflow: hidden; |
|||
display: flex; |
|||
align-content: center; |
|||
flex-direction: row; |
|||
justify-content: center; |
|||
font-size: 28rpx; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.handleBtn { |
|||
display: inline-flex; |
|||
flex-direction: column; |
|||
justify-content: space-between; |
|||
align-content: space-between; |
|||
flex: 1; |
|||
padding-right: 20rpx; |
|||
box-sizing: border-box; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.handleBtn button { |
|||
text-align: center; |
|||
transform: rotate(90deg); |
|||
} |
|||
.handleBtn button:not([size="mini"]) { |
|||
width: 160rpx; |
|||
margin-top: 130rpx; |
|||
margin-bottom: 130rpx; |
|||
} |
|||
.handleBtn .clear { |
|||
margin-right:32rpx; |
|||
background-color: #eee; |
|||
} |
|||
|
|||
.handleBtn .confirm { |
|||
color: #fff; |
|||
background-color: #42d9d3; |
|||
} |
|||
.handCenter { |
|||
border: 4rpx dashed #e9e9e9; |
|||
flex: 5; |
|||
overflow: hidden; |
|||
box-sizing: border-box; |
|||
} |
|||
.handRight { |
|||
display: inline-flex; |
|||
align-items: center; |
|||
} |
|||
.handRight .handTitle { |
|||
transform: rotate(90deg); |
|||
flex: 1; |
|||
color: #666; |
|||
} |
|||
.handWriting { |
|||
background: #fff; |
|||
width: 100%; |
|||
height: 95vh; |
|||
flex: 2; |
|||
} |
Loading…
Reference in new issue