Lodop

Lodop

从2015年的时候,就接触过这个软件,那个时候,我只是拿别人做好的,使用。没有想到,我自己也从事这方面的开发呢。一开始我觉得Lodop不好用,指令什么的太复杂了,而且可视化的操作,感觉做得非常差。但是通过自己做出了3个模板后,感觉可视化的软件,其实已经做得很好了。该有的功能,都有了。这就行了。此外,我第一次知道,原来一维码还有如此多得种类。另外,xps文件原来很适合搞打印,能准确的反原出真实的打印效果。自己也是第一次摸索使用,所以,记录了本文。

在尝试过Lodop之后,我也尝试了另外一款软件Hiprint,起初被它网页式的拖拽吸引了,后来发现其不过是个弟弟。(对比有几大问题:1、直接打印时,文字的字体就两种;2、打印时字体居然成虚线了;3、导出pdf,其不过是图片而已,再打印文字还是模糊的。)

有篇文章还不错:https://www.cnblogs.com/moonvan/p/3419280.html

起步

一般需要在html页面中引入Lodop库文件。

<script src="LodopFuncs.js"></script>
<object  id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0> 
       <embed id="LODOP_EM" type="application/x-print-lodop" width=0 height=0></embed>
</object>
var LODOP=getLodop(document.getElementById('LODOP_OB'),document.getElementById('LODOP_EM'));

推荐:

动态构建

var LODOP=getLodop();

云打印

核心有以下两点,更改为安装C-LODOP的打印机的IP,端口8000不要变。第二、获取CLodop。

<script src="http://10.20.24.65:8000/CLodopFuncs.js"></script>
LODOP = getCLodop();

其实我还是分不清CLodop跟那两个插件的区别是啥?反正只需要安装CLodop好像就可以了。

可视化设计

功能说明

第三个样例,找到空白设计,打开之后,大概弹出一个设计框。如下:

1601177342556

对于功能,如下:

  • 1、进行微调位置,对应快捷键 ctrl+ 方向箭。

  • 2、调整文字大小。

  • 3、旋角。比如文字旋转方向。好像在预览模式下才能看见。

  • 4、调整大小,比如纸张、文本框,根据选择的不同,设置内容不同。

  • 5、文字加粗、倾斜、下划线等。必须是文字才能设置,其他都是置灰。

  • 6、文本框的对齐方式。

  • 7、矩形、边框线等。

  • 8、多选模式下,进行对齐等。ctrl、shift可以多选。

  • 9、背景图片等。这个也非常重要。可以把设计稿放在下面,进行拖动设计。

  • 10、插入对象。尤其是插入文本框,这个很重要。

  • 11、文本框。

  • 12、生成LODOP代码,隐藏有点深。

  • 13、标尺,暂时不知道怎么用。

  • 14、打印预览,有些效果只能在预览情况下,看得出来。

  • 15、文本框,重要说明:拖动文本框的感觉,好像是选择文本一样,反而,选择边框拖动,非常费劲,然后加上微调,非常方便调整整体位置。

  • 16、这个三角,用来显示、隐藏对象列表,尤其页面元素比较多,在列表上选择非常方便。(有时候,左侧利用shift、ctrl多选之后,然后还需要点右侧内容区域,才能删除、或调整位置。也有可能不需要。)

  • 17、对象属性,显示当前的值。

操作策略

下面描述我自己摸索出来的设计模式:

  • 1、加载背景图片

加载的图片最好是使用扫描出来的。(我用的好像是别人截图的)。然后截取图片中主要的内容区域,设置背景图片的大小。选择套打模式。这种图片,能反映出最终的尺寸,所以相当于在上面描。

  • 2、打开对象列表

主要是用来参考,或者快速选择对应的对象。

  • 3、快速生成大量的文本框,并大致拖到对应位置。

这一步可以使用ctrl+拖拽,也可以简单的从菜单项中选择。快速将对应的标签、内容填上。等待微调。

  • 4、感觉差不多了,保存代码。然后再该代码基础上,再进行调整。

先导出代码保存,防止丢失。在代码中设置通用的字体大小和基础样式。然后像图片修图一样,进行精修模式。由于有基础样式,避免了大量调整文字等工作。这一步,需要一块一块的精确的调整,然后预览。这一步中,可以多选进行调整尺寸、字体等。也可以快速的进行对齐,如左边对齐、右边对齐等。

  • 5、预览效果

