html2canvas 实现页面转图片并下载

一 前言

最近做了一个周报,从不同的数据表抓取数据,然后展示到前端页面显示。这个过程不难,让我烦恼的是:要把周报的数据导出来,然后打印,打印也必须在一张纸上。想到这里,我整理了一下思绪,我要写几个存储过程,存储过程里有很多复杂的逻辑元素。要做个导出功能,还必须在一张A4纸上打印出来。纳尼?必须在一张纸上打印!然后我翻阅了资料和问了度娘。html2canvas插件可以实现我的需求。一开始我是很高兴的,因为能行。接下来我就发现了一些问题:

1.下载下来的js,运行直接报错,Oh,天呐!

2.有些浏览器根本不支持a标签下载图片。

3.图片没有那么清晰,比较模糊。

4.下载到本地的图片不完全,这个很致命。

兜兜转转,终于搞定了。记录此刻!

二 准备

1 <script src="~/Scripts/jquery-1.8.2.js"></script>
2 <script src="~/Scripts/html2canvas.min.js"></script>
3 <script src="~/Scripts/bluebird.js"></script>

三 Demo/js

  1 @using PlatForm.ERP.Models.Reports
  2 @using PlatForm.ERP.Models.Daily
  3 @model WeekReportSummaryAndPlanModel
  4 @{
  5     var webSiteName = ViewBag.WebSiteName;
  6     var weekName = ViewBag.WeekName;
  7     var operateDayOrWeekReport = ViewBag.OperateDayOrWeekReport as OperateDayOrWeekReportModel;
  8     var storeVisitorFlowRateDayOrWeekReports = ViewBag.StoreVisitorFlowRateDayOrWeekReports as IList<StoreVisitorFlowRateDayOrWeekReportModel>;
  9     var singleProductDayOrWeekReports = ViewBag.SingleProductDayOrWeekReports as IList<SingleProductDayOrWeekReportModel>;
 10     var weekReportSummaryAndPlan = ViewBag.WeekReportSummaryAndPlan as WeekReportSummaryAndPlanModel;
 11 }
 12 <style type="text/css">
 13     td {
 14         border: 1px solid #ccc;
 15     }
 16 </style>
 17 <div style="float:right;"><input type="button" id="btn" class="k-button" value="保存为图片" /></div>
 18 <div id="imgDiv" style="padding-top:30px;">
 19     <div>
 20         <table class="zTable" cellpadding="0" cellspacing="0" style="80%;text-align:center;background-color:white;">
 21             <tr>
 22                 <td colspan="20" style="font-weight:bolder;text-align:center;background-color:#87CEFA;">店铺运营基础数据</td>
 23             </tr>
 24             <tr>
 25                 <td style="font-weight:bolder;">日期</td>
 26                 <td style="font-weight:bolder;">成交金额</td>
 27                 <td style="font-weight:bolder;">访客数</td>
 28                 <td style="font-weight:bolder;">去年访客数</td>
 29                 <td style="font-weight:bolder;">访客数同比</td>
 30                 <td style="font-weight:bolder;">浏览量</td>
 31                 <td style="font-weight:bolder;">去年浏览量</td>
 32                 <td style="font-weight:bolder;">浏览量同比</td>
 33             </tr>
 34             @if (operateDayOrWeekReport != null)
 35             {
 36                 <tr>
 37                     <td style="font-weight:bolder;" rowspan="10">@operateDayOrWeekReport.WeekName</td>
 38                     <td>@operateDayOrWeekReport.DealAmount</td>
 39                     <td>@operateDayOrWeekReport.VisitorCount</td>
 40                     <td>@operateDayOrWeekReport.BeforeYearVisitorCount</td>
 41                     <td>@operateDayOrWeekReport.VisitorCountYearOnYear</td>
 42                     <td>@operateDayOrWeekReport.BrowseVolume</td>
 43                     <td>@operateDayOrWeekReport.BeforeYearBrowseVolume</td>
 44                     <td>@operateDayOrWeekReport.BrowseVolumeYearOnYear</td>
 45                 </tr>
 46             }
 47             <tr>
 48                 <td colspan="20" style="font-weight:bolder;text-align:center;background-color:#87CEFA;">下单</td>
 49             </tr>
 50             <tr>
 51                 <td style="font-weight:bolder;">下单客户数</td>
 52                 <td style="font-weight:bolder;">下单单量</td>
 53                 <td style="font-weight:bolder;">下单商品件数</td>
 54                 <td style="font-weight:bolder;">下单金额</td>
 55             </tr>
 56             @if (operateDayOrWeekReport != null)
 57             {
 58                 <tr>
 59                     <td>@operateDayOrWeekReport.OrderCustomerCount</td>
 60                     <td>@operateDayOrWeekReport.OrderQuantity</td>
 61                     <td>@operateDayOrWeekReport.OrderProductCount</td>
 62                     <td>@operateDayOrWeekReport.OrderAmount</td>
 63                 </tr>
 64             }
 65             <tr>
 66                 <td colspan="20" style="font-weight:bolder;text-align:center;background-color:#87CEFA;">成交</td>
 67             </tr>
 68             <tr>
 69                 <td style="font-weight:bolder;">成交客户数</td>
 70                 <td style="font-weight:bolder;">成交单量</td>
 71                 <td style="font-weight:bolder;">成交商品件数</td>
 72                 <td style="font-weight:bolder;">客单价</td>
 73                 <td style="font-weight:bolder;">实际销售件数</td>
 74                 <td style="font-weight:bolder;">实际销售金额</td>
 75                 <td style="font-weight:bolder;">去年实际销售</td>
 76                 <td style="font-weight:bolder;">退货件数</td>
 77                 <td style="font-weight:bolder;">退货金额</td>
 78                 <td style="font-weight:bolder;">去年退货金额</td>
 79                 <td style="font-weight:bolder;">下单转化率</td>
 80                 <td style="font-weight:bolder;">成交转化率</td>
 81                 <td style="font-weight:bolder;">下单成交转化率</td>
 82             </tr>
 83             @if (operateDayOrWeekReport != null)
 84             {
 85                 <tr>
 86                     <td>@operateDayOrWeekReport.DealCustomerCount</td>
 87                     <td>@operateDayOrWeekReport.DealQuantity</td>
 88                     <td>@operateDayOrWeekReport.DealProductCount</td>
 89                     <td>@operateDayOrWeekReport.CustomerPrice</td>
 90                     <td>@operateDayOrWeekReport.RealSaleCount</td>
 91                     <td>@operateDayOrWeekReport.RealSaleAmount</td>
 92                     <td>@operateDayOrWeekReport.BeforeYearRealSale</td>
 93                     <td>@operateDayOrWeekReport.ReturnCount</td>
 94                     <td>@operateDayOrWeekReport.ReturnAmount</td>
 95                     <td>@operateDayOrWeekReport.BeforeYearReturn</td>
 96                     <td>@operateDayOrWeekReport.OrderConversionRate</td>
 97                     <td>@operateDayOrWeekReport.ConversionRate</td>
 98                     <td>@operateDayOrWeekReport.OrderDealConversionRate</td>
 99                 </tr>
100             }
101             <tr>
102                 <td colspan="20" style="font-weight:bolder;text-align:center;background-color:#87CEFA;">费用</td>
103             </tr>
104             <tr>
105                 <td style="font-weight:bolder;">补单佣金</td>
106                 <td style="font-weight:bolder;">活动</td>
107                 <td style="font-weight:bolder;">快车</td>
108                 <td style="font-weight:bolder;">其他</td>
109             </tr>
110             @if (operateDayOrWeekReport != null)
111             {
112                 <tr>
113                     <td>@operateDayOrWeekReport.SupplementOrderCommission</td>
114                     <td>@operateDayOrWeekReport.Activitie</td>
115                     <td>@operateDayOrWeekReport.KuaiChe</td>
116                     <td>@operateDayOrWeekReport.OtherFee</td>
117                 </tr>
118             }
119         </table>
120     </div>
121     <div style="padding-top:50px;">
122         <table class="zTable" cellpadding="0" cellspacing="0" style="80%;text-align:center; background-color:white;">
123             <tr>
124                 <td colspan="20" style="font-weight:bolder;text-align:center;background-color:#87CEFA;">店铺流量</td>
125             </tr>
126             <tr>
127                 <td style="font-weight:bolder;">日期</td>
128                 <td style="font-weight:bolder;">来源</td>
129                 <td style="font-weight:bolder;">访客数</td>
130                 <td style="font-weight:bolder;">访客数占比</td>
131                 <td style="font-weight:bolder;">上周访客数</td>
132                 <td style="font-weight:bolder;">上周访客数占比</td>
133                 <td style="font-weight:bolder;">去年同时期访客数</td>
134                 <td style="font-weight:bolder;">去年同时期访客数占比</td>
135                 <td style="font-weight:bolder;">环比(访客数)</td>
136                 <td style="font-weight:bolder;">同比(访客数)</td>
137             </tr>
138 
139             @if (storeVisitorFlowRateDayOrWeekReports != null)
140             {
141                 foreach (var item in storeVisitorFlowRateDayOrWeekReports)
142                 {
143                     <tr>
144                         <td style="font-weight:bolder;">@item.WeekName</td>
145                         <td>@item.Source</td>
146                         <td>@item.VisitorCount</td>
147                         <td>@item.VisitorCountProportion</td>
148                         <td>@item.BeforeDayOrWeekVisitorCount</td>
149                         <td>@item.BeforeDayOrWeekVisitorCountProportion</td>
150                         <td>@item.BeforeYearVisitorCount</td>
151                         <td>@item.BeforeYearVisitorCountProportion</td>
152                         <td>@item.Ratio</td>
153                         <td>@item.YearRatio</td>
154                     </tr>
155                 }
156             }
157 
158         </table>
159     </div>
160     <div style="padding-top:50px;">
161         <table class="zTable" cellpadding="0" cellspacing="0" style="80%;text-align:center; background-color:white;">
162             <tr>
163                 <td colspan="20" style="font-weight:bolder;text-align:center;background-color:#87CEFA;">单品</td>
164             </tr>
165             <tr>
166                 <td style="font-weight:bolder;">货号</td>
167                 <td style="font-weight:bolder;">日期</td>
168                 <td style="font-weight:bolder;">实际销售件数</td>
169                 <td style="font-weight:bolder;">实际销售金额</td>
170                 <td style="font-weight:bolder;">退货件数</td>
171                 <td style="font-weight:bolder;">退货金额</td>
172                 <td style="font-weight:bolder;">搜索排名</td>
173                 <td style="font-weight:bolder;">浏览量</td>
174                 <td style="font-weight:bolder;">访客数</td>
175                 <td style="font-weight:bolder;">加购人数</td>
176                 <td style="font-weight:bolder;">加购率</td>
177                 <td style="font-weight:bolder;">下单客户数</td>
178                 <td style="font-weight:bolder;">下单转化率</td>
179                 <td style="font-weight:bolder;">成交客户数</td>
180                 <td style="font-weight:bolder;">成交商品数</td>
181                 <td style="font-weight:bolder;">成交转化率</td>
182             </tr>
183             <tr>
184                 @if (singleProductDayOrWeekReports != null)
185                 {
186                     foreach (var item in singleProductDayOrWeekReports)
187                     {
188                     <tr>
189                         <td style="font-weight:bolder;">@item.StyleNo</td>
190                         <td style="font-weight:bolder;">@(item.Time.Value.ToString("yyyy-MM-dd"))</td>
191                         <td>@item.RealSaleCount</td>
192                         <td>@item.RealSaleAmount</td>
193                         <td>@item.ReturnProductCount</td>
194                         <td>@item.ReturnProductAmount</td>
195                         <td>@item.SearchRanking</td>
196                         <td>@item.BrowseVolume</td>
197                         <td>@item.VisitorCount</td>
198                         <td>@item.AddPurchasePeopleCount</td>
199                         <td>@item.AddPurchaseRate</td>
200                         <td>@item.OrderCustomerCount</td>
201                         <td>@item.OrderConversionRate</td>
202                         <td>@item.DealCustomerCount</td>
203                         <td>@item.DealProductCount</td>
204                         <td>@item.DealConversionRate</td>
205                     </tr>
206                 }
207             }
208             </table>
209         </div>
210         <div style="padding-top:50px;">
211             <form id="summaryAndPlan">
212                 <table class="zTable" cellpadding="0" cellspacing="0" style="80%;">
213                     <tr>
214                         <td class="adminTitle" style="font-weight:bolder;">
215                             总结:
216                         </td>
217                         <td class="adminData">
218                             <textarea id="Summary" name="Summary" style="600px;height:100px;">@(weekReportSummaryAndPlan==null?"":weekReportSummaryAndPlan.Summary.Trim())</textarea>
219                         </td>
220                     </tr>
221                     <tr>
222                         <td class="adminTitle" style="font-weight:bolder;">
223                             计划:
224                         </td>
225                         <td class="adminData">
226                             <textarea id="UpPlan" name="UpPlan" style="600px;height:100px;">@(weekReportSummaryAndPlan == null ? "" : weekReportSummaryAndPlan.UpPlan.Trim())</textarea>
227                         </td>
228                     </tr>
229                     <tr>
230                         <td class="adminData" colspan="2" style="text-align: center;">
231                             <input type="button" id="confirmPlan" class="k-button" value="确定" />
232                         </td>
233                     </tr>
234                 </table>
235             </form>
236         </div>
237     </div>
238     <script>
239         $("#confirmPlan").click(function () {
240         if (confirm("确定吗?")) {
241             var summary =$("#@Html.FieldIdFor(x=>x.Summary)").val();
242             var plan =$("#@Html.FieldIdFor(x=>x.UpPlan)").val();
243         $.ajax({
244             url: "@Url.Action("123", "aa")",
245             data: { "webSiteName":"@webSiteName","summary": summary,"plan":plan,"weekName":"@weekName"},
246             type: "POST",
247             success: function (result) {
248                     if (result.split("|")[0] == "true") {
249                         alertBox(result.split("|")[0], result.split("|")[1]);
250                     } else {
251                         alertBox(result.split("|")[0], result.split("|")[1]);
252                     }
253                 }
254             });
255         }
256     });
257     </script>
258     <script src="~/Scripts/jquery-1.8.2.js"></script>
259     <script src="~/Scripts/html2canvas.min.js"></script>
260     <script src="~/Scripts/bluebird.js"></script>
261     <script type="text/javascript">
262     $(document).ready(function () {
263         // canvas生成图片
264         $("#btn").on("click", function () {
265             var getPixelRatio = function (context) { // 获取设备的PixelRatio
266                 var backingStore = context.backingStorePixelRatio ||
267                     context.webkitBackingStorePixelRatio ||
268                     context.mozBackingStorePixelRatio ||
269                     context.msBackingStorePixelRatio ||
270                     context.oBackingStorePixelRatio ||
271                     context.backingStorePixelRatio || 0.5;
272                 return (window.devicePixelRatio || 0.5) / backingStore;
273             };
274             //生成的图片名称
275             var imgName = "@(webSiteName)@(weekName).jpg";
276             var shareContent = document.getElementById("imgDiv");
277             var width = shareContent.offsetWidth;
278             var height = shareContent.offsetHeight;
279             var canvas = document.createElement("canvas");
280             var context = canvas.getContext('2d');
281             var scale = getPixelRatio(context); //将canvas的容器扩大PixelRatio倍,再将画布缩放,将图像放大PixelRatio倍。
282             canvas.width = width * scale;
283             canvas.height = height * scale;
284             canvas.style.width = width + 'px';
285             canvas.style.height = height + 'px';
286             context.scale(scale, scale);
287 
288             var opts = {
289                 scale: 1,
290                 background: '#FFFFFF'
291             };
292             window.pageYoffset = 0;
293             document.documentElement.scrollTop = 0;
294             document.body.scrollTop = 0;
295             html2canvas(shareContent, opts).then(function (canvas) {
296                 context.imageSmoothingEnabled = false;
297                 context.webkitImageSmoothingEnabled = false;
298                 context.msImageSmoothingEnabled = false;
299                 context.imageSmoothingEnabled = false;
300                 var dataUrl = canvas.toDataURL('image/jpeg', 1.0);
301                 dataURIToBlob(imgName, dataUrl, callback);
302             });
303         });
304     })
305 
306 
307     // edited from https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
308     var dataURIToBlob = function (imgName, dataURI, callback) {
309         var binStr = atob(dataURI.split(',')[1]),
310             len = binStr.length,
311             arr = new Uint8Array(len);
312 
313         for (var i = 0; i < len; i++) {
314             arr[i] = binStr.charCodeAt(i);
315         }
316 
317         callback(imgName, new Blob([arr]));
318     }
319 
320     var callback = function (imgName, blob) {
321         var triggerDownload = $("<a>").attr("href", URL.createObjectURL(blob)).attr("download", imgName).appendTo("body").on("click", function () {
322             if (navigator.msSaveBlob) {
323                 return navigator.msSaveBlob(blob, imgName);
324             }
325         });
326         triggerDownload[0].click();
327         triggerDownload.remove();
328     };
329     </script>

四 效果图

五 最后

  自己记录一下,有这方面的需求,大家可以借鉴一下,不喜勿喷!

原文地址:https://www.cnblogs.com/aiyining1314/p/13320976.html