项目中遇到一个需求:将展示的二维码页面保存成图片。在网上找了很久找到了一款插件html2canvas,本以为用这个插件可以轻松实现网页区域截图呢,没想到出了幺蛾子,花了我一天的时间来解决。以下为利用html2canvas实现网页区域截图的整个过程。
【相关资料】
1、div_to_img:这是一个单html实现的网页转图片的demo。下载地址>>
2、div2img:Tp-admin及ThinkAdmin后端框架可以集成的插件代码。下载地址>>
在实现网页区域截屏功能的过程中,遇到了一个问题“网页通过script标签引入了html2canvas,但在使用时却仍然报错“Uncaught ReferenceError: html2canvas is not defined”。”为此波波还特意在SegmentFault社区向精通前端的大佬们求助了。问题链接:https://segmentfault.com/q/1010000039059307
以下是波波最终解决该问题的代码片段,供后期其他遇到同类问题的朋友们参考。
1、将“div2img”的压缩包下载后解压至Tp-admin的“/static/plugs/”目录下。
2、在“/static/admin/app.js”中RequireJS的配置中添加html2canvas模块。代码如下:
- paths: {
- // 自定义插件(源码自创建或已修改源码)
- 'admin.plugs': ['plugs'],
- 'admin.listen': ['listen'],
- 'template': ['../plugs/template/template'],
- 'pcasunzips': ['../plugs/jquery/pcasunzips'],
- // 开源插件(未修改源码)
- 'pace': ['../plugs/jquery/pace.min'],
- 'json': ['../plugs/jquery/json2.min'],
- 'layui': ['../plugs/layui/layui'],
- 'jquery': ['../plugs/jquery/jquery.min'],
- 'base64': ['../plugs/jquery/base64.min'],
- 'angular': ['../plugs/angular/angular.min'],
- 'ckeditor': ['../plugs/ckeditor/ckeditor'],
- 'websocket': ['../plugs/socket/websocket'],
- 'bootstrap': ['../plugs/bootstrap/js/bootstrap.min'],
- 'bootstrap.typeahead': ['../plugs/bootstrap/js/bootstrap3-typeahead.min'],
- 'jquery.ztree': ['../plugs/ztree/jquery.ztree.all.min'],
- 'jquery.masonry': ['../plugs/jquery/masonry.min'],
- 'jquery.cookies': ['../plugs/jquery/jquery.cookie'],
- 'dropdown': ['../plugs/dropdown/dropdown'],
- 'treetable': ['../plugs/treetable/treetable'],
- 'html2canvas':['../plugs/div2img/html2canvas.min'],
- 'bluebird':['../plugs/div2img/bluebird'],
- },
- shim: {
- 'layui': {deps: ['jquery']},
- 'ckeditor': {deps: ['jquery']},
- 'websocket': {deps: [_root + '../plugs/socket/swfobject.min.js']},
- 'pcasunzips': {deps: ['jquery']},
- 'admin.plugs': {deps: ['jquery', 'layui']},
- 'admin.listen': {deps: ['jquery', 'jquery.cookies', 'admin.plugs']},
- 'bootstrap': {deps: ['jquery']},
- 'bootstrap.typeahead': {deps: ['bootstrap']},
- 'jquery.ztree': {deps: ['jquery', 'css!' + _root + '../plugs/ztree/zTreeStyle/zTreeStyle.css']},
- 'jquery.cookies': {deps: ['jquery']},
- 'jquery.masonry': {deps: ['jquery']},
- 'html2canvas':{deps:['jquery','bluebird']},
- },
其实主要看path的最后两行和shim的最后一行。其他人也可以参照用RequireJS。官方有文档。
3、网页部分代码。
- <script>
- var screenshot;
- require(['html2canvas'],function (html2canvas){
- this.screenshot = function(){
- var getPixelRatio = function (context) { // 获取设备的PixelRatio
- var backingStore = context.backingStorePixelRatio ||
- context.webkitBackingStorePixelRatio ||
- context.mozBackingStorePixelRatio ||
- context.msBackingStorePixelRatio ||
- context.oBackingStorePixelRatio ||
- context.backingStorePixelRatio || 0.5;
- return (window.devicePixelRatio || 0.5) / backingStore;
- };
- //生成的图片名称
- var imgName = (new Date()).valueOf()+".jpg";
- var shareContent = document.getElementById("printarea");
- var width = shareContent.offsetWidth;
- var height = shareContent.offsetHeight;
- var canvas = document.createElement("canvas");
- var context = canvas.getContext('2d');
- var scale = getPixelRatio(context); //将canvas的容器扩大PixelRatio倍,再将画布缩放,将图像放大PixelRatio倍。
- canvas.width = width * scale;
- canvas.height = height * scale;
- canvas.style.width = width + 'px';
- canvas.style.height = height + 'px';
- context.scale(scale, scale);
- var opts = {
- scale: scale,
- canvas: canvas,
- width: width,
- height: height,
- dpi: window.devicePixelRatio
- };
- html2canvas(shareContent, opts).then(function (canvas) {
- context.imageSmoothingEnabled = false;
- context.webkitImageSmoothingEnabled = false;
- context.msImageSmoothingEnabled = false;
- context.imageSmoothingEnabled = false;
- var dataUrl = canvas.toDataURL('image/jpeg', 1.0);
- dataURIToBlob(imgName, dataUrl, callback);
- });
- }
- })
- var dataURIToBlob = function (imgName, dataURI, callback) {
- var binStr = atob(dataURI.split(',')[1]),
- len = binStr.length,
- arr = new Uint8Array(len);
- for (var i = 0; i < len; i++) {
- arr[i] = binStr.charCodeAt(i);
- }
- callback(imgName, new Blob([arr]));
- }
- var callback = function (imgName, blob) {
- var triggerDownload = $("<a>").attr("href", URL.createObjectURL(blob)).attr("download", imgName).appendTo("body").on("click", function () {
- if (navigator.msSaveBlob) {
- return navigator.msSaveBlob(blob, imgName);
- }
- });
- triggerDownload[0].click();
- triggerDownload.remove();
- };
- </script>
在HTML部分我们只需要写一个保存的按钮就可以了。
- <button class="layui-btn layui-btn-danger" type='button' onclick="screenshot();">保存图片</button>
【总结】
之前一直在写screenshot()函数,所出现的问题主要是当前对象访问不到。因此最后能得以解决就是在页面中先定义一个对象,然后require异步加载模块的时候,将新的函数对象赋值给全局对象。然后“Uncaught ReferenceError: html2canvas is not defined”的问题就解决了,保存图片的功能就实现了。