这一步,在设计中,选择打印预览,然后设置,在设置中选择默认的打印机为xps虚拟打印机。这是神器,基本上跟真实的打印差不多,但是能节省不少纸张。

  • 6、微调

使用拖拽快速调整大的效果,使用ctrl快速的选择多个组件,可以快速的设置统一的大小、尺寸等。使用ctrl+方向箭头可以进行微调,然后预览。此外,像直线等,可以先大致拖动更改大小,然后拖到合适的位置上,然后再利用菜单栏上的输入框或者输入框右侧上下箭头,快速调整尺寸等。

  • 7、添加边线等。

    打印的时候,应该先打印线,但是我喜欢设计的时候,把线放到最后一步。

  • 8、保存最终的代码。

将最终的代码保存起来,然后可以进行进一步处理。

总结:

利用可视化设计能非常方便的设计出打印的样式。直接用html来生成打印的样式,也尝试过,自己手动写样式,写html、table等,达到相同的效果,没有可视化来得快,而且用html打印,不能精确控制打印效果。

预览效果

预览基本上等于真实的打印效果。但是,预览速度很快,然后再回到微调设计。

为什么需要预览,有很多的属性,虽然设置了,在设计模式下,其实,并看不出来效果,只有预览,才能看出真实的效果。如下面的文本属性,好多效果都只能预览后,才能看出来:

1603163214719

预览神器:在设置中选择默认的打印机为xps虚拟打印机。基本上跟真实的打印差不多,但是能节省不少纸张。还方便。2秒就能看出效果。windows没有的,可以自行搜索安装。

预览方法:记得要放大预览,这样,很容易发现不协调部分。

1603163428453

分块策略

一个典型的布局如下:

1603161754961

对应的代码:

LODOP.ADD_PRINT_TEXT(412,20,36,30,"重量\r\n1.71吨");
LODOP.ADD_PRINT_TEXT(412,55,39,31,"装载率\r\n27.8%");
LODOP.ADD_PRINT_TEXT(412,85,170,30,"车牌\r\n沪EK6953(含装9.92米/56立方)");
LODOP.ADD_PRINT_TEXT(412,201,60,30,"实际发车时间\r\n05日14:26");

好处:首先,设计的字体太小,对齐不好掌控,通过换行,有一致的左对齐效果,不需要调整。其次,这样分割,减少了块,代码量少,看起来更精简写,写起来,更容易,后期也容易整体进行调整。再次,由于,相同语义的在一个整体,后期更容易理解。顺便说下,不用担心固定文本与动态文本注入问题,后面有扩展功能。

所以,进行扩展:

下面分两块设计,左侧的块右对齐,右侧的块,默认左对齐即可。效果绝对比下面的好,而且也简单。

1603162303202

1603162406517

1603162565064

快捷键

ctrl + 方向箭 微调位置

ctrl + delete 删除。

ctrl + 左键框选,ctrl + 左键拖动,复制。

在打印设计时, 按住CTRL再拖拽选中的对象,可实现快速复制。

打印对象列中按住ALT键的同时拖拉改变对象的顺序位置。

指令相关

ADD_PRINT_TEXT   //插入文本,常用指令
SET_PRINT_STYLE  //设置默认的尺寸
SET_PRINT_STYLEA  // 常用.SET_PRINT_STYLEA(0, 来设置刚刚的元素的特殊样式。
LODOP.ADD_PRINT_LINE   //设置直线。由于只有向上、向小的线,所以,设置高度为1,宽度为1,即为水平直线。

纸张大小

最好打开标尺,来显示纸张的大小。默认使用的纸张大小都是用px来标注的,所以要进行转换。纸张大小,可以在代码中设置,也可以打印的时候选择。在设计模式下,预览的时候,有提示大小。注意,它默认使用的尺寸是px。

//公式  F3为厘米,60mm最终纸的大小227px。
=(F3/10/2.54)*96   

设置默认的风格

LODOP.SET_PRINT_STYLE("FontSize",11);
LODOP.SET_PRINT_STYLE("FontName","楷体");

设置旋转角度

LODOP.SET_PRINT_STYLEA(0,"Angle",-90);

尺寸转换

96px=1英寸=2.54cm=25.4mm。默认的,如指令ADD_PRINT_TEXT中的参数,都是px单位,另外,页面也是px单位。最神奇的是,居然,显示的大小尺寸,跟真实的差不多。

示例PrintSample29.html如下描述:

