js开发打印证书功能
最近突然被加了要打印证书的功能的需求。其实打印功能很简单,直接调用window.print()就可以打印,只是这是最基本的打印,会打印当前页面的所有元素,而我们要的是局部打印,实现方法:
1.设置好开头与结尾,然后进行识别和打印(前边有介绍),见:https://www.cnblogs.com/ljwsyt/p/9511546.html;
2.使用jqPrint进行打印。jqPrint是对window的打印进行了一些简单便捷的封装,其源代码很少。
地址:https://github.com/MRlijiawei/enroll/blob/master/enroll-webapp/src/main/resources/static/plugins/print/jquery.jqprint-0.3.js
项目要求写一个公共插件,在任何系统都可以使用。但是局限性太大,而且和应用场景有很大关联。如果是做一个拖拽组件,那就只能管理员的角色进行一一拖拽,比较费时;最终暂时写了一个用户自助打印的组件。
思路是使用绝对布局把文字定位到证书图片上相应的位置,然后打印。
html代码:
<div>
<div id="printArea">
<!--startprint942,631-->
<div id="toPrint">
</div>
<!--endprint-->
</div>
<div style="display:none">
<button onclick="printNotifier()">打印</button>
</div>
</div>
有效区域只有一个空的div
css代码:
#toPrint {
position:absolute;
/* background:url('/res/img/notifications.png'); */
left: 50%;
top: 50%;
}
#toPrint div {
position:absolute;
}
#toPrint img {
position:absolute;
}
可以看到只是设置了一个居中和绝对布局。其余样式在js中动态控制,因为做了自适应和公共化。
js代码:
myApp.controller('notifierController', function ($rootScope, $scope, services, $sce, $stateParams, $state) {
$scope.services = services;
//查询录取通知书内容
services["getApplyStatus"] = function (param) {
return $rootScope.serverAction('/apply/queryDegreeApplyInfo', param, "GET");
};
//模板
$scope.printObj = {
notifierObj:{
"url": "/res/img/notifications.png",
"height": "631",
"width": "942"
},
paramList:[{
"objName":"黄大明",
"left":"133",
"top":"189",
"size": "28"
},{
"objName":"SXXX小学",
"left":"460",
"top":"270",
"size": "28"
},{
"objName":"2018",
"left":"195",
"top":"314",
"size": "28"
},{
"objName":"8",
"left":"325",
"top":"314",
"size": "28"
},{
"objName":"31",
"left":"405",
"top":"314",
"size": "28"
}]
}
services.getApplyStatus('token').success(function(res) {
if ('OK' == res.result) {
if(res.msg) {
$scope.printObj.paramList[0].objName = res.msg.studentName;
$scope.printObj.paramList[1].objName = res.msg.applySchoolName;
//屏幕自适应
suitScreen($scope);
//组装页面
assembleHtml($scope);
//打印
printNotifier();
}
} else {
layer.alert(res.msg);
}
});
//拖动
/*$(document).on("mousedown","#toPrint",function(e){
//webkit内核和火狐禁止文字被选中
$('body').addClass('select')
//ie浏览器禁止文字选中
document.body.onselectstart=document.body.ondrag=function(){
return false;
}
$scope.moveBegin = true;
$scope.mouseStartPoint = {"left":e.pageX,"top": e.pageY};
});
$(document).on("mouseup",function(e){
$scope.moveBegin = false;
});
$(document).on("mousemove",function(e){
if(!$scope.moveBegin) {
return;
}
$("#toPrint").css("margin-left", e.pageX - $scope.mouseStartPoint.left - 454 + "px");
$("#toPrint").css("margin-top", e.pageY - $scope.mouseStartPoint.top - 315 + "px");
});*/
});
function printNotifier() {
try{
print.portrait = false;//横向打印
}catch(e){
//alert("不支持此方法");
}
var HKEY_RootPath="HKEY_CURRENT_USER\\Software\\Microsoft\\Internet Explorer\\PageSetup\\";
/*try{
var WSc=new ActiveXObject("WScript.Shell");
HKEY_Key="header";
WSc.RegWrite(HKEY_RootPath+HKEY_Key,"");
HKEY_Key="footer";
WSc.RegWrite(HKEY_RootPath+HKEY_Key,"");
}catch(e){
}*/
$("#printArea").jqprint();
}
function suitScreen($scope) {
var effectiveHeight = findParam("#toPrint", "height");
var effectiveWidth = findParam("#toPrint","width");
if($scope.printObj.notifierObj.width/effectiveWidth > $scope.printObj.notifierObj.height/effectiveHeight) {
//取最接近的一个属性进行自适应,并适当调小一些
var suitTimes = $scope.printObj.notifierObj.width/effectiveWidth*1.2;
} else {
var suitTimes = $scope.printObj.notifierObj.height/effectiveHeight*1.2;
}
$scope.printObj.notifierObj.width = $scope.printObj.notifierObj.width/suitTimes;
$scope.printObj.notifierObj.height = $scope.printObj.notifierObj.height/suitTimes;
for(i=0;i<$scope.printObj.paramList.length;i++) {
$scope.printObj.paramList[i].size = $scope.printObj.paramList[i].size/suitTimes;
$scope.printObj.paramList[i].left = $scope.printObj.paramList[i].left/suitTimes;
$scope.printObj.paramList[i].top = $scope.printObj.paramList[i].top/suitTimes;
}
}
function assembleHtml($scope) {
var htmlStr = "<img src='" + $scope.printObj.notifierObj.url+"' style='width:"+$scope.printObj.notifierObj.width+"px;height:"+
$scope.printObj.notifierObj.height+"px'>";
for(i=0;i<$scope.printObj.paramList.length;i++) {
var nowObj = $scope.printObj.paramList[i];
htmlStr += "<div style='font-size:"+nowObj.size+"px;top:"+nowObj.top+"px;left:"+nowObj.left+"px'>"+nowObj.objName+"</div>";
}
$("#toPrint").css("margin-left", (0-$scope.printObj.notifierObj.width)/2+"px");
$("#toPrint").css("margin-top", (0-$scope.printObj.notifierObj.height)/2+"px");
$("#toPrint").css("height", $scope.printObj.notifierObj.height+"px");
$("#toPrint").css("width", $scope.printObj.notifierObj.width+"px");
$("#toPrint").append(htmlStr);
}
//获取有效区域
function findParam(targetObj, attribute) {
//取数字
if($(targetObj).css(attribute) && $(targetObj).css(attribute).replace(/[^0-9]/ig,"") != '0') {
return $(targetObj).css(attribute).replace(/[^0-9]/ig,"");
} else {
//递归
return findParam($(targetObj).parent(), attribute);
}
}
angular1的框架。
其中有几个关键思路:
(1)模板结构定义,及根据参数长度动态生成页面。
(2)屏幕自适应,选取比较接近的(宽或高),然后计算倍数,并做了1.2倍的缩小,使其不至于都挨着页面边界不美观。取有效宽度时,从需要打印的元素往上层parent一层层递归取,直到取到有效的宽和高。递归时,由于已开始没有return,导致一直取不到最终值
return findParam($(targetObj).parent(), attribute);
(3)拖动实现,已注掉的那段mouse事件,思路是点击目标元素时开始计算坐标,放开时停止,中间移动的动作根据坐标偏移量来调整目标的left和top。有个小瑕疵就是有时候放开之后再点击就回到页面中间去了,由于后来做了页面大小的自适应就没有管了。
(4)打印的时候一些设置。由于是自动打印,不能要求用户手动我改设置,主要是两个,一个是基本上证书都是横向,所有打印要改成默认横向,然后去掉页眉页脚,实现的代码是
try{
print.portrait = false;//横向打印
}catch(e){
//alert("不支持此方法");
}
下边注释掉的网上说的是去掉页眉页脚用的,但是实测加上之后反而去不掉了。
开发完成之后,基本功能也都OK了,然后就是考虑兼容性的问题了。自适应解决了很大程度上的兼容性问题,但是对于浏览器的兼容性和移动端的兼容性还需要再进行测试。
经测试,在移动端的时候,如果屏幕分辨率较小,那么就会出现子题比较小的情况。而谷歌对于小于12px的字体,大小始终固定在12不会再变小,这就出现了兼容性问题。
解决思路是按比例缩放,使用属性是-webkit-transform。而缩放默认是以中心为原点进行缩放,而我们画图填充是以左上角为原点的,所有缩放的同时还必须使用transform-origin:0 0设置以左上角为基准进行缩放。
最后就是,如果大于12px而又进行了缩放,那么就会变得更大,所有我们给这两个样式设置一个条件,那就是以12px作为临界点。
代码如下:
function assembleHtml($scope) {
var htmlStr = "<img src='" + $scope.printObj.notifierObj.url+"' style='width:"+$scope.printObj.notifierObj.width+"px;height:"+
$scope.printObj.notifierObj.height+"px'>";
for(i=0;i<$scope.printObj.paramList.length;i++) {
var nowObj = $scope.printObj.paramList[i];
if(nowObj.size < 12) {
htmlStr += "<div style='font-size:"+nowObj.size+"px;top:"+nowObj.top+"px;left:"+nowObj.left+
//谷歌浏览器字体小于12px时会不再变小,使用-webkit-transform兼容,并设置已左上角作为变换原点
"px;-webkit-transform:scale("+nowObj.size/12+","+nowObj.size/12+");transform-origin:0 0'>"+nowObj.objName+"</div>";
} else {
htmlStr += "<div style='font-size:"+nowObj.size+"px;top:"+nowObj.top+"px;left:"+nowObj.left+
"px'>"+nowObj.objName+"</div>";
}
}
$("#toPrint").css("margin-left", (0-$scope.printObj.notifierObj.width)/2+"px");
$("#toPrint").css("margin-top", (0-$scope.printObj.notifierObj.height)/2+"px");
$("#toPrint").css("height", $scope.printObj.notifierObj.height+"px");
$("#toPrint").css("width", $scope.printObj.notifierObj.width+"px");
$("#toPrint").append(htmlStr);
}
附上效果对比图,更容易理解些

