关于web打印,需要对页面内容进行页面样式设置,呈现出分页的样子,同时对于题目中的图片或表格尽量不分到两个页面中,因此实现了一个jquery的web打印插件,当然,这个插件目前只适用于部分情况,仅供借鉴!
/***
*
* 针对页面打印进行调整样式和DOM
* @since 2018年9月18日 09:00:31
****/
(function($){
var methods = {
//初始化
init : function( options ){
var settings = $.extend({},this.print.defaults,options);
//根据目前部分属性,设置对应的其他属性
var sizeObj = settings['sizes'][settings.size];
settings['bodyWidth'] = sizeObj.width;
settings['pageWidth'] = (sizeObj.width - 4 - settings['paddingLeft'] * 2 - settings['contentMargin']*settings['columns']) / settings['columns'];
settings['pageHeight'] = sizeObj.height;
$(this).print('setSettings',settings);
//预处理//创建分页
$(this).print('preInt').print('createPage');
return $(this);
},
//预处理:将页面呈现出对应的样式,去除一些需要过滤的点来
preInt : function(){
var $this = $(this),settings = $this.print('getSettings'),
pageWidth = settings['pageWidth'],
childClass = settings['childClass'],
paddingHeight = settings['paddingTop'] * 2,
pageHeight = settings['pageHeight'],
breakHeight = settings['breakHeight'];
//设置当前容器宽度,让内容根据宽度呈现出对应的高度来
$this.attr('style','width:'+pageWidth+'px;margin:0px auto;')
//去除自带的分页样式
$this.find('[style*="page-break-before"]').each(function(){
$(this).attr('style',$(this).attr('style').replace('page-break-before:always',''))
});
//将容器下第一级优先处理大于一页的内容
$this.children('.'+childClass).each(function(){
var $child = $(this),height = $child.outerHeight(true);//获得高度
if(height+paddingHeight > pageHeight){
var childs = $child.children();
if(childs.length > 1){//有多个子结构,则每个结构全都分开
childs.each(function(){
var $temp = $('<div></div>').addClass(childClass);
$temp.append($(this));
$child.before($temp);
})
$child.remove();
}else{
//如果只有一个标签,则继续查看是否有下级标签
var $c = $(childs[0]);//获得第一个标签
var cc = $c.children();
var dt = $c.offset().top;
if(cc.length > 1){//子标签下含有多个子标签
//每隔300像素一个标签进行换行
var temp = [],count = 1;
cc.each(function(){
var $cc = $(this);
var st = $cc.offset().top;
if( (st - dt)< (count*breakHeight) ){
temp.push($cc);
}else{
count++;
var $temp = $('<div></div>').addClass(childClass);
var $cloneP = $c.clone();
$cloneP.empty();
temp.forEach(function(item){
$cloneP.append(item.clone());
})
$temp.append($cloneP);
$child.before($temp);
temp = [$cc];
}
})
if(temp.length > 0){
var $temp = $('<div></div>').addClass(childClass);
var $cloneP = $c.clone().empty();
temp.forEach(function(item){
$cloneP.append(item);
})
$temp.append($cloneP);
$child.before($temp);
temp = [];
}
$child.remove();//删除
}else{//一个标签都没有,全是字或者就一个标签
//多级还是一个标签的,暂时不考虑,目前没有处理办法。
throw new Error('存在内容超过一页且无法处理的内容,建议在录入的时候简单处理。')
}
}
}
})
return $this;
},
//根据子级内容DOM创建分页容器
createPage : function(){
var $this = $(this),settings = $this.print('getSettings'),
paddingHeight = settings['paddingTop'] * 3,
pageHeight = settings['pageHeight'],
pageWidth = settings['pageWidth'],
useDot = settings['useDot'],
dotId = settings['dotId'],
dotHeight = settings['dotHeight'],
dotWidth = settings['dotWidth'],
dotClass = settings['dotClass'],
pageClass = settings['pageClass'],
contentClass = settings['contentClass'],
columns = settings['columns'],
bodyWidth = settings['bodyWidth'];
var childs = $this.children();
//从上向下计算,达到符合条件后,就把符合条件的放到一个dom中
var pageArr = [],//最终的结果
temp = [],//临时页面
tempHeight = 0,
pyHeight = 0,//偏移距离
nowPageIndex = 1;//当前的页面索引
childs.each(function( index,item ){
var $item = $(item);
//如果是js,则调过
if(item.tagName == 'SCRIPT'){
return true;
}
var allHeight = $item.outerHeight(true);//真实的整体高度
var top = $item.offset().top;//距离顶部距离
var height = $item.height();//除去margin padding的高度(肉眼高度)
//实际top
var rtop = top + pyHeight;
if(rtop + height + paddingHeight > (pageHeight * nowPageIndex) ){
//开始下一页,并计算偏移距离,重置参数
// console.log(nowPageIndex);
pyHeight = ( pageHeight * nowPageIndex + parseInt(($item.css('margin-top') || '0px').replace('px'),10) - top) + 0;
pageArr.push(temp);
temp = [$item];
nowPageIndex++;
}else{
temp.push($item);
}
})
pageArr.push(temp);
//重置DOM
$this.empty();
//重新处理DOM
for(var i=0;i<pageArr.length;i+=columns){
var $page = $('<div></div>');
//如果有dot需求,则增加
if(useDot){
var $dot1 = $('<span></span>').addClass(dotClass).attr('style','left:0px;top:0px;width:'+dotWidth+'px;height:'+dotHeight+'px;').attr('id',dotId);
var $dot2 = $('<span></span>').addClass(dotClass).attr('style','right:0px;top:0px;width:'+dotWidth+'px;height:'+dotHeight+'px;');
var $dot3 = $('<span></span>').addClass(dotClass).attr('style','left:0px;bottom:0px;width:'+dotWidth+'px;height:'+dotHeight+'px;');
$page.append($dot1);
$page.append($dot2);
$page.append($dot3);
}
//添加样式和页码
$page.addClass(pageClass).attr('pageindex',i+1).attr('style','height:'+pageHeight+'px;')
for(var j=0;j<columns;j++){
var $content = $("<div></div>").addClass(contentClass).attr('style','width:'+pageWidth+'px;float:left;')
var item = pageArr[i+j];
if(item){
item.forEach(function(item2){
$content.append(item2);
})
$page.append($content);//添加多个列
}
}
$this.append($page);
}
//还原容器A4/3宽度
$this.attr('style','width:'+bodyWidth+'px;margin:0px auto;');//设置body宽度,先进行计算
return $this;
},
//获得某些选中针对锚点相对距离
getPos : function( checkSelector ){
var $this = $(this),settings = $this.print('getSettings'),
pageClass = settings['pageClass'],
dotId = settings['dotId'];
var result = [];
$this.find(checkSelector).each(function(){
var $check = $(this);
var left = $check.offset().left;
var top = $check.offset().top;
var $dot = $check.parents('.'+pageClass).find('#'+dotId);
var dl = $dot.offset().left;
var dt = $dot.offset().top;
var rsLeft = left - dl;
var rsTop = top - dt;
var rs = {
left : rsLeft,
top : rsTop
}
result.push(rs);
})
return result;
},
//设置settings
setSettings : function(settings){
$(this).data('settings',settings);
},
//获得设置项目
getSettings: function(name) {
if(name){
return $(this).data('settings')[name];
}else{
return $(this).data('settings');
}
}
};
$.fn.print = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method with name ' + method + ' does not exists for jQuery.print');
}
};
//默认的属性
$.fn.print.defaults = {
sizes : {
'a4' : {
width : 1184,
height : 1672
// width:600,
// height : 800
},
'a3' : {
width : 3000,
height : 4000
}
},
size : 'a4',//默认A4大小
columns : 1,
pageClass : 'page',//外层样式--页面
contentClass : '',//page下content的样式
contentMargin : 0,//内容的外边据,多个需要控制距离呈现高度
paddingTop : 30,//页面中顶部空白距离,底部相同
paddingLeft : 30,//页面中左侧空白距离,右侧同样
useDot : true,//是否启用锚点进行标识页面位置
dotClass: 'dot',//dot对应的样式
dotWidth : 30,//默认宽度30px
dotHeight : 30,//默认高度30px
dotId : 'dot',//计算距离的点的ID
childClass : 'timu',//子级的样式,用于包裹、判断,每个子级都要有
breakHeight : 200//如果出现一行超过一页,那么设置多少像素超过则自动换行
}
})(window.jQuery || $);
根据 $.fn.print.defaults
提供的内置参数,可以进行配置。如下:
$('body').print({
size : 'a4',//a3
columns : 2,//一页几列
dotWidth : 30,
dotHeight : 20,
paddingTop : 50,
paddingLeft : 20,
pageClass : 'comba',
contentClass : 'content',
contentMargin : 10
});
在使用的时候,对应的页面样式一定要与设置的宽度相对应,否则呈现的效果可能不太正确。 如果页面中有图片的话,可以稍微延迟下调用时间,让图片都加载出来后处理,最好还是直接指定图片的宽高。
转载请注明出处: https://chrunlee.cn/article/web-print-jquery-plugin.html