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 ...
随机推荐
- C# Task用法
1.Task的优势 ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便.比如: ◆ ThreadPool不支持线程的取消.完成.失败通知等交互性 ...
- 所有人都可以是开发人员——《Office 365开发入门指南》视频教程即将上市
今天是春节假期的最后一天,在这里给全国的朋友们拜个晚年,祝大家身体健康,晚年幸福啊.这个春节大家过的怎么样啊,我自己是在老家过的年,家乡的年味还是比较浓的,也再次感谢朋友圈的大家给我看了各地的风光 ...
- Wpf学习20180605
Windows Presentation Foundation 窗口展示框架 WPF. 与winform界面程序比较,我认为最大的区别是‘与分辨率无关’这个特性. 传统winform程序在低分辨率的电 ...
- 模块热替换 HMR
devserver:{hot:true},既及时更新代码,样式(需配合loader)变化,自动重编译,只适用于开发环境. 入口文件中,添加监视: + if (module.hot) {+ module ...
- spring_06装配bean_2
一.前言 1.自动装配尽量不要用,不如使用set明确 二. 通过构造函数注入值(Bean中可以没有get,set方法) <bean id="emp" class=" ...
- (7)Microsoft office Word 2013版本操作入门_常用技巧
1.自定义快速功能栏调整:常用功能按钮可以设置显示到此处.(如图所示的另存为和插入批注功能) 2.word中截图功能: 2.1 截图插入后的图片,可以进行设置 选中图片---点击[格式]可以设置图片 ...
- 浅谈spring中AOP以及spring中AOP的注解方式
AOP(Aspect Oriented Programming):AOP的专业术语是"面向切面编程" 什么是面向切面编程,我的理解就是:在不修改源代码的情况下增强功能.好了,下面在 ...
- Reactor模式理解
Reactor模式 也可以叫反应器模式或者应答者模式 reactor模式简介 让我们先了解一下阻塞I/O与非阻塞I/O I/O 是非常缓慢的 I/O绝对是计算机操作中最慢的.访问RAM的事件为ns级别 ...
- vue单页应用添加百度统计
前言 申请百度统计后,会得到一段JS代码,需要插入到每个网页中去,在Vue.js项目首先想到的可能就是,把统计代码插入到index.html入口文件中,这样就全局插入,每个页面就都有了;这样做就涉及到 ...
- springboot 数据验证
不能相信前端传过来的任何数据 一定不能相信前端传过来的任何数据 绝对不能相信前端传过来的任何数据 @JsonFormat 时间必须是指定的格式(这里是接收参数格式,不是取数据来格式化) @Null 必 ...