源码地址:

1.1 确定截图选取范围

用户在开始截图后,需要在页面上选取一个截图范围,并且可以直观的看到,类似如下效果:

image

我们的选取范围就是鼠标开始按下的那个点到鼠标拖动然后松开的那个点之间所组成的矩形。
为了能直观看到我们选取的范围,我们将这个矩形框随着鼠标拖动给画出来,利用canvas即可,为了方便绘制,这里使用了jcanvas

1.2 将选取范围内的网页生成截图

如何将选取框范围内的网页内容变成图像呢,我们可以使用html2canvas.jshtml2canvas可以将页面中的DOM元素生成canvas,是将网页生成图像的非常好的一个选择。使用非常简单:

html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);
});

上面的代码就可以将body转成canvas。html2canvas使用到了Promise,得确保你的浏览器支持。
html2canvas虽然可以将指定元素转成canvas,有了canvas我们就可以轻易的生成图像。但是并不能满足将选取框范围内的内容转成canvas的需求,选取框内可能有多个元素,并且可能是多个不完整的元素,元素只有部分。
我们可以先将body整个转成canvas,然后将这个canvas进行剪裁(或生成image后剪裁),将选取框范围的内容剪裁出来。很简单,使用drawImage即可。
drawImage 方法允许在 canvas 中插入其他图像( img 和 canvas 元素) 。drawImage函数有三种函数原型:

drawImage(image, dx, dy)
drawImage(image, dx, dy, dw, dh)
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)

2 打印

打印使用 jquery.print.jsjquery.print.js是一款可以实现网页打印的插件,实用的方法非常简单。类似html2canvas可以转换元素为canvas这样,它可以选取元素进行部分打印。

$(".print").click(function(){
$(".need_print").print();
});

2 完整实现

创建screenshotsPrint.js,内容如下:

/**
* 默认画笔线宽
* @type {number}
*/
var defaultStrokeWidth = 1; //画矩形选取框的线宽 /**
* 选取划线的canvasExt
* @type {{drawRect: canvasExt.drawRect}}
*/
var canvasExt = {
/**
* 画矩形
* @param canvasId canvasId
* @param penColor 画笔颜色
* @param strokeWidth 线宽
*/
drawRect: function (canvasId, penColor, strokeWidth) {
var that = this; that.penColor = penColor;
that.penWidth = strokeWidth;
var canvas = document.getElementById(canvasId);
//canvas 的矩形框
var canvasRect = canvas.getBoundingClientRect();
//canvas 矩形框的左上角坐标
var canvasLeft = canvasRect.left;
var canvasTop = canvasRect.top; // 要画的矩形的起点 xy
var x = 0;
var y = 0; //鼠标点击按下事件,画图准备
canvas.onmousedown = function(e) { //设置画笔颜色和宽度
var color = that.penColor;
var penWidth = that.penWidth;
// 确定起点
x = e.clientX - canvasLeft;
y = e.clientY - canvasTop;
// 添加layer
$("#"+canvasId).addLayer({
type: 'rectangle',
strokeStyle: color,
strokeWidth: penWidth,
name:'areaLayer',
fromCenter: false,
x: x, y: y,
width: 1,
height: 1
});
// 绘制
$("#"+canvasId).drawLayers();
$("#"+canvasId).saveCanvas(); //鼠标移动事件,画图
canvas.onmousemove = function(e){ // 要画的矩形的宽高
var width = e.clientX-canvasLeft - x;
var height = e.clientY-canvasTop - y; // 清除之前画的
$("#"+canvasId).removeLayer('areaLayer'); $("#"+canvasId).addLayer({
type: 'rectangle',
strokeStyle: color,
strokeWidth: penWidth,
name:'areaLayer',
fromCenter: false,
x: x, y: y,
width: width,
height: height
}); $("#"+canvasId).drawLayers();
}
};
//鼠标抬起
canvas.onmouseup=function(e){ var color = that.penColor;
var penWidth = that.penWidth; canvas.onmousemove = null; var width = e.clientX - canvasLeft - x;
var height = e.clientY- canvasTop - y; $("#"+canvasId).removeLayer('areaLayer'); $("#"+canvasId).addLayer({
type: 'rectangle',
strokeStyle: color,
strokeWidth: penWidth,
name:'areaLayer',
fromCenter: false,
x: x, y: y,
width: width,
height: height
}); $("#"+canvasId).drawLayers();
$("#"+canvasId).saveCanvas(); // 把body转成canvas
html2canvas(document.body, {
scale: 1,
// allowTaint: true,
useCORS: true //跨域使用
}).then(canvas => {
var capture_x, capture_y
if (width > 0) {
//从左往右画
capture_x = x + that.penWidth
}else {
//从右往左画
capture_x = x + width + that.penWidth
}
if (height > 0) {
//从上往下画
capture_y = y + that.penWidth
}else {
//从下往上画
capture_y = y + height + that.penWidth
}
printClip(canvas, capture_x, capture_y, Math.abs(width), Math.abs(height))
});
// 移除画的选取框
$("#"+canvasId).removeLayer('areaLayer');
// 隐藏用于华画取框的canvas
$("#"+canvasId).hide()
}
}
}; /**
* 选取截屏
* @param canvasId
*/
function clipScreenshots(canvasId){
canvasExt.drawRect(canvasId, "red", defaultStrokeWidth);
} /**
* 打印截取区域
* @param canvas 截取的canvas
* @param capture_x 截取的起点x
* @param capture_y 截取的起点y
* @param capture_width 截取的起点宽
* @param capture_height 截取的起点高
*/
function printClip(canvas, capture_x, capture_y, capture_width, capture_height) {
// 创建一个用于截取的canvas
var clipCanvas = document.createElement('canvas')
clipCanvas.width = capture_width
clipCanvas.height = capture_height
// 截取
clipCanvas.getContext('2d').drawImage(canvas, capture_x, capture_y, capture_width, capture_height, 0, 0, capture_width, capture_height)
var clipImgBase64 = clipCanvas.toDataURL()
// 生成图片
var clipImg = new Image()
clipImg.src = clipImgBase64
var con = confirm('打印截图吗?取消则保存截图')
if (con) {
$(clipImg).print()
}else {
downloadIamge(clipImgBase64)
}
} /**
* 下载保存图片
* @param imgUrl 图片地址
*/
function downloadIamge(imgUrl) {
// 图片保存有很多方式,这里使用了一种投机的简单方法。
// 生成一个a元素
var a = document.createElement('a')
// 创建一个单击事件
var event = new MouseEvent('click')
// 生成文件名称
var timestamp = new Date().getTime();
var name = imgUrl.substring(22, 30) + timestamp + '.png';
a.download = name
// 将生成的URL设置为a.href属性
a.href = imgUrl;
// 触发a的单击事件 开始下载
a.dispatchEvent(event);
}

