h5实现浏览pdf文件并签名上传
html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="format-detection" content="telephone=no" /> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <title>合同签名</title> <link rel="stylesheet" href="css/style.css" /> <link rel="stylesheet" href="css/pdfh5.css" /> <link href="https://www.gjtool.cn/download/pdfh5.png" type="image/x-icon" rel="shortcut icon" /> <meta charset="utf-8"> <style> body, html { width: 100%; margin: 0; padding: 0; height: 100%; } #demo { display: none; height: 70%; } #canvas { border: 0.01rem solid #f30; } #canvas-btn { display: flex; align-items: center; justify-content: center; margin: 0; /*padding: 0.13rem;*/ } #clear_btn { width: 30%; background: #ca4341; margin: auto; text-align: center; line-height: 1rem; margin-top: 0.27rem; color: #fff; border-radius: 1.31rem; clear: both; } #save_btn { width: 30%; background: #4cd964; margin: auto; text-align: center; line-height: 1rem; margin-top: 0.27rem; color: #fff; border-radius: 1.31rem; clear: both; } #showToastWraper { position: fixed; z-index: 999; top: 35%; right: 0; left: 0; width: 90%; margin: auto; background: rgba(0, 0, 0, 0.6); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7f000000, endColorstr=#7f000000); text-align: center; padding: 10px 20px; color: #dcdcdc; border-radius: 50px; } </style> </head> <body> <!-- <iframe src="./pdf/web/viewer.html?file='http://124.133.28.25:8082/common/download?fileName=%E5%AB%A6%E5%A8%A5%E5%A7%90%E5%A7%90%E9%A3%8E%E6%B9%BF%E5%85%8D%E7%96%AB%E7%A7%91%E7%96%BE%E7%97%85%E4%B8%B4%E5%BA%8A%E8%AF%8A%E7%96%97%E6%96%B9%E6%A1%88%E6%B5%8E%E5%8D%97%E8%8E%B1%E5%8D%8E%E5%88%86%E5%85%AC%E5%8F%B850613758.pdf&delete=true'" style='width:100%;height:100%'></iframe> --> <div id="app"> <div class="text-wrapper"> <div class="text part1"> <div> <span class="letter"> <div class="character">L</div> <span></span> </span> <span class="letter"> <div class="character">o</div> <span></span> </span> <span class="letter"> <div class="character">a</div> <span></span> </span> <span class="letter"> <div class="character">d</div> <span></span> </span> <span class="letter"> <div class="character">i</div> <span></span> </span> <span class="letter"> <div class="character">n</div> <span></span> </span> <span class="letter"> <div class="character">g</div> <span></span> </span> </div> </div> <div class="how-to"><span>正在加载中,请您耐心等待...</span></div> </div> </div> <div id="demo"></div> <canvas id='canvas'></canvas> <div id="canvas-btn"> <div id="clear_btn" class="op_btn">重新签名</div> <div id="save_btn" class="save_btn">提交签名</div> <div class="cleaerfix"></div> </div> <!-- pdf的js --> <script src="js/pdf.js"></script> <script src="js/pdf.worker.js"></script> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script src="js/pdfh5.js" type="text/javascript" charset="utf-8"></script> <!-- 签名的js --> <script type="text/javascript" src="js/flexible.debug.js"></script> <script type="text/javascript" src="js/zepto.js"></script> <script type="text/javascript" src="js/touch.js"></script> <script type="text/javascript" src="js/flexible.debug.js"></script> <script type="text/javascript" src="js/flexible_css.debug.js"></script> <script type="text/javascript"> var pdfh5; $(function () { $("#app").remove() $("#demo").show() var query = window.location.search.substring(1); var url = query.split("=")[1]; //从路由地址获取pdf线上地址 console.log('url??',url) pdfh5 = new Pdfh5('#demo', {
pdfurl: './git.pdf', //本地预览地址 // pdfurl: url, //pdf文件线上地址 // ,URIenable:true //开启浏览器地址栏file参数获取 }); //pdf准备开始渲染,此时可以拿到pdf总页数 pdfh5.on("ready", function () { console.log("pdf准备开始渲染,总页数:" + this.totalNum) }) //监听pdf渲染成功 pdfh5.on("success", function (time) { time = time / 1000 console.log("pdf渲染完成,总耗时" + time + "秒") }) }) </script> <script> var isSign = false var haveSign = false //获取页面尺寸 var canvasWidth = document.body.clientWidth; var canvasHeight = canvasWidth; //声明canvas var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); //设置canvas尺寸 canvas.width = canvasWidth * 0.98; canvas.height = canvasHeight * 0.45; //画笔颜色 var strokeColor = "#000"; //鼠标 isMouseDown = false; //上一次绘制的的坐标 var lastLoc = { x: 0, y: 0 }; //初始记录事件 var lastTimestamp = 0; //上一次线条宽度 var lastLineWidth = -1; //var var maxV = 10; var minV = 0.1; var maxLineWidth = 5; var minLineWidth = 1; //点击色块切换画笔颜色 $(".colorBtn").on("click", function (e) { $(".colorBtn").removeClass('colorBtnBorder'); $(this).addClass("colorBtnBorder"); strokeColor = $(this).css(""); }) //清除 $('#clear_btn').on('click', function (e) { context.clearRect(0, 0, canvasWidth, canvasHeight); isSign = false }); function submitImg (orderId,imgData) { $.ajax({ url: "http://域名或ip地址/oa/order/qiangmingSaving", //图片提交地址 type: "post", data: { orderId: orderId, qianming: imgData.substring(22) }, success: function (res) { console.log(res) if (res.code==200) { haveSign = true showToast('提交签名成功'); } else { showToast('提交签名失败'); } } }); } // 弹窗提示 function showToast(text, width, radius) { var widthDiv = width ? width : '50%';//自定义宽度 var radiusDiv = radius ? radius : '50px';//自定义边框角度 //此处你还可以定义 位置、文字颜色大小、背景色、显示时长等等 var showToastDiv = "<div id='showToastWraper'></div>"; var showToastWraper = $("#showToastWraper"); var isExat = showToastWraper.length; if (!isExat) { //第一次创建元素 并且设置元素把显示状态的停止掉、渐隐显示、显示文本内容、设置自定义样式、1.5s后渐隐消失 $(document.body).append(showToastDiv); $("#showToastWraper").stop().fadeIn(300).html(text).css({ width: widthDiv, borderRadius: radiusDiv }).delay(1500).fadeOut(500); } else { //第二次 就不需要创建元素了减少dom操作 showToastWraper.stop().fadeIn(300).html(text).css({ width: widthDiv, borderRadius: radiusDiv }).delay(1500).fadeOut(500); } } //保存画图 $('#save_btn').on('click', function (e) { if (isSign) { if (!haveSign) { var image = canvasToImage(canvas); var query = window.location.search.substring(1); var orderId = query.split("/").pop().split('.')[0]; console.log('id??',orderId) submitImg(orderId,image) } else { showToast('请勿重复提交签名') } } else { showToast('请签名') } }); // 将canvas转换成画布 function canvasToImage(canvas) { // var image = new Image(); // image.src = canvas.toDataURL("image/png"); // return image; return canvas.toDataURL("image/png"); } //获取canvas 坐标 x,y 分别代表相对window内的xy function windowToCanvas(x, y) { //canvas提供的方法返回canvas 距 他外围包围盒子的距离left,top值 var bbox = canvas.getBoundingClientRect(); //返回的就是canvas 内的坐标值 return { x: Math.round(x - bbox.left), y: Math.round(y - bbox.top) } } //封装 事件 function beginStroke(point) { isMouseDown = true; //第一次用户画的坐标初始值 lastLoc = windowToCanvas(point.x, point.y); //获取首次点击鼠标 事件戳 lastTimestamp = new Date().getTime(); } function endStroke() { isMouseDown = false; } function moveStroke(point) { //开始绘制直线 var curLoc = windowToCanvas(point.x, point.y); //路程 var s = calcDistance(curLoc, lastLoc); //结束时间 var curTimestamp = new Date().getTime(); //时间差 var t = curTimestamp - lastTimestamp; //绘制线条粗细 var lineWidth = calcLineWidth(t, s); //绘制 context.beginPath(); context.moveTo(lastLoc.x, lastLoc.y); context.lineTo(curLoc.x, curLoc.y); context.strokeStyle = strokeColor; context.lineWidth = lineWidth; context.lineCap = "round"; context.lineJoin = "round"; context.stroke(); //给lastLoc赋值维护 lastLoc = curLoc; //时间更新 lastTimestamp = curTimestamp; lastLineWidth = lineWidth; } //pc鼠标事件 canvas.onmousedown = function (e) { e.preventDefault(); beginStroke({ x: e.clientX, y: e.clientY }); } canvas.onmouseup = function (e) { e.preventDefault(); endStroke(); } canvas.onmouseout = function (e) { e.preventDefault(); endStroke(); isSign = true } canvas.onmousemove = function (e) { e.preventDefault(); if (isMouseDown) { moveStroke({ x: e.clientX, y: e.clientY }); } } //移动端 canvas.addEventListener("touchstart", function (e) { e.preventDefault(); touch = e.touches[0]; //限制一根手指触碰屏幕 beginStroke({ x: touch.pageX, y: touch.pageY }); }); canvas.addEventListener("touchend", function (e) { e.preventDefault(); endStroke(); isSign = true }); canvas.addEventListener("touchmove", function (e) { e.preventDefault(); if (isMouseDown) { touch = e.touches[0]; moveStroke({ x: touch.pageX, y: touch.pageY }); } }); //速度 = 路程 / 时间 用来计算书写速度来改变线条粗细 function calcDistance(loc1, loc2) { //返回 数的平方根 return Math.sqrt((loc1.x - loc2.x) * (loc1.x - loc2.x) + (loc1.y - loc2.y) * (loc1.y - loc2.y)); } //线条宽度 function calcLineWidth(t, s) { var v = s / t; var resultLineWidth; if (v <= minV) { resultLineWidth = maxLineWidth; } else if (v >= maxV) { resultLineWidth = minLineWidth; } else { resultLineWidth = maxLineWidth - (v - minV) / (maxV - minV) * (maxLineWidth - minLineWidth); } if (lastLineWidth == -1) { return resultLineWidth; } else { return lastLineWidth * 2 / 3 + resultLineWidth * 1 / 3; } } </script> </body> </html>
本地查看会提示跨域,需上传到服务器测试
完整项目文件放在百度网盘,自行下载即可,这里只是做个记录
链接: https://pan.baidu.com/s/1PZIr8Whc8dhRjeNQOHNZcw 提取码: abya
参考pdf预览博客:https://www.gjtool.cn/archives/pdfh5
参考签名博客:https://www.jianshu.com/p/53335cdd3892