前边有提到最近的一个证书生成保存下载打印的需求。

之前实现的是一个单个操作的页面,现在把实现的批量效果和进度效果的代码展示出来。

html

 1 <button class="btn btn-primary" ng-click="derive()" style="margin-top: 20px;">生成证书(方案1)</button>
 2                     <button class="btn btn-primary" ng-click="derive2()" style="margin-top: 20px;">生成证书(方案2)</button>
 3                     <button class="btn btn-primary" ng-click="derive3()" style="margin-top: 20px;">生成证书(方案3)</button>
 4 <grid-table data-control="tableControl"></grid-table>
 5         <!-- 进度 -->
 6         <div class="progress_cls" ng-if="progressShow">
 7             <div class="layui-progress layui-progress-big" lay-filter="notifierProgress" lay-showpercent="yes">
 8                 <div class="layui-progress-bar" lay-percent="0%">
 9                 <!-- 解决数字不出来问题 -->
10                     <span class="layui-progress-text">0%</span>
11                 </div>
12             </div>
13             <div class="progress_stitistics_cls">
14                 <div>总数:<span>{{progressTotal}}</span></div>
15                 <div>成功:<span>{{doneNum}}</span></div>
16                 <div>失败:<span>{{failedNum}}</span></div>
17             </div>
18             <button class="btn btn-primary" ng-click="closeProgress()" ng-if="progressDone">确定</button>
19         </div>
20         <!-- 进度2 -->
21         <div class="progress_cls" ng-if="progressShow2">
22             <div class="layui-progress layui-progress-big" lay-filter="notifierProgress2" lay-showpercent="yes">
23                 <div class="layui-progress-bar" lay-percent="0%">
24                 <!-- 解决数字不出来问题 -->
25                     <span class="layui-progress-text">0%</span>
26                 </div>
27             </div>
28             <div class="progress_stitistics_cls">
29                 <div>总数:<span>{{progressTotal}}</span></div>
30                 <div>当前完成:<span>{{doneNum}}</span></div>
31             </div>
32             <button class="btn btn-primary" ng-click="closeProgress()" ng-if="progressDone2">确定</button>
33         </div>
34         <!-- 进度3 -->
35         <div class="progress_cls" ng-if="progressShow3">
36             <div class="layui-progress layui-progress-big" lay-filter="notifierProgress3" lay-showpercent="yes">
37                 <div class="layui-progress-bar" lay-percent="0%">
38                 <!-- 解决数字不出来问题 -->
39                     <span class="layui-progress-text">0%</span>
40                 </div>
41             </div>
42             <div class="progress_stitistics_cls">
43                 <div>总数:<span>{{progressTotal}}</span></div>
44                 <div>当前完成:<span>{{doneNum}}</span></div>
45             </div>
46             <button class="btn btn-primary" ng-click="closeProgress()" ng-if="progressDone3">确定</button>
47         </div>

css

 1 #toPrint {
 2     position:absolute;
 3     left: 10000px;
 4     top: 50%;
 5 }
 6
 7 #toPrint div {
 8     position:absolute;
 9     font-weight: bold;
10 }
11
12 #toPrint img {
13     position:absolute;
14 }
15
16 #textArea {
17     width: 100%;
18     height: 100%;
19 }
20
21 .printCanvas {
22     display:inline-block;
23 }
24
25 #toPrint3 {
26     position:absolute;
27     left: 10000px;
28     top: 50%;
29     display: inline-flex;
30 }