demo.html中进行使用

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试截取保存或打印</title>
<script type="text/javascript" src="libs/jquery-2.1.0.js"></script>
<script type="text/javascript" src="libs/html2canvas.js"></script>
<script type="text/javascript" src="libs/jQuery.print.js"></script>
<script type="text/javascript" src="libs/jcanvas.min.js"></script>
<script type="text/javascript" src="js/screenshotsPrint.js"></script>
<style>
body, html {
width: 100%;
height: 100%;
}
.print {
position: relative;
z-index: 100;
}
h1 {
color: orangered;
}
h2 {
color: darkblue;
}
h2 {
color: forestgreen;
}
#bg_canvas {
position: absolute;
z-index: 500;
left: 0;
top: 0;
}
</style>
</head>
<body>
<button class="print">开始截图</button>
<div>
<h1>哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈</h1>
<h2>嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿</h2>
<h3>呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵呵</h3>
<br/>
<p>这是一张跨域图片</p>
<img src="http://p7.qhimg.com/t01ceede0272d4b5a8b.png" alt="来个跨区的图片">
</div>
<!-- 用于画选取框的canvas -->
<canvas id="bg_canvas" width="100%" height="100%" />
<script>
$(function(){
var clientWidth = document.documentElement.clientWidth || document.body.clientWidth
var clientHeight = document.documentElement.clientHeight || document.body.clientHeight
// 更新canvas宽高
$("#bg_canvas").attr("width", clientWidth);
$("#bg_canvas").attr("height", clientHeight);
$("#bg_canvas").hide();
$(".print").click(function(){
$("#bg_canvas").show()
alert('现在你可以使用鼠标拖拽选取打印区域,松开后完成')
//调用选取截屏
clipScreenshots("bg_canvas");
}); });
</script>
</body>
</html>

