导读:微信小程序手写签名,先来看一下效果jsPage({data:{canvasName:'handWriting',ctx:'',canvasWidth:0,canvasHeight:0,trans...
微信小程序手写签名,先来看一下效果
js
- Page({
- data: {
- canvasName: 'handWriting',
- ctx: '',
- canvasWidth: 0,
- canvasHeight: 0,
- transparent: 1,
- selectColor: 'black',
- lineColor: '#1a1a1a',
- lineSize: 1.5,
- lineMin: 0.5,
- lineMax: 8,
- 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: [],
- half: 0
- },
- onLoad() {
- let canvasName = this.data.canvasName
- let ctx = wx.createCanvasContext(canvasName)
- this.setData({
- ctx: ctx
- })
- var query = wx.createSelectorQuery();
- query.select('.handCenter').boundingClientRect(rect => {
-
- this.setData({
- canvasWidth: rect.width,
- canvasHeight: rect.height
- })
-
-
- this.setCanvasBg('#fff');
-
-
- }).exec();
-
- },
-
-
- uploadScaleStart(e) {
- if (e.type != 'touchstart') return false;
- let ctx = this.data.ctx;
- ctx.setFillStyle(this.data.lineColor);
- ctx.setGlobalAlpha(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) {
- this.data.half++;
- if ((this.data.half % 3) != 0) {
- return false
- }
- 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.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
- })
- 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({
- half: 0,
- linePrack,
- currentLine: []
- })
- },
- retDraw() {
- this.data.ctx.clearRect(0, 0, 700, 730)
- this.data.ctx.draw();
-
-
- this.setCanvasBg("#fff");
- },
-
-
- pointToLine(line) {
- this.calcBethelLine(line);
- return;
- },
-
- 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.setFillStyle(color);
- ctx.setStrokeStyle(color);
- } else {
- ctx.setFillStyle(point[0].color);
- ctx.setStrokeStyle(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();
- }
- ctx.draw(true)
- },
- selectColorEvent(event) {
- console.log(event)
- var color = event.currentTarget.dataset.colorValue;
- var colorSelected = event.currentTarget.dataset.color;
- this.setData({
- selectColor: colorSelected,
- lineColor: color
- })
- },
- setCanvasBg(color) {
- this.data.ctx.rect(0, 0, this.data.canvasWidth, this.data.canvasHeight - 4);
-
- this.data.ctx.setFillStyle(color)
- this.data.ctx.fill()
- this.data.ctx.draw()
-
- }
- })
wxml
- <view class="container">
- <view class="handCenter">
- <canvas class="handWriting" disable-scroll="true" bindtouchstart="uploadScaleStart" bindtouchmove="uploadScaleMove"
- bindtouchend="uploadScaleEnd" bindtap="mouseDown" canvas-id="handWriting">
- </canvas>
- </view>
- <button style="margin-top:20rpx" catchtap="retDraw">重写</button>
- </view>
wxss
- .handWriting {
- background: #fff;
- width: 500rpx;
- height: 700rpx;
- }
-
- .handRight {
- display: inline-flex;
- align-items: center;
- }
-
- .handCenter {
- box-shadow: 0 4px 12px rgba(0,0,0,.25);
- flex: 5;
- overflow: hidden;
- box-sizing: border-box;
- margin-top: 30rpx;
- }
-
- .handTitle {
- transform: rotate(90deg);
- flex: 1;
- color: #666;
- }
-
- .handBtn button {
- font-size: 28rpx;
- }
-
- .handBtn {
- height: 95vh;
- display: inline-flex;
- flex-direction: column;
- justify-content: space-between;
- align-content: space-between;
- flex: 1;
- }
-
- .delBtn {
- position: absolute;
- top: 250rpx;
- left: 0rpx;
- transform: rotate(90deg);
- color: #180303;
- }
-
- .delBtn image {
- position: absolute;
- top: 13rpx;
- left: 25rpx;
- }
-
- .subBtn {
- position: absolute;
- bottom: 52rpx;
- left: -3rpx;
- display: inline-flex;
- transform: rotate(90deg);
- background: #008ef6;
- 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;
- }