js

  1  /*
  2      导出数据
  3      */
  4     $scope.derive = function () {
  5         var toSendList = [];
  6         var passList = [];
  7         for(var i=0;i<$scope.tableControl.rows.length;i++) {
  8             if($scope.tableControl.rows[i].select) {
  9                 toSendList.push($scope.tableControl.allData[i]);
 10                 //没有数据,原5,现先1
 11                 if(1 == $scope.tableControl.allData[i].applyStatus) {
 12                     passList.push($scope.tableControl.allData[i]);
 13                 }
 14             }
 15         }
 16         if(1 > toSendList.length) {
 17             layer.alert("请选择需要生成证书的记录");
 18             return;
 19         }
 20         if(toSendList.length != passList.length) {
 21             layer.alert("只能对审核通过的记录进行证书生成");
 22             return;
 23         }
 24         layer.confirm("是否确认生成证书?", {
 25             btn: ['确定', '取消']
 26         }, function () {
 27             $scope.progressTotal = toSendList.length;
 28             $scope.doneNum = 0;
 29             $scope.failedNum = 0;
 30
 31             layer.closeAll();
 32             var maskLoad = layer.load(1, {shade: [0.8, '#393D49']});
 33             //打开进度
 34             $scope.curProgress = "0%";
 35             $scope.progressShow = true;
 36             $.each(toSendList, function(index, e){
 37                 var url = location.origin+"/pages/print/printBatch.html?"+encodeURIComponent(e.studentName)+"&&"+encodeURIComponent(e.applySchoolName);
 38                 //services.save_notifier(url).success(function (res) { 39                 $.ajax({
 40                     url: location.origin+'/basic/school',
 41                     headers: {'token': $rootScope.token},
 42                     type: 'get',
 43                     dataType: 'json',
 44                     contentType: 'application/json;charset=UTF-8',
 45                     async: true,
 46                 }).success(function (res) {
 47                     if ('OK' == res.result) {
 48                         $scope.doneNum++;
 49                     } else {
 50                         $scope.failedNum++;
 51                     }
 52                 }).error(function (res) {
 53                     $scope.failedNum++;
 54                 }).always(function () {
 55                     //刷新成功和失败数量
 56                     if(($scope.doneNum + $scope.failedNum) < $scope.progressTotal) {
 57                         //更新进度
 58                         //$scope.curProgress = Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%";
 59                         element.progress('notifierProgress', Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%")
 60                     } else {
 61                         //完成
 62                         $scope.curProgress = "100%";
 63                         ////进度条渲染需要时间??数据较少时执行完成还没渲染出来--改用定时器
 64                         var finishInterval = setInterval(function() {
 65                             if($(".layui-progress")[0]) {
 66                                 element.progress('notifierProgress', "100%");
 67                                 clearInterval(finishInterval);
 68                             }
 69                         }, 200);
 70                         $scope.progressDone = true;
 71                         //去掉转圈
 72                         $(".layui-layer-loading").hide();
 73                         //layer.closeAll();
 74                     }
 75                 });
 76             });
 77
 78         });
 79     }
 80
 81     //方案2
 82     $scope.derive2 = function () {
 83         //先单线程
 84         var toSendList = [];
 85         var passList = [];
 86         for(var i=0;i<$scope.tableControl.rows.length;i++) {
 87             if($scope.tableControl.rows[i].select) {
 88                 toSendList.push($scope.tableControl.allData[i]);
 89                 //没有数据,原5,现先1
 90                 if(1 == $scope.tableControl.allData[i].applyStatus) {
 91                     passList.push($scope.tableControl.allData[i]);
 92                 }
 93             }
 94         }
 95         if(1 > toSendList.length) {
 96             layer.alert("请选择需要生成证书的记录");
 97             return;
 98         }
 99         if(toSendList.length != passList.length) {
100             layer.alert("只能对审核通过的记录进行证书生成");
101             return;
102         }
103         layer.confirm("是否确认生成证书?", {
104             btn: ['确定', '取消']
105         }, function () {
106             $scope.progressTotal = toSendList.length;
107             $scope.doneNum = 0;
108             $scope.failedNum = 0;
109
110             layer.closeAll();
111             var maskLoad = layer.load(1, {shade: [0.8, '#393D49']});
112             //打开进度
113             $scope.curProgress = "0%";
114             $scope.progressShow2 = true;
115
116             //弹出隐藏绘图层
117             $("#printArea").remove();
118             $("body").append("<div id='printArea'><div id='toPrint'></div></div>");
119
120             //绘制证书
121             suitScreen($scope);
122             var imgStr = "<img src='" + $scope.printObj.notifierObj.url+"' style='width:"+$scope.printObj.notifierObj.width+"px;height:"+
123             $scope.printObj.notifierObj.height+"px'><div id='textArea'></div>";
124             $("#toPrint").append(imgStr);
125             $("#toPrint").css("margin-top", (0-$scope.printObj.notifierObj.height-60)/2+"px");
126             $("#toPrint").css("height", $scope.printObj.notifierObj.height+"px");
127             $("#toPrint").css("width", $scope.printObj.notifierObj.width+"px");
128
129             //填充文字
130             $.each(toSendList, function(index, e){
131                 $("#textArea").empty();
132                 $scope.printObj.paramList[0].objName = e.studentName;
133                 $scope.printObj.paramList[1].objName = e.applySchoolName;
134                 var htmlStr = "";
135                 for(i=0;i<$scope.printObj.paramList.length;i++) {
136                     var nowObj = $scope.printObj.paramList[i];
137                     if(nowObj.fontSize < 12) {
138                         htmlStr += "<div style='font-family:"+nowObj.fontFamily+";font-size:"+nowObj.fontSize+"px;top:"+nowObj.top+"px;left:"+nowObj.left+
139                         //谷歌浏览器字体小于12px时会不再变小,使用-webkit-transform兼容,并设置已左上角作为变换原点
140                             "px;-webkit-transform:scale("+nowObj.fontSize/12+","+nowObj.fontSize/12+");transform-origin:0 0'>"+nowObj.objName+"</div>";
141                     } else {
142                         htmlStr += "<div style='font-family:"+nowObj.fontFamily+";font-size:"+nowObj.fontSize+"px;top:"+nowObj.top+"px;left:"+nowObj.left+
143                             "px'>"+nowObj.objName+"</div>";
144                     }
145                 }
146                 //$("#toPrint").css("margin-left", (0-$scope.printObj.notifierObj.width)/2+"px");
147                 $("#textArea").append(htmlStr);
148
149                 //保存
150                 html2canvas(document.querySelector("#toPrint")).then(function(canvas) {
151                     var type = 'png';//格式可以自定义
152                     var imgData = canvas.toDataURL(type);
153                     imgData = imgData.replace(_fixType(type),'image/octet-stream');
154                     //文件名可以自定义
155                     var filename = '录取通知书_' + e.studentName + '.' + type;
156                     saveFile(imgData,filename);
157                     $scope.doneNum++;
158                     //刷新成功和失败数量
159                     if(($scope.doneNum + $scope.failedNum) < $scope.progressTotal) {
160                         //更新进度
161                         //$scope.curProgress = Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%";
162                         element.progress('notifierProgress2', Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%")
163                     } else {
164                         //完成
165                         $scope.curProgress = "100%";
166                         ////进度条渲染需要时间??数据较少时执行完成还没渲染出来--改用定时器
167                         var finishInterval = setInterval(function() {
168                             if($(".layui-progress")[0]) {
169                                 element.progress('notifierProgress2', "100%");
170                                 clearInterval(finishInterval);
171                             }
172                         }, 200);
173                         $scope.progressDone2 = true;
174                         //去掉转圈
175                         $(".layui-layer-loading").hide();
176                     }
177                 });
178             });
179
180         });
181     }
182
183     //方案3
184     $scope.derive3 = function () {
185         //先单线程
186         var toSendList = [];
187         var passList = [];
188         for(var i=0;i<$scope.tableControl.rows.length;i++) {
189             if($scope.tableControl.rows[i].select) {
190                 toSendList.push($scope.tableControl.allData[i]);
191                 //没有数据,原5,现先1
192                 if(1 == $scope.tableControl.allData[i].applyStatus) {
193                     passList.push($scope.tableControl.allData[i]);
194                 }
195             }
196         }
197         if(1 > toSendList.length) {
198             layer.alert("请选择需要生成证书的记录");
199             return;
200         }
201         if(toSendList.length != passList.length) {
202             layer.alert("只能对审核通过的记录进行证书生成");
203             return;
204         }
205         layer.confirm("是否确认生成证书?", {
206             btn: ['确定', '取消']
207         }, function () {
208             $scope.progressTotal = toSendList.length;
209             $scope.doneNum = 0;
210             $scope.failedNum = 0;
211
212             layer.closeAll();
213             var maskLoad = layer.load(1, {shade: [0.8, '#393D49']});
214             //打开进度
215             $scope.curProgress = "0%";
216             $scope.progressShow3 = true;
217
218             //弹出隐藏绘图层
219             $("#toPrint3").remove();
220             $("body").append("<div id='toPrint3'></div>");
221
222             suitScreen($scope);
223
224             var allCanvas = $("canvas");
225             var zip = new JSZip();
226             //zip.file("readme.txt", "证书\n");
227             var img = zip.folder("images");
228
229             //图片加载是异步,所有用递归来做,否则前边生成的都会被最后一个覆盖
230             (function loop(n) {
231                 if (n>=toSendList.length) return;
232
233                 var image = new Image();
234                 image.src = $scope.printObj.notifierObj.url;
235                 image.onload = function () { //为异步函数,所以将创建canvas放在onload中.
236
237                     $("#toPrint3").empty();
238                     $("#toPrint3").append("<canvas id='toPrint_' class='printCanvas'></canvas>");
239                     $scope.printObj.paramList[0].objName = toSendList[n].studentName;
240                     $scope.printObj.paramList[1].objName = toSendList[n].applySchoolName;
241
242
243                     $("#toPrint_").css("margin-top", (0-$scope.printObj.notifierObj.height)/2+"px");
244                     var canvas = document.getElementById("toPrint_");
245                     canvas.width = $scope.printObj.notifierObj.width;
246                     canvas.height = $scope.printObj.notifierObj.height;
247                     var ctx = canvas.getContext("2d");
248                     ctx.drawImage(image, 0, 0, $scope.printObj.notifierObj.width, $scope.printObj.notifierObj.height);
249                     $.each($scope.printObj.paramList, function(index, e) {
250                         //canvas的字体不会有12px的兼容性问题
251                         ctx.font = "bold "+e.fontSize+"px "+e.fontFamily;
252                         //canvas写字以字体的左下角为基准,因而要再加一个字体大小的高度
253                         ctx.fillText(e.objName, e.left, e.top+e.fontSize);
254                     });
255                     img.file('录取通知书_' + toSendList[n].studentName + '.png', canvas.toDataURL().substring(22), {base64: true});
256                     $scope.doneNum++;
257                     //刷新成功和失败数量
258                     if(($scope.doneNum + $scope.failedNum) < $scope.progressTotal) {
259                         //更新进度
260                         //$scope.curProgress = Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%";
261                         element.progress('notifierProgress3', Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%")
262                     } else {
263                         //完成
264                         $scope.curProgress = "100%";
265                         var finishInterval = setInterval(function() {
266                             if($(".layui-progress")[0]) {
267                                 element.progress('notifierProgress3', "100%");
268                                 clearInterval(finishInterval);
269                             }
270                         }, 200);
271                         $scope.progressDone3 = true;
272                         //去掉转圈
273                         $(".layui-layer-loading").hide();
274
275                         zip.generateAsync({type:"blob"}).then(function(content) {
276                             saveAs(content, "证书.zip");
277                         });
278                     }
279
280                     loop(n+1);
281                 }
282           })(0);
283
284
285         });
286     }
287
288     $scope.closeProgress = function () {
289         $scope.progressShow = false;
290         $scope.progressDone = false;
291         $scope.progressShow2 = false;
292         $scope.progressDone2 = false;
293         $scope.progressShow3 = false;
294         $scope.progressDone3 = false;
295         layer.closeAll();
296     }
297
298   //模板
299     $scope.printObj = {
300         notifierObj:{
301             "url": "/res/img/notifications.png",
302             "height": "631",
303             "width": "942"
304         },
305         paramList:[{
306                 "objName":"黄大明",
307                 "left":"133",
308                 "top":"191",
309                 "fontSize": "28",
310                 "fontFamily": "KaiTi"
311             },{
312                 "objName":"SXXX小学",
313                 "left":"460",
314                 "top":"272",
315                 "fontSize": "28",
316                 "fontFamily": "KaiTi"
317             },{
318                 "objName":"2018",
319                 "left":"195",
320                 "top":"312",
321                 "fontSize": "28",
322                 "fontFamily": "KaiTi"
323             },{
324                 "objName":"8",
325                 "left":"325",
326                 "top":"312",
327                 "fontSize": "28",
328                 "fontFamily": "KaiTi"
329             },{
330                 "objName":"31",
331                 "left":"405",
332                 "top":"312",
333                 "fontSize": "28",
334                 "fontFamily": "KaiTi"
335             }]
336     }
337
338     function suitScreen($scope) {
339         //A4横向标准
340         var effectiveHeight = 1240;
341         var effectiveWidth = 1754;
342         if($scope.printObj.notifierObj.width/effectiveWidth > $scope.printObj.notifierObj.height/effectiveHeight) {
343             //取最接近的一个属性进行自适应,并适当调小一些
344             var suitTimes = $scope.printObj.notifierObj.width/effectiveWidth*1.2;
345         } else {
346             var suitTimes = $scope.printObj.notifierObj.height/effectiveHeight*1.2;
347         }
348         $scope.printObj.notifierObj.width = $scope.printObj.notifierObj.width/suitTimes;
349         $scope.printObj.notifierObj.height = $scope.printObj.notifierObj.height/suitTimes;
350         for(i=0;i<$scope.printObj.paramList.length;i++) {
351             $scope.printObj.paramList[i].fontSize = $scope.printObj.paramList[i].fontSize/suitTimes;
352             $scope.printObj.paramList[i].left = $scope.printObj.paramList[i].left/suitTimes;
353             $scope.printObj.paramList[i].top = $scope.printObj.paramList[i].top/suitTimes;
354         }
355     }
356
357     function _fixType(type) {
358         //imgData是一串string,base64
359         type = type.toLowerCase().replace(/jpg/i, 'jpeg');
360         var r = type.match(/png|jpeg|bmp|gif/)[0];
361         return 'image/' + r;
362     }
363
364     function saveFile(data, filename) {
365         var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
366         save_link.href = data;
367         save_link.download = filename;
368
369         //下载
370         var event = document.createEvent('MouseEvents');
371         event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
372         save_link.dispatchEvent(event);
373     }
374
375     //方案3使用canvas先画好,然后批量打包保存
376     function drawNotifier($scope, id, img) {
377         //canvas需要先定位好,否则画好再动就清除了
378         //$("#toPrint").css("margin-left", (0-$scope.printObj.notifierObj.width)/2+"px");不可见元素,同样不考虑其左右缩进
379         $(id).css("margin-top", (0-$scope.printObj.notifierObj.height)/2+"px");
380         var canvas = document.getElementById(id.substring(1));
381         canvas.width = $scope.printObj.notifierObj.width;
382         canvas.height = $scope.printObj.notifierObj.height;
383         var ctx = canvas.getContext("2d");
384         var img=new Image();
385         img.src = $scope.printObj.notifierObj.url;
386         var deferred=$.Deferred();
387         var thisObj = $scope.printObj;
388         //img.οnlοad=function() {389         requestAnimationFrame(function() {
390             //需要onload方法接收,否则画不出
391             ctx.drawImage(img, 0, 0, thisObj.notifierObj.width, thisObj.notifierObj.height);
392             //写文字,且要在画好图片之后写,否则会被图片覆盖
393             $.each(thisObj.paramList, function(index, e) {
394                 //canvas的字体不会有12px的兼容性问题
395                 ctx.font = "bold "+e.fontSize+"px "+e.fontFamily;
396                 //canvas写字以字体的左下角为基准,因而要再加一个字体大小的高度
397                 ctx.fillText(e.objName, e.left, e.top+e.fontSize);
398             });
399             deferred.resolve(canvas.toDataURL().substring(22));
400         })
401         //}
402         return deferred.promise();
403
404     }

