源码地址:

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. hiho #1485 : hiho字符串(滑动窗口)

    #1485 : hiho字符串 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 如果一个字符串恰好包含2个'h'.1个'i'和1个'o',我们就称这个字符串是hiho字符 ...

  2. SQL server 大量数据导入和系统运行慢的问题

    1.日常排查语句 --当前正在执行的语句 SELECT der.[session_id],der.[blocking_session_id], sp.lastwaittype,sp.hostname, ...

  3. MySQL8.0.18通用版本安装

    环境说明: 系统版本:CentOS release 6.8 (Final) MySQL版本:mysql-8.0.18 内存:63G 空间:8T 1 配置本地yum仓库 这个只需要拷贝一个镜像,然后挂载 ...

  4. C/C++ - 指针 与 引用

    一.指针 1.指针与指针变量的区分 a.指针:指针就是内存编号,也就是内存地址,通俗的讲,指针就是变量的地址. 注1:指针的大小是根据计算机的操作系统而定的,跟变量类型无关 注2:如果是32位的操作系 ...

  5. 洛谷 P2473 [SCOI2008]奖励关 ( 期望DP )

    题目链接 题意 : 中文题.点链接 分析 : 第一道有关概率期望的DP 有个大部分情况下通用的结论 概率正推.期望反推 原因不明.其实是没有查到较好的解释 这题由于有一些取物品的先决条件在这里 而且观 ...

  6. CF 354 div2 B 酒杯金字塔

    B. Pyramid of Glasses time limit per test 1 second memory limit per test 256 megabytes input standar ...

  7. sklearn.model_selection Part 2: Model validation

    1. check_cv() def check_cv(cv=3, y=None, classifier=False): if cv is None: cv = 3 if isinstance(cv, ...

  8. Unit Test in SpringBoot

    此处的Unit Test in SpringBoot 包括: SpringApplication Test Service Test ControllerTest 测试项目结构如下: 代码如下: PO ...

  9. ssm框架文件配置

    1 简介 Spring MVC (web level),采取 MVC 架构,意图取代麻烦的 Servlet 写法,简化 web 层 MyBatis (dao level),意图取代 jdbc 操作数据 ...

  10. shiro所需的依赖

    <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring< ...