作者:石文文的简书
链接:https://www.jianshu.com/p/8c43576bdbe3
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

JS实现网页选取截屏 保存+打印 功能(转)的更多相关文章

  1. js利用clipboardData在网页中实现截屏粘贴的功能

    目前仅有高版本的 Chrome 浏览器支持这样直接粘贴,其他浏览器目前为止还无法粘贴,不过火狐和ie11浏览器在可编辑的div中能够粘贴截图的图片也是base64位和Chrome利用clipboard ...

  2. 利用 clipboardData 在网页中实现截屏粘贴的功能

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  3. android截屏:保存一个view的内容为图片并存放到SD卡

    项目中偶尔会用到截屏分享,于是就有了下面这个截屏的方法~ 下面得saveImage()方法就是保存当前Activity对应的屏幕所有内容的截屏保存. private void saveImage() ...

  4. iOS截屏保存至相册

    #pragma mark 截屏并保存至相册 -(void)screenShotsComplete:(void(^)(UIImage * img)) complete { CGSize imageSiz ...

  5. Unity3d 截屏保存到相册,并且刷新相册

    要做一个截图的功能,并且玩家可以在相册中看到. 做的时候遇到了三个问题: 1.unity自带的截图API,Application.CaptureScreenshot在Android上不生效 2.图片保 ...

  6. IOS 截屏(保存到相册中)

    @interface NJViewController () /** * 点击截屏按钮 */ - (IBAction)captureView:(UIButton *)sender; /** * 白色v ...

  7. js 将网页生成为html保存访问

    2012-04-03 今天实现了一个需求,主题是将浏览中的网页生成html保存起来,记录访问url,挂在公司网站上做案例.     首先忙活了N久的是去搜索生成html的js函数.   什么IE自带的 ...

  8. 使用adb命令对手机进行截屏保存到电脑,SDCard

    adb shell /system/bin/screencap -p /sdcard/screenshot.png(保存到SDCard) adb pull /sdcard/screenshot.png ...

  9. vba截屏保存

    Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVa ...

随机推荐

  1. golang之基本数据类型

    目录 一.golang之基本数据类型 1. 整型 (1)有符号(范围是负数.0和正数) (2)无符号(范围是0和正数) (3)特殊整型 (4)数字字面量语法 2. 浮点型 3. 复数类型 4. 布尔类 ...

  2. 浮点数的存储、类型转换知识点(面宝P34)

    以float a=1.0f为例: (int)a实际上是以浮点数a为参数构造了一个整型数,该整数的值是1: (int&)a则是告诉编译器将a当作整数看(并没有做任何实质上的转换),即读a的内存时 ...

  3. java8 base64编码和解码

    package com.oy; import java.nio.charset.StandardCharsets; import java.util.Base64; import org.junit. ...

  4. 【WC2016】论战捆竹竿

    已经快三周了啊--终于把挖的坑填了-- 首先显然是把除了自身的所有border拿出来,即做 \(\left\{ n - b_1, n - b_2, \dots, n - b_k, n \right\} ...

  5. Android 造炫目的圆形菜单 秒秒钟高仿建行圆形菜单

    1.概述 今天打开建行看存款,一看伤心欲绝,再看:我擦,这个圆形菜单挺炫.于是,为了掩盖我悲痛的心情,我决定是实现这个效果.好了,其实还有个原因,记得我初学android那会我做的应用被鄙视了,说我的 ...

  6. 关于int,bool,str

    今日主要内容 基本数据类型(int,bool,str) 1.基本数据数据类型: int 整数 str 字符串. 一般不存放大量的数据 bool 布尔值. 用来判断. True, False list ...

  7. linux工作常用命令

    修改文件后缀 如 将文件application.properties.sample改为application.properties,格式 mv  文件名称.{改前后缀,修改后的目标后缀} 定位到修改文 ...

  8. Java 里volatile关键字是什么意思啊?如何使用呢?

    一旦一个并发共享变量(类的成员变量.静态成员变量)被 volatile 关键字修饰就具备了可见性(即一个线程修改了一个变量的值对于另一个线程来说是立即可见的)和有序性(即禁止进行指令重排序),实质是在 ...

  9. jsvnadmin访问一直登陆 找不到用户

    报错:AH01618: user zhangsan not found: /svn/hangzhi 在svnadmin控制台上将用户分好组,不然即使有账户也登不上

  10. 关于Tomcat配置相关总结

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...