以上是三种实现方案,第一种需要一个接口,后两种不需要接口,直接前端生成。

说一下中间遇到的问题:

1.进度条里边的文字显示不出来:

用的是layui的进度条,很简单,就几行代码。

<div class="layui-progress layui-progress-big" lay-filter="notifierProgress" lay-showpercent="yes"><div class="layui-progress-bar" lay-percent="0%"></div>
</div>

但是进度百分比文字就是显示不出来,查看元素,官方api里是有span标签的,但是自己的一直没有,可见layui官网也是有点坑。也许一些版本或者新的版本支持吧,但是有个直接有效的解决办法就是,在内部直接写一个span标签。

      <div class="layui-progress layui-progress-big" lay-filter="notifierProgress" lay-showpercent="yes"><div class="layui-progress-bar" lay-percent="0%"><!-- 解决数字不出来问题 --><span class="layui-progress-text">0%</span></div></div>

2.进度动态更新:

当前使用的是angular框架,我使用了一个变量来动态刷新,但是实际并没有效果。最终不得不使用组件的方法:

element.progress('notifierProgress', Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%")

其中第一个参数就是前边的lay-filter

3.对于需要进行绘制又不想让用户看到:

很简单的方法,直接给你需要操作的元素绝对定位,然后给他一个很大很大的left(当然上下左右都可以),这样他就飘到屏幕的十万八千里外了,用户除非自己F12看,否则永远也看不到。这个方法之前在上一家公司有使用过。

4.对于canvas画图片异步加载的问题:

这个问题困扰了我很久,因为我要做批量绘制,使用同一个dom,绘制完一个然后清空再绘制下一个。早早就写完了逻辑,一运行也没有报错,燃鹅,打开文件一看,全都是最后一条数据生成的图片。已经使用了image.onload进行绘制了还出现这种问题。然后打断点调试,发现each遍历完了,才走进onload事件。我就又尝试着用定时器、用回调,都没有成功,而且这样比较容易出现问题。最终找到了一个解决办法,那就是用递归。代码如下

 1 //图片加载是异步,所有用递归来做,否则前边生成的都会被最后一个覆盖
 2             (function loop(n) {
 3                 if (n>=toSendList.length) return;
 4
 5                 var image = new Image();
 6                 image.src = $scope.printObj.notifierObj.url;
 7                 image.onload = function () { //为异步函数,所以将创建canvas放在onload中.
 8
 9                     $("#toPrint3").empty();
10                     $("#toPrint3").append("<canvas id='toPrint_' class='printCanvas'></canvas>");
11                     $scope.printObj.paramList[0].objName = toSendList[n].studentName;
12                     $scope.printObj.paramList[1].objName = toSendList[n].applySchoolName;
13
14
15                     $("#toPrint_").css("margin-top", (0-$scope.printObj.notifierObj.height)/2+"px");
16                     var canvas = document.getElementById("toPrint_");
17                     canvas.width = $scope.printObj.notifierObj.width;
18                     canvas.height = $scope.printObj.notifierObj.height;
19                     var ctx = canvas.getContext("2d");
20                     ctx.drawImage(image, 0, 0, $scope.printObj.notifierObj.width, $scope.printObj.notifierObj.height);
21                     $.each($scope.printObj.paramList, function(index, e) {
22                         //canvas的字体不会有12px的兼容性问题
23                         ctx.font = "bold "+e.fontSize+"px "+e.fontFamily;
24                         //canvas写字以字体的左下角为基准,因而要再加一个字体大小的高度
25                         ctx.fillText(e.objName, e.left, e.top+e.fontSize);
26                     });
27                     img.file('录取通知书_' + toSendList[n].studentName + '.png', canvas.toDataURL().substring(22), {base64: true});
28                     $scope.doneNum++;
29                     //刷新成功和失败数量
30                     if(($scope.doneNum + $scope.failedNum) < $scope.progressTotal) {
31                         //更新进度
32                         //$scope.curProgress = Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%";
33                         element.progress('notifierProgress3', Math.round(($scope.doneNum + $scope.failedNum) / $scope.progressTotal * 100) + "%")
34                     } else {
35                         //完成
36                         $scope.curProgress = "100%";
37                         var finishInterval = setInterval(function() {
38                             if($(".layui-progress")[0]) {
39                                 element.progress('notifierProgress3', "100%");
40                                 clearInterval(finishInterval);
41                             }
42                         }, 200);
43                         $scope.progressDone3 = true;
44                         //去掉转圈
45                         $(".layui-layer-loading").hide();
46
47                         zip.generateAsync({type:"blob"}).then(function(content) {
48                             saveAs(content, "证书.zip");
49                         });
50                     }
51
52                     loop(n+1);
53                 }
54           })(0);

还有在调试中使用的一些方法,其中:

 1 var deferred=$.Deferred();
 2         var thisObj = $scope.printObj;
 3         //img.οnlοad=function() { 4         requestAnimationFrame(function() {
 5             //需要onload方法接收,否则画不出
 6             ctx.drawImage(img, 0, 0, thisObj.notifierObj.width, thisObj.notifierObj.height);
 7             //写文字,且要在画好图片之后写,否则会被图片覆盖
 8             $.each(thisObj.paramList, function(index, e) {
 9                 //canvas的字体不会有12px的兼容性问题
10                 ctx.font = "bold "+e.fontSize+"px "+e.fontFamily;
11                 //canvas写字以字体的左下角为基准,因而要再加一个字体大小的高度
12                 ctx.fillText(e.objName, e.left, e.top+e.fontSize);
13             });
14             deferred.resolve(canvas.toDataURL().substring(22));
15         })
16         //}
17         return deferred.promise();