其中“类好啊”是未变换未设置原点的最终效果,“北门小学”是都设置后的效果,下边的日期是设置了缩放但是没有设置原点的效果。
还有一个很关键的步骤就是定义好模板之后获取数据并替换掉模板中的值。原本设计要做一个通用的,但是就要存库,而且一个模板一张图片就要存一次,而且对于值的获取后台也不好处理,所有暂时就直接js中定义模板了。
整个流程很简洁也很实用,希望大家喜欢。感谢大家支持,求关注,求红包奖励金。
js开发打印证书功能的更多相关文章
- js开发打印证书功能(二)
在上一篇的基础上,实现了一下另外一种方式. 上一篇地址:https://www.cnblogs.com/ljwsyt/p/9525290.html 首先,该方式也是有几种方法. 1.在上一篇的基础上, ...
- 网站开发进阶(十二)JS实现打印功能(包括打印预览、打印设置等)
JS实现打印功能(包括打印预览.打印设置等) 绪 最近在进行项目开发时,需要实现后台管理端打印功能,遂在网上一阵搜索,搜到了很多相关的文章.其中绝大部分文章都是使用的Lodop5.0(Web打印和套打 ...
- 浅试WebStorm配置Node.js开发环境
web前端开发IDE一直喜欢用WebStorm,这里简单介绍如何用WebStorm搭建一个Node.js开发环境. 首先,需要在本地安装好node.js,以及npm包管理工具.你也可以吧node.js ...
- Koa与Node.js开发实战(2)——使用Koa中间件获取响应时间(视频演示)
学习架构: 在实战项目中,经常需要记录下服务器的响应时间,也就是从服务器接收到HTTP请求,到最终返回给客户端之间所耗时长.在Koa应用中,利用中间件机制可以很方便的实现这一功能.代码如下所示: 01 ...
- Node.js学习笔记——Node.js开发Web后台服务
一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...
- .NET开发邮件发送功能的全面教程(含邮件组件源码)
今天,给大家分享的是如何在.NET平台中开发“邮件发送”功能.在网上搜的到的各种资料一般都介绍的比较简单,那今天我想比较细的整理介绍下: 1) 邮件基础理论知识 2) ...
- MVC5 网站开发之七 用户功能 3用户资料的修改和删除
这次主要实现管理后台界面用户资料的修改和删除,修改用户资料和角色是经常用到的功能,但删除用户的情况比较少,为了功能的完整性还是坐上了.主要用到两个action "Modify"和& ...
- MVC5 网站开发之八 栏目功能 添加、修改和删除
本次实现栏目的浏览.添加.修改和删除. 栏目一共有三种类型. 常规栏目-可以添加子栏目,也可以添加内容模型.当不选择内容模型时,不能添加内容. 单页栏目-栏目只有一个页面,可以设置视图. 链接栏目-栏 ...
- 移动端报表JS开发示例--获取定位
上次分享了移动端报表JS开发的系统概念,后来我又回去摸索了一些案例.之前接触到的FineReport的APP客户端可以用来打卡签到,就好奇研究了以下,这次就来聊一聊报表移动端开发如何实现定位功能. 1 ...
随机推荐
- git获取远程服务器的指定分支
昨天糗大了...进入新公司,公司服务器上有Online为线上版本,开发版本默认的为Master,本地clone的开发版为master,公司用的git 自动部署(puh后服务器自动更新了代码...这个有 ...
- 【Tomcat】Tomcat的类加载机制
在Tomcat中主要有以下几种类加载器:(图片来自网络) tomcat启动时,会创建几种类加载器: 1 Bootstrap 引导类加载器 加载JVM启动所需的类,以及标准扩展类,位于jre/lib/e ...
- go里面的指针用法
什么是指针 指针是存储一个变量的内存地址的变量. 在上图中,变量 b 的值是 156,存储在地址为 0x1040a124 的内存中.变量 a 存储了变量 b 的地址.现在可以说 a 指向 b. 指针的 ...
- JVM-Ubuntu18.04.1下编译OpenJDK8
近期开始学习JVM,看的是周老师的<深入理解Java虚拟机>,打算先自己编译个JDK来提升对JVM的兴趣.本文分三部分来描述编译OpenJDK的过程,分别是编译前准备工作.构建编译环境.进 ...
- HDU6187(对偶图生成树)
Destroy Walls Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)T ...
- 填一个laravel视图缓存没有及时更新的坑
1.此坑背景 laravel在渲染blade模板后,会将渲染好的结果存到storage/framework/views(默认路径,也可在配置中修改的)中,以便下次使用.但我最近总是发现修改了blade ...
- 29.Odoo产品分析 (四) – 工具板块(2) – 搜索和仪表盘(1)
查看Odoo产品分析系列--目录 "项目管理"是一个用于管理你的项目,且将它们与其他应用关联起来的非常灵活的模块,他允许您的公司管理项目阶段,分配团队,甚至跟踪与项目相关的时间和工 ...
- Python基础知识点
自学记录: 1.字符串 python中单引号和双引号使用完全相同. 使用三引号('''或""")可以指定一个多行字符串. 转义符 '\' 反斜杠可以用来转义,使用r可以让 ...
- Kotlin入门(24)如何自定义视图
Android提供了丰富多彩的视图与控件,已经能够满足大部分的业务需求,然而计划赶不上变化,总是有意料之外的情况需要特殊处理.比如PagerTabStrip无法在布局文件中指定文本大小和文本颜色,只能 ...
- recovery&linux系统升级数据更新分析总结
先说说对升级的理解吧.系统升级是软件更新及BUG修复的主要方式,升级的主要原理就是数据搬移的过程,把我们需要的数据,从某个地方,更新到另外的一个地方.这个过程就叫做升级.一般是当我们系统有了新的功能增 ...