Lodop很多函数的参数可声明使用in(英寸)、cm(厘米)、mm(毫米)、pt(磅)、px(1/96英寸)等长度单位,注意这里的px不是像素,是绝对长度单位,1px等于1/96英寸,与正常DPI显示设置的像素值相等。如果采用该单位,那么正常显示的屏幕内容与实际打印输出的内容大小相当,这个长度单位可以实现感觉上的“所见等于所打”,px是缺省长度单位,如此以来,单位换算关系为:1in = 2.54cm = 25.4mm = 72pt = 96px

文本元素

可以使用下面的方式,进行设置,代码可以通过生成器来生成。

LODOP.ADD_PRINT_TEXT(24,157,100,20,"(该趟未回皮)");
LODOP.SET_PRINT_STYLEA(0,"FontName","Arial");
LODOP.SET_PRINT_STYLEA(0,"FontSize",8);
LODOP.SET_PRINT_STYLEA(0,"Bold",1);
LODOP.SET_PRINT_STYLEA(0,"Alignment",3);

图片元素

比如插入图片,实际上是插入一段html代码。注意使用绝对的url链接,否则,不被识别。

width=’100%’控制大小占打印区域100%。

LODOP.ADD_PRINT_IMAGE(391,17,60,23,"<img border='0' src='http://10.20.24.65:8005/yunda.png'  width='100%' />");

分块设计

另外,关于打印区域进行分块,可以采用相对坐标。类似如下:

y=100;
LODOP.ADD_PRINT_TEXT(y,57,138,20,"这条线路装货物重量:");
LODOP.ADD_PRINT_TEXT(y+100,66,100,20,"上海ZZ阜阳YD");
LODOP.ADD_PRINT_TEXT(y+130,57,120,20,"本车规定发车时间");

由于生成的代码比较简单,我们也可以自己对代码进行解析,比如,自己定义LODOP.ADD_PRINT_TEXT函数,然后处理、输出新的代码。见后面增加偏移量的增加设计。

相应的代码块放在一起。

自研

官方提供的工具已经很不错了,但是自己也能自己边写一个代码,来解析指令,生成指令等。

大致的思路是:

var LODOP={
  ADD_PRINT_TEXT:function(){
     //处理指令
     //输出优化的指令
     console.log('LODOP.ADD_PRINT_TEXT(y,57,138,20,"这条线路装货物重量:");');
  }
};

增强文字打印

增加文字打印,对花括号内的变量进行解析。其实也没有啥用,设计模板,生成的代码不包含带变量名替换的,还要手动改回来。但总归是一种思路吧。

分两步

步骤一:改造原来提供的LodopFuncs.js文件。在添加授权的位置处,增加如下代码:

//===如下空白位置适合调用统一功能(如注册语句、语言选择等):==
//另一种模式。
//加载模板数据 data
LODOP.tpl = function(str){
    console.log(str);
    var fields = str.match(/\{\w+\}/g);
    if(fields){
        for(var i=0;i< fields.length;i++){
            var field = fields[i].substr(1,fields[i].length-2);
            this.data[field] && (str = str.replace(new RegExp(fields[i],"g"),this.data[field]));
        }
    }
    return str;
}
if(!LODOP._addtpl){ 
    LODOP._addtpl = true;
    var _ADD_PRINT_TEXT = LODOP.ADD_PRINT_TEXT;
    LODOP.ADD_PRINT_TEXT = function(a,b,c,d,txt){
        _ADD_PRINT_TEXT.call(LODOP,a,b,c,d,LODOP.tpl(txt));
    }
}
//=======================================================

代码说明:增加了锁标识,防止重复执行锁内的代码,造成死循环。即_addtpl增加过模板函数后,下次就不再执行了。

步骤二:调用

LODOP = getLodop();
LODOP.data = {hi:'hello',name:'suchuanchao',status:'入场'} ;
LODOP.PRINT_INIT("打印控件功能演示_地磅承重系统3");
LODOP.SET_PRINT_PAGESIZE(3,800,45,"");
LODOP.SET_PRINT_STYLE("FontSize",8);
LODOP.ADD_PRINT_TEXT(18,15,137,23,"上海韵达快运");
LODOP.SET_PRINT_STYLEA(0,"FontName","楷体");
LODOP.ADD_PRINT_TEXT(45,22,100,18,"进出状态:{status}");

