网站 keywords,郑州正规网站制作公司,无锡高端网站开发,微信小程序开发视频完整教程网上找了个源码改吧改吧#xff0c;清除了没用的功能和兼容性#xff0c;基于uniapp开发的 样子 vue2 使用方法#xff0c;具体的可以根据业务自行修改 signature refsignature width100% height410rpx/signatureconfi…网上找了个源码改吧改吧清除了没用的功能和兼容性基于uniapp开发的 样子 vue2 使用方法具体的可以根据业务自行修改 signature refsignature width100% height410rpx/signatureconfirm(){this.$refs[signature].getCavasTempFile((url) {//外部调用子组件的方法获取签名的base64})
} vue2源码 templateview classcanvas_wrapper refcanvas_wrappers :stylecanvasStylecanvas classhandWriting disable-scrolltrue touchstartuploadScaleStart touchmoveuploadScaleMovetouchenduploadScaleEnd canvas-idhandWriting/canvas/view
/templatescriptexport default {props: {width: {type: String,default: 100%},height: {type: String,default: 200rpx},},data() {return {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, //顺滑度用60的距离来计算速度currentPoint: {},currentLine: [], // 当前线条firstTouch: true, // 第一次触发radius: 1, //画圆的半径cutArea: {top: 0,right: 0,bottom: 0,left: 0}, //裁剪区域bethelPoint: [], //保存所有线条 生成的贝塞尔点lastPoint: 0,chirography: [], //笔迹currentChirography: {}, //当前笔迹linePrack: [], //划线轨迹 , 生成线条的实际点half: 0 //绘制一半点};},computed: {canvasStyle() {return width:${this.widht};height:${this.height}}},mounted() {this.containerEnter()},methods: {containerEnter() {let canvasName this.canvasNamelet ctx uni.createCanvasContext(canvasName, this)this.ctx ctx;var query uni.createSelectorQuery().in(this);query.select(.canvas_wrapper).boundingClientRect(rect {this.canvasWidth rect.width;this.canvasHeight rect.height;/* 将canvas背景设置为 白底不设置 导出的canvas的背景为透明 */this.setCanvasBg(rgba(0,0,0,0));}).exec();},containerAfter() {this.retDraw()},// 获取临时文件getCavasTempFile(fn) {uni.canvasToTempFilePath({destWidth: 200,destHeight: 200,canvasId: handWriting,success: (res) {//签名成功回调fn(res.tempFilePath)this.containerAfter()},fail: (err) {console.log(图片临时文件生成失败, err);}}, this)},// 笔迹开始uploadScaleStart(e) {if (e.type ! touchstart) return false;this.ctx.setFillStyle(this.lineColor); // 初始线条设置颜色this.ctx.setGlobalAlpha(this.transparent); // 设置半透明let currentPoint {x: e.touches[0].x,y: e.touches[0].y}let currentLine this.currentLine;currentLine.unshift({time: new Date().getTime(),dis: 0,x: currentPoint.x,y: currentPoint.y})this.currentPoint currentPointif (this.firstTouch) {this.currentPoint {top: currentPoint.y,right: currentPoint.x,bottom: currentPoint.y,left: currentPoint.x}this.firstTouch false;}this.pointToLine(currentLine);},// 笔迹移动uploadScaleMove(e) {this.half;if ((this.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.cutArea.top) {this.cutArea.top point.y;}if (point.y 0) this.cutArea.top 0;if (point.x this.cutArea.right) {this.cutArea.right point.x;}if (this.canvasWidth - point.x 0) {this.cutArea.right this.canvasWidth;}if (point.y this.cutArea.bottom) {this.cutArea.bottom point.y;}if (this.canvasHeight - point.y 0) {this.cutArea.bottom this.canvasHeight;}if (point.x this.cutArea.left) {this.cutArea.left point.x;}if (point.x 0) this.cutArea.left 0;this.lastPoint this.currentPointthis.currentPoint pointlet currentLine this.currentLinecurrentLine.unshift({time: new Date().getTime(),dis: this.distance(this.currentPoint, this.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.lastPoint this.currentPoint;this.currentPoint point;let currentLine this.currentLinecurrentLine.unshift({time: new Date().getTime(),dis: this.distance(this.currentPoint, this.lastPoint),x: point.x,y: point.y})if (currentLine.length 2) {var info (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;//$(#info).text(info.toFixed(2));}//一笔结束保存笔迹的坐标点清空当前笔迹//增加判断是否在手写区域this.pointToLine(currentLine);var currentChirography {lineSize: this.lineSize,lineColor: this.lineColor};var chirography this.chirographychirography.unshift(currentChirography);this.chirography chirographyvar linePrack this.linePracklinePrack.unshift(this.currentLine);this.half 0;this.linePrack linePrack;this.currentLine [];},retDraw() {this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)this.ctx.draw();//设置canvas背景this.setCanvasBg(rgba(0,0,0,0));},//画两点之间的线条参数为:line会绘制最近的开始的两个点pointToLine(line) {this.calcBethelLine(line);return;},//计算插值的方式calcBethelLine(line) {if (line.length 1) {line[0].r this.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].xy0 line[1].yx2 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;}//从计算公式看三个点分别是(x0,y0),(x1,y1),(x2,y2) (x1,y1)这个是控制点控制点不会落在曲线上实际上这个点还会手写获取的实际点却落在曲线上len this.distance({x: x2,y: y2}, {x: x0,y: y0});lastRadius this.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.smoothness) break;}this.radius Math.min(time / len * this.pressure this.lineMin, this.lineMax) * this.lineSizeline[0].r this.radius;//计算笔迹半径if (line.length 2) {r0 (lastRadius this.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;}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.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.lineColor;this.bethelDraw(a, 1);point [{x: x,y: y,r: r}];}}this.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.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) {var color event.currentTarget.dataset.colorValue;var colorSelected event.currentTarget.dataset.color;this.selectColor colorSelected;this.lineColor color;},setCanvasBg(color) {this.ctx.rect(0, 0, this.canvasWidth, this.canvasHeight - 4);this.ctx.setFillStyle(color)this.ctx.fill() //设置填充this.ctx.draw() //开画},},onShow() {}}
/scriptstyle langscss scoped.canvas_wrapper {position: relative;background: #f8f7fc;border: 2px solid #EBEBEB;border-radius: 4px;margin: 0 auto;}.canvas_wrapper .handWriting {width: 100%;height: 100%;position: relative;z-index: 10;}.canvastips {position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: 1;pointer-events: none;font-family: PingFang SC;font-style: normal;font-weight: 400;font-size: 70rpx;line-height: 180rpx;text-align: center;letter-spacing: 30rpx;color: #E6E6E6;}
/stylevue3使用 由于是两个项目操作也是不一样所以获取图片的逻辑也有点不一样 signatrue refsignatrueRef confirmSignconfirmSign/signatrue代码 templateuni-popup refpopup typebottomview classpage_containerview classcanvas_title请在这里签名/viewview classcanvas_wrapper refcanvas_wrapperscanvas classhandWriting disable-scrolltrue touchstartuploadScaleStarttouchmoveuploadScaleMove touchenduploadScaleEnd canvas-idhandWriting/canvasview classcanvastips flex_center_center请在这里签名/view/viewview classzbutton_wrapper fixed_bottomview classzbutton clickretDraw重新签名/viewview classzbutton black clickgetCavasTempFile完成签名并提交/view/view/view/uni-popup
/templatescript setupimport {ref,onMounted,computed,nextTick} from vuelet popup ref(null)let state ref({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, //顺滑度用60的距离来计算速度currentPoint: {},currentLine: [], // 当前线条firstTouch: true, // 第一次触发radius: 1, //画圆的半径cutArea: {top: 0,right: 0,bottom: 0,left: 0}, //裁剪区域bethelPoint: [], //保存所有线条 生成的贝塞尔点lastPoint: 0,chirography: [], //笔迹currentChirography: {}, //当前笔迹linePrack: [], //划线轨迹 , 生成线条的实际点half: 0 //绘制一半点})let canvasStyle computed(() {return width:${state.value.widht};height:${state.value.height}})onMounted(() {// console.log(popup)})const init () {console.log(1111111111)popup.value.open(bottom);nextTick(() {containerEnter()})}const containerEnter () {let canvasName state.value.canvasNamelet ctx uni.createCanvasContext(canvasName, this)state.value.ctx ctx;var query uni.createSelectorQuery().in(this);query.select(.canvas_wrapper).boundingClientRect(rect {state.value.canvasWidth rect.width;state.value.canvasHeight rect.height;/* 将canvas背景设置为 白底不设置 导出的canvas的背景为透明 */setCanvasBg(rgba(0,0,0,0));}).exec();}const containerAfter () {retDraw()}// 获取临时文件const getCavasTempFile (fn) {// if (state.value.linePrack.length 0 || state.value.linePrack[0].length 2) {// return state.value.$Tips({// title: 请签名// })// }uni.canvasToTempFilePath({destWidth: 200,destHeight: 200,canvasId: handWriting,success: (res) {//签名成功回调emits(confirmSign, res.tempFilePath)containerAfter()popup.value.close();},fail: (err) {console.log(图片临时文件生成失败, err);}}, this)}// 笔迹开始const uploadScaleStart (e) {if (e.type ! touchstart) return false;console.log(开始了);state.value.ctx.setFillStyle(state.value.lineColor); // 初始线条设置颜色state.value.ctx.setGlobalAlpha(state.value.transparent); // 设置半透明let currentPoint {x: e.touches[0].x,y: e.touches[0].y}let currentLine state.value.currentLine;currentLine.unshift({time: new Date().getTime(),dis: 0,x: currentPoint.x,y: currentPoint.y})state.value.currentPoint currentPointif (state.value.firstTouch) {state.value.currentPoint {top: currentPoint.y,right: currentPoint.x,bottom: currentPoint.y,left: currentPoint.x}state.value.firstTouch false;}pointToLine(currentLine);}// 笔迹移动const uploadScaleMove (e) {state.value.half;if ((state.value.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 state.value.cutArea.top) {state.value.cutArea.top point.y;}if (point.y 0) state.value.cutArea.top 0;if (point.x state.value.cutArea.right) {state.value.cutArea.right point.x;}if (state.value.canvasWidth - point.x 0) {state.value.cutArea.right state.value.canvasWidth;}if (point.y state.value.cutArea.bottom) {state.value.cutArea.bottom point.y;}if (state.value.canvasHeight - point.y 0) {state.value.cutArea.bottom state.value.canvasHeight;}if (point.x state.value.cutArea.left) {state.value.cutArea.left point.x;}if (point.x 0) state.value.cutArea.left 0;state.value.lastPoint state.value.currentPointstate.value.currentPoint pointlet currentLine state.value.currentLinecurrentLine.unshift({time: new Date().getTime(),dis: distance(state.value.currentPoint, state.value.lastPoint),x: point.x,y: point.y})pointToLine(currentLine);}// 笔迹结束const uploadScaleEnd (e) {console.log(结束了);if (e.type ! touchend) return 0;let point {x: e.changedTouches[0].x,y: e.changedTouches[0].y}state.value.lastPoint state.value.currentPoint;state.value.currentPoint point;let currentLine state.value.currentLinecurrentLine.unshift({time: new Date().getTime(),dis: distance(state.value.currentPoint, state.value.lastPoint),x: point.x,y: point.y})if (currentLine.length 2) {var info (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;//$(#info).text(info.toFixed(2));}//一笔结束保存笔迹的坐标点清空当前笔迹//增加判断是否在手写区域pointToLine(currentLine);var currentChirography {lineSize: state.value.lineSize,lineColor: state.value.lineColor};var chirography state.value.chirographychirography.unshift(currentChirography);state.value.chirography chirographyvar linePrack state.value.linePracklinePrack.unshift(state.value.currentLine);state.value.half 0;state.value.linePrack linePrack;state.value.currentLine [];}const retDraw () {state.value.ctx.clearRect(0, 0, state.value.canvasWidth, state.value.canvasHeight)state.value.ctx.draw();//设置canvas背景setCanvasBg(rgba(0,0,0,0));}//画两点之间的线条参数为:line会绘制最近的开始的两个点const pointToLine (line) {calcBethelLine(line);return;}//计算插值的方式const calcBethelLine (line) {if (line.length 1) {line[0].r state.value.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].xy0 line[1].yx2 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;}//从计算公式看三个点分别是(x0,y0),(x1,y1),(x2,y2) (x1,y1)这个是控制点控制点不会落在曲线上实际上这个点还会手写获取的实际点却落在曲线上len distance({x: x2,y: y2}, {x: x0,y: y0});lastRadius state.value.radius;for (let n 0; n line.length - 1; n) {dis line[n].dis;time line[n].time - line[n 1].time;if (dis state.value.smoothness) break;}state.value.radius Math.min(time / len * state.value.pressure state.value.lineMin, state.value.lineMax) *state.value.lineSizeline[0].r state.value.radius;//计算笔迹半径if (line.length 2) {r0 (lastRadius state.value.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;}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 (state.value.radius - lastRadius) / n * i;point.push({x: x,y: y,r: r});if (point.length 3) {let a 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 state.value.lineColor;bethelDraw(a, 1);point [{x: x,y: y,r: r}];}}state.value.currentLine line}//求两点之间距离const distance (a, b) {let x b.x - a.x;let y b.y - a.y;return Math.sqrt(x * x y * y);}const 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;}const bethelDraw (point, is_fill, color) {let ctx state.value.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)}const selectColorEvent (event) {var color event.currentTarget.dataset.colorValue;var colorSelected event.currentTarget.dataset.color;state.value.selectColor colorSelected;state.value.lineColor color;}const setCanvasBg (color) {state.value.ctx.rect(0, 0, state.value.canvasWidth, state.value.canvasHeight - 4);// ctx.setFillStyle(red)state.value.ctx.setFillStyle(color)state.value.ctx.fill() //设置填充state.value.ctx.draw() //开画}const emits defineEmits([confirmSign])defineExpose({init})
/scriptstyle langscss scoped.page_container {height: calc(702rpx 140rpx 106rpx env(safe-area-inset-bottom));background: #fff;}.canvas_wrapper {position: relative;width: 702rpx;height: 702rpx;background: #F6F6F6;border: 2px solid #EBEBEB;border-radius: 4px;margin: 0 auto;}.canvas_wrapper .handWriting {width: 100%;height: 100%;position: relative;z-index: 10;}.canvastips {position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: 1;pointer-events: none;font-family: PingFang SC;font-style: normal;font-weight: 400;font-size: 70rpx;line-height: 180rpx;text-align: center;letter-spacing: 30rpx;color: #E6E6E6;/* transform: rotate(90deg); */}.canvas_title {height: 120rpx;padding: 0 32rpx;font-family: PingFang SC;font-style: normal;font-weight: 500;font-size: 36rpx;line-height: 120rpx;mix-blend-mode: normal;opacity: 0.9;}
/style 文章转载自: http://www.morning.ypcd.cn.gov.cn.ypcd.cn http://www.morning.rdlfk.cn.gov.cn.rdlfk.cn http://www.morning.xjkfb.cn.gov.cn.xjkfb.cn http://www.morning.nkbfc.cn.gov.cn.nkbfc.cn http://www.morning.ptslx.cn.gov.cn.ptslx.cn http://www.morning.cmzgt.cn.gov.cn.cmzgt.cn http://www.morning.mntxalcb.com.gov.cn.mntxalcb.com http://www.morning.rfzzw.com.gov.cn.rfzzw.com http://www.morning.nmbbt.cn.gov.cn.nmbbt.cn http://www.morning.ymqfx.cn.gov.cn.ymqfx.cn http://www.morning.xflwq.cn.gov.cn.xflwq.cn http://www.morning.yzxhk.cn.gov.cn.yzxhk.cn http://www.morning.htbsk.cn.gov.cn.htbsk.cn http://www.morning.ymwrs.cn.gov.cn.ymwrs.cn http://www.morning.mmhyx.cn.gov.cn.mmhyx.cn http://www.morning.lchtb.cn.gov.cn.lchtb.cn http://www.morning.lsnbx.cn.gov.cn.lsnbx.cn http://www.morning.dmzfz.cn.gov.cn.dmzfz.cn http://www.morning.csgwd.cn.gov.cn.csgwd.cn http://www.morning.zxfdq.cn.gov.cn.zxfdq.cn http://www.morning.tjpmf.cn.gov.cn.tjpmf.cn http://www.morning.rjrz.cn.gov.cn.rjrz.cn http://www.morning.lnbcg.cn.gov.cn.lnbcg.cn http://www.morning.skdhm.cn.gov.cn.skdhm.cn http://www.morning.4q9h.cn.gov.cn.4q9h.cn http://www.morning.nbybb.cn.gov.cn.nbybb.cn http://www.morning.kjkml.cn.gov.cn.kjkml.cn http://www.morning.qfrmy.cn.gov.cn.qfrmy.cn http://www.morning.skcmt.cn.gov.cn.skcmt.cn http://www.morning.hzqjgas.com.gov.cn.hzqjgas.com http://www.morning.bytgy.com.gov.cn.bytgy.com http://www.morning.tgbx.cn.gov.cn.tgbx.cn http://www.morning.xdpjf.cn.gov.cn.xdpjf.cn http://www.morning.rdpps.cn.gov.cn.rdpps.cn http://www.morning.mywmb.cn.gov.cn.mywmb.cn http://www.morning.yhjrc.cn.gov.cn.yhjrc.cn http://www.morning.ffrys.cn.gov.cn.ffrys.cn http://www.morning.bnpcq.cn.gov.cn.bnpcq.cn http://www.morning.lsssx.cn.gov.cn.lsssx.cn http://www.morning.sbncr.cn.gov.cn.sbncr.cn http://www.morning.txtzr.cn.gov.cn.txtzr.cn http://www.morning.ngkgy.cn.gov.cn.ngkgy.cn http://www.morning.rntby.cn.gov.cn.rntby.cn http://www.morning.wwxg.cn.gov.cn.wwxg.cn http://www.morning.mngh.cn.gov.cn.mngh.cn http://www.morning.lprfk.cn.gov.cn.lprfk.cn http://www.morning.qgjxy.cn.gov.cn.qgjxy.cn http://www.morning.lcwhn.cn.gov.cn.lcwhn.cn http://www.morning.ybyln.cn.gov.cn.ybyln.cn http://www.morning.rkdzm.cn.gov.cn.rkdzm.cn http://www.morning.rjcqb.cn.gov.cn.rjcqb.cn http://www.morning.brcdf.cn.gov.cn.brcdf.cn http://www.morning.smdnl.cn.gov.cn.smdnl.cn http://www.morning.hjjkz.cn.gov.cn.hjjkz.cn http://www.morning.srltq.cn.gov.cn.srltq.cn http://www.morning.knrgb.cn.gov.cn.knrgb.cn http://www.morning.lmfxq.cn.gov.cn.lmfxq.cn http://www.morning.fmry.cn.gov.cn.fmry.cn http://www.morning.llxns.cn.gov.cn.llxns.cn http://www.morning.nnjq.cn.gov.cn.nnjq.cn http://www.morning.lbggk.cn.gov.cn.lbggk.cn http://www.morning.hbqhz.cn.gov.cn.hbqhz.cn http://www.morning.xpqsk.cn.gov.cn.xpqsk.cn http://www.morning.hwprz.cn.gov.cn.hwprz.cn http://www.morning.nkjpl.cn.gov.cn.nkjpl.cn http://www.morning.clpfd.cn.gov.cn.clpfd.cn http://www.morning.frmmp.cn.gov.cn.frmmp.cn http://www.morning.zrgx.cn.gov.cn.zrgx.cn http://www.morning.nchlk.cn.gov.cn.nchlk.cn http://www.morning.kfldw.cn.gov.cn.kfldw.cn http://www.morning.hhxpl.cn.gov.cn.hhxpl.cn http://www.morning.gtcym.cn.gov.cn.gtcym.cn http://www.morning.bfycr.cn.gov.cn.bfycr.cn http://www.morning.ygkb.cn.gov.cn.ygkb.cn http://www.morning.gyjld.cn.gov.cn.gyjld.cn http://www.morning.ttvtv.cn.gov.cn.ttvtv.cn http://www.morning.mkyny.cn.gov.cn.mkyny.cn http://www.morning.mltsc.cn.gov.cn.mltsc.cn http://www.morning.plxhq.cn.gov.cn.plxhq.cn http://www.morning.drtgt.cn.gov.cn.drtgt.cn