给方法添加回调,使用promise,这样在调用这个方法时就可以用then进行接收了。

requestAnimationFrame,一个用的好比较有意思的window方法,类似timeout和interval,但是不需要设置时间,此处可以代替onload使用。

5.canvas转base64与文件操作:

 1 //canvas转图片
 2
 3 canvas.toDataURL().substring(22)
 4
 5 //js新建文件和文件填充
 6
 7 var zip = new JSZip();
 8 //zip.file("readme.txt", "证书\n");
 9 var img = zip.folder("images");
10
11 img.file('录取通知书_' + toSendList[n].studentName + '.png', canvas.toDataURL().substring(22), {base64: true});
12
13 //js文件打包下载
14
15 zip.generateAsync({type:"blob"}).then(function(content) {
16 saveAs(content, "证书.zip");
17 });

用到的插件:FileSaver.js, jszip.min.js。用法也比较简单。

6.数据较少时,进度条无法刷新到100%的问题:

数据较少,用时较少,然后进度条渲染出来了,但是一直停在0%。没有研究源码,不知道是因为异步加载的问题还是因为css动画的样式问题还是因为渲染组件异步的问题,总之就是在执行完之后,打断点审查元素并没有生成组件,所有此时更新进度100%也没用。

解决方法:使用定时器