代码说明:上面最后一句语句中的花括号内的变量会自动的解析。如果该变量未提供,会原样输出{变量名}

除此之外,不进行封装也行。形式如下:

//首先定义我们自己的函数
//加载模板数据 data
  function tpl(data={}){
    return function (str){
      console.log(str);
      var fields = str.match(/\{\w+\}/g);
      if(fields){
        for(var i=0;i< fields.length;i++){
          var field = fields[i].substr(1,fields[i].length-2);
          data[field] && (str = str.replace(new RegExp(fields[i],"g"),data[field]));
        }
      }
      return str;
    }
  }
//打印时候
function create_page(){
    //注入模板数据对象 data
    // var _t = tpl({hi:'hello',name:'suchuanchao',status:'入场'}); 
    // //测试模板转换输出
    // console.log(_t("{hi} world! My name is {name}"));

    LODOP = getLodop();
    //手动调用函数来进行转换
    LODOP.ADD_PRINT_TEXT(45,22,100,18,_t("进出状态:{status}"));
    //后续代码略

后来发现,sed源码里面也有类似的封装代码,如下:

fprintf (out, _("  -n, --quiet, --silent\n\
                 suppress automatic printing of pattern space\n"));

其实,后面这种简单封装,个人感觉更容易理解一些。

增加偏移量

这个功能,本来是打算做成块功能,即一堆元素形成一个块,然后可以整体进行整体调整位置。但是呢,块是可以嵌套定义,在嵌套的模式下,代码实现起来,比较难,而且也很难理解。所以,就搞最简单的,设置偏移量。

偏移量的含义是:相对设计稿的便宜量。水平x,x>0,相对设计稿右移。同理,竖向y,y>0,相对设计稿下移。

叠加使用,偏移量用变量标式,如:整体偏x0,局部再设置偏移量时,x0+x1。

由于只是使用了像素值,所以,并没有增加转换相关的函数。有需要的话,再考虑完善。

灵感代码:

//比如,设置一个固定的y值,然后需要手工计算,相对固定的y的便宜量。
LODOP.ADD_PRINT_TEXT(412 +y,85,170,30,"车牌\r\n沪EK6953(含装9.92米/56立方)");
LODOP.ADD_PRINT_TEXT(412 +y,201,60,30,"实际发车时间\r\n05日14:26");
LODOP.ADD_PRINT_TEXT(445 +y,19,261,20,"B 你的车牌沪EK1573(含厢9.72米/56立方)");

上面代码没有进行任何封装,但是比较简单,直观。下面讲述自己封装:

方式一:改造原来提供的LodopFuncs.js文件,改造的代码(示例代码只改造了几种常见的典型):

此种方法,副作用少,使用起来问题不大。

LODOP.offset_x = 0;//水平方向偏移量
LODOP.offset_y = 0;//竖直方向偏移量
LODOP.offset = function(y=null,x=null){
    if(y!=null){
        LODOP.offset_y = y;   //这里如果换成  LODOP.offset_y += y,又是另外一种效果。估计用不到。
    }
    if(x!=null){
        LODOP.offset_x = x;
    }
}

if(!LODOP._addtpl){ 
    LODOP._addtpl = true;
    var _ADD_PRINT_TEXT = LODOP.ADD_PRINT_TEXT;
    LODOP.ADD_PRINT_TEXT = function(a,b,c,d,txt){
        console.log(LODOP.offset_x);
        _ADD_PRINT_TEXT.call(LODOP,a + LODOP.offset_y ,b + LODOP.offset_x ,c,d,LODOP.tpl(txt));
    }

    // LODOP.ADD_PRINT_BARCODE(555,76,160,60,"Code93","68005715342");
    var _ADD_PRINT_BARCODE = LODOP.ADD_PRINT_BARCODE;
    LODOP.ADD_PRINT_BARCODE = function(a,b,c,d,codeType,codeStr){
        _ADD_PRINT_BARCODE.call(LODOP,a + LODOP.offset_y ,b + LODOP.offset_x ,c,d,codeType,codeStr);
    }

    // LODOP.ADD_PRINT_LINE(519,13,518,262,0,1);
    //只移动,不变形
    var _ADD_PRINT_LINE = LODOP.ADD_PRINT_LINE;
    LODOP.ADD_PRINT_LINE = function(a,b,c,d,lineType,lineSize){
        _ADD_PRINT_LINE.call(LODOP,a + LODOP.offset_y ,b + LODOP.offset_x ,c + LODOP.offset_y ,d + LODOP.offset_x ,lineType,lineSize);
    }

    // LODOP.ADD_PRINT_RECT(15,12,250,635,0,1);
    var _ADD_PRINT_RECT = LODOP.ADD_PRINT_RECT;
    LODOP.ADD_PRINT_RECT = function(a,b,c,d,lineType,lineSize){
        _ADD_PRINT_RECT.call(LODOP,a + LODOP.offset_y ,b + LODOP.offset_x ,c,d,lineType,lineSize);
    }
}

偏移量叠加

推荐使用下面偏移量叠加功能。

LODOP.offset_x = 0;//水平方向偏移量
LODOP.offset_y = 0;//竖直方向偏移量
LODOP.offset = function(y=null,x=null,isClear){
    var flag = isClear=== -1 ?-1:1;
    if(y!=null){
        LODOP.offset_y += flag*y;
    }
    if(x!=null){
        LODOP.offset_x += flag*x;
    }
}

方式二:底层修改LodopFuncs.js文件:

此种方式是从底层修改,将所有的底层都修改了。副作用大。不确定是否有潜在的问题。目前使用,暂无问题。用这种方式,不但能做偏移量增加,也能做文字模板替换等。核心代码如下:

var _AddItemArray = LODOP.AddItemArray;
LODOP.AddItemArray = function(type,top,left,width,height,strContent,itemname,ShapeType,intPenStyle,intPenWidth,intColor,isLinePosition,BarType,strChartTypess){
    if (top===undefined||left===undefined||width===undefined||height===undefined||strContent===undefined){
        return false;
    }
    if(type == 3 && ShapeType === 0 ){ //直线类,需要特别处理 如ADD_PRINT_LINE、ADD_PRINT_UPLINE等
        _AddItemArray.call(LODOP,type,top + LODOP.offset_y,left + LODOP.offset_x ,width  + LODOP.offset_y,height  + LODOP.offset_x,strContent,itemname,ShapeType,intPenStyle,intPenWidth,intColor,isLinePosition,BarType,strChartTypess);
    }else{
        _AddItemArray.call(LODOP,type,top + LODOP.offset_y,left + LODOP.offset_x ,width,height,strContent,itemname,ShapeType,intPenStyle,intPenWidth,intColor,isLinePosition,BarType,strChartTypess);
    }
    return true;
}

使用代码的示例:

//方式一:
// LODOP.offset_y = 200;
// LODOP.offset_x = 100;
//方式二:
LODOP.offset(200,100);
LODOP.ADD_PRINT_TEXT(526,86,100,20,"交件条码:");
LODOP.SET_PRINT_STYLEA(0,"FontSize",8);
LODOP.SET_PRINT_STYLEA(0,"Alignment",2);
LODOP.ADD_PRINT_BARCODE(555,76,160,60,"Code93","68005715342");
LODOP.ADD_PRINT_LINE(519,13,518,262,0,1);
LODOP.ADD_PRINT_RECT(15,12,250,635,0,1);
LODOP.offset(200,100,-1);  //也有两种,这里省略了。

批量打印

由于前面对基础的封装,批量打印,变得非常简单。示例如下:

offset函数也可以放到create_page代码中。

function print_preview(){
  LODOP = getLodop();
  LODOP.PRINT_INIT("打印控件功能演示_地磅承重系统");
  LODOP.SET_PRINT_MODE("PRINT_NOCOLLATE",1);
  for(var i= 0;i<10;i++){
    create_page(data[i]);
    LODOP.offset(680);//下一页的偏移量
  }
  LODOP.SET_PRINT_PAGESIZE(3,720,45,"");//这里3表示纵向打印且纸高“按内容的高度”;720表示纸宽72mm;45表示页底空白4.5mm
  LODOP.PREVIEW();
}

备注:记得官方推荐是,批量打印时,按切分成多个任务,每个任务打印若干组数据来处理。

文档推荐

下面的文章可以查看,其中包含了自己设计的增加部分。

https://localhost.lodop.net:8443/CLodopDemos/PrintSample35.html

循环设计,设计完后,能返回刚刚设计的代码,然后能再次进行设计。

https://localhost.lodop.net:8443/CLodopDemos/PrintSample50.html

跟自己做的功能重复了

将js代码保存让人无法直接看懂的特殊base64编码。然后方便传输。另外,模板,还提供了前面自己设计的注入功能。