1     var finishInterval = setInterval(function() {
2           if($(".layui-progress")[0]) {
3                   element.progress('notifierProgress3', "100%");
4                        clearInterval(finishInterval);
5            }
6      }, 200);

一般遇到这种异步造成还没渲染完成就做了处理的问题,使用定时器或者timeout都是一种解决办法。

转载于:https://www.cnblogs.com/ljwsyt/p/9555931.html

js证书批量生成与打包下载相关推荐

  1. 前端js html转换成pdf可下载打印;前端js可批量生成条形码;前端js可批量生成二维码,生成letter标签

    注意:本文调试的是letter纸尺寸 前端js html转换成pdf可下载打印  html2canvas  + jspdf 前端js生成条形码 Options · lindell/JsBarcode ...

  2. Java 批量文件不打包下载_【Java】Java批量文件打包下载zip

    /* * 另存为 */ @RequestMapping("/saveAs.do") public @ResponseBody void saveAs(String filePath ...

  3. java动态生成excel_java动态生成excel打包下载

    @SuppressWarnings("unchecked")public String batchExport() throwsDBException{ @SuppressWarn ...

  4. C# NPOI 批量导出Excel 打包下载

    public void NopiPack()         {             //下载             int colCount = 43;//列数             Res ...

  5. Android签名证书的生成

    本节只针对如何从零开始实现简单的打包签名 目录 概要 Keytool生成JKS签名证书 Android Studio生成JKS签名证书 AS版本信息 签名证书的生成 签名打包 概要 debug.key ...

  6. java实现excel打包下载

    最近公司让我做一个报表的打包下载功能,以前从来没有接触过,从问了下度娘,实现其功能的方式很多,其中我找到一篇博文就写得非常好,本人也是根据博文所讲做的,但是现在找不到他的链接地址了,,在这里就本人所做 ...

  7. 前端批量生成二维码并打包下载

    前端批量生成二维码并打包下载 项目中遇到一个紧急需求在没有后端配合的情况下,前端独自实现生成二维码并打包下载 生成二维码:下载 qrcodejs2 批量打包下载:下载 JSZip 和 FileSave ...

  8. vue实现前台生成word并下载,并且可实现批量打包下载

    一.引用场景: 前面的一个项目里面有一个申报表,后台收集的申报表需要批量导出,一开始我是用到的C#的WordOpApControlle,但是这种方法存在一个难以解决的问题.就是当你导出的这个word模 ...

  9. vue批量生成二维码并压缩打包下载(图片带标题)

    借鉴:原文~~~(但是有问题,在基础上改良) 效果图(生成的二维码带下面标题的): 代码如下: 先安装依赖(或者用命令:npm i jszip): yarn add jszip yarn add fi ...

最新文章

  1. tensorflow 代码阅读
  2. 编写自己的Shell解释器
  3. JAVA怎么查找错误,如何调试错误“符号查找错误:未定义符号”
  4. 记住要重置线程上下文类加载器
  5. opencv +opencv_contrib+CMake+VS2015
  6. [转]Http Message结构学习总结
  7. 用java写一个贪吃蛇小游戏(源码在最后)
  8. 深入理解双线性插值算法
  9. 爬虫python是什么意思_python爬虫是什么? 【黑马程序员】
  10. 计算机教室条幅文字,教室横幅标语尺寸
  11. 利用python实现华氏温度和摄氏温度的转换
  12. JavsScript 节流函数 分金定穴
  13. Android中对静态壁纸和动态壁纸原理深入理解
  14. ip-guard控制台远程控制客户端的授权方式有几种?
  15. java jtable 复选框_java swing如何在JTable一个单元格添加多个复选框
  16. Tech Lead(技术经理) 带人之道
  17. 鸿蒙os后台运行,Day10 鸿蒙,Ability全家桶(二)如何后台运行任务
  18. OSChina 娱乐弹弹弹——假期就是睡睡睡
  19. 劲乐园合歌(幽灵圣典+飞吧喜鹊+唯一+v3+幽灵圣典2)1铃声 劲乐...
  20. 网页服务器版本,华为网页版本进云服务器

热门文章

  1. adxl345取出值怎么算角度_改了别人的程序和一些自己的研究,用ADXL345测量角度成功...
  2. python数据分析:流量数据化运营(中)——流量数据波动原因下探分析
  3. 使用 MATLAB 进行无线通信设计
  4. Ant Design中select框往下滑动会自动回到顶部的问题
  5. 平均股价的时间序列图形_如何用公式表达股票平均价格
  6. 策略模式——实现促销活动
  7. Codeforces713D(二维RMQ)
  8. 使用python selenium爬取淘宝商品信息 自动登录淘宝和爬取某一宝贝的主图,属性图和详情图等等
  9. 中学校园IP网络广播系统解决方案-校园数字IP广播系统方案设计指南
  10. 为什么设计理化生实验室智能吊装系统?