记录--使用 JS 实现基本的截图功能

这篇具有很好参考价值的文章主要介绍了记录--使用 JS 实现基本的截图功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--使用 JS 实现基本的截图功能

思路分析

在开始动手之前,分析一下整个功能的实现过程:

  1. 根据图片大小创建 canvas1 画布,并将原图片直接定位在 canvas1 上;

  2. 在画布上添加一个蒙层,以区分当前 canvas 图像是被裁剪的原图像;

  3. 在蒙层上方,对裁剪区域(鼠标移动形成的矩形范围)再次进行图像绘制;

  4. 获取裁剪区域的数据,并将该数据定位到另一个 canvas 画布上。

实现过程

准备工作

首先,编写所需的 HTML 结构并获取对应元素。

<body>
  <!-- 上传文件 -->
  <input type="file" id="imageFile" accept="image/*">
  <!-- 保存被裁剪的原图像,初始样式需要设置 display: none -->
  <div class="canvasContainer1">
    <canvas id="canvas1"></canvas>
  </div>
  <!-- 保存裁剪区域的图像,初始样式需要设置 display: none -->
  <div class="canvasContainer2">
    <canvas id="canvas2"></canvas>
  </div>
</body>

<script>
const imageFile = document.querySelector('#imageFile');
const canvasContainer1 = document.querySelector('.canvasContainer1');
const canvasContainer2 = document.querySelector('.canvasContainer2');
const canvas1 = document.querySelector('#canvas1');
const canvas2 = document.querySelector('#canvas2');
const ctx = canvas1.getContext('2d');
const ctx2 = canvas2.getContext('2d');

const imageBox = new Image(); // 创建一个存放图片的容器
</script>

绘制原图像

我们需要监听 input 元素的 change 事件,以获取上传图片的相关参数,这里主要是为了获取图片的宽度和高度。

我们创建一个 FileReader() 对象并监听其 load 事件。load 事件在读取操作成功后立刻执行,在这个方法中我们就可以获取图片的宽高。

function init() {
  imageFile.addEventListener('change', handleFileChange, false); // 监听图片上传事件。
}

function handleFileChange(e) {
  const imgFile = e.target.files[0]; // 获取上传的图片对象。

  const reader = new FileReader();
  reader.onload = function(e) {
    const imgSrc = e.target.result; // 图片文件的 base64 编码格式。
    imageBox.src = imgSrc; // 把图片放入 img 容器。

    // 等图片加载完成后,获取图片的宽高。
    imageBox.onload = function () {
      const imgWidth = this.width, imgHeight = this.height;
      console.log(imgWidth, imgHeight);
    }
  }
  if (imgFile) {
    reader.readAsDataURL(imgFile); // 读取图片文件,读取完成才能获取 result 属性。
  }
}

init();

记录--使用 JS 实现基本的截图功能

此时还没有图片,我们创建一个自适应图片大小的 canvas1 画布,并使用 drawImage() 方法将上传的图片直接定位到 canvas1 当中。
function handleFileChange(e) {
  const imgFile = e.target.files[0]; // 获取上传的图片对象。

  const reader = new FileReader();
  reader.onload = function (e) {
    const imgSrc = e.target.result; // 图片的 base64 编码。
    imageBox.src = imgSrc; // 把上传的图像放入 img 容器。

    // 图片加载完毕后执行
    imageBox.onload = function () {
      // 获取图片的宽高。
      const imgWidth = this.width, imgHeight = this.height;
      console.log(imgWidth, imgHeight);
      
      // 创建 canvas 画布并绘制图片。
      generateCanvas(canvasContainer1, canvas1, imgWidth, imgHeight);
      ctx.drawImage(imageBox, 0, 0, imgWidth, imgHeight);
    }
  }
  if (imgFile) {
    reader.readAsDataURL(imgFile); // 将当前file读取成DataURL
  }
}

// 根据 width 和 height 创建 canvas 画布。
function generateCanvas(container, canvas, width, height) {
  container.width = width + 'px';
  container.height = height + 'px';
  canvas.width = width;
  canvas.height = height;
  container.style.display = 'block'; // 显示 canvas 区域。
}

记录--使用 JS 实现基本的截图功能

可以看到原图像已经成功被绘制,接下来就可以开始动态绘制截图区域了。

绘制截图区域

在这个过程中,我们需要分别监听 imageBox 容器(原图像)上的 mousedownmousemovemouseup 事件,这些事件的作用如下:

  • mousedown 事件:记录开始截图的位置,并开始监听 mousemovemouseup 事件。
  • mousemove 事件:监听鼠标的偏移量,以计算裁剪区域的宽度和高度。
  • mouseup 事件:截图结束,注销监听 mousedownmousemove 事件,并绘制裁剪区域。
let startPosition = []; // 记录鼠标点击(开始截图)的位置。
let screenshotData = []; // 保存截取部分的相关信息。

function init() {
  // 监听鼠标点击事件。
  canvas1.addEventListener('mousedown', handleMouseDown, false);
}

// 记录鼠标点击(开始截图)的位置,并监听相关事件。
function handleMouseDown(e) {
  startPosition = [e.offsetX, e.offsetY];

  canvas1.addEventListener('mousemove', handleMouseMove, false);
  canvas1.addEventListener('mouseup', handleMouseUp, false);
}

// 监听鼠标的偏移量,以计算裁剪区域的宽度和高度。
function handleMouseMove(e) {
  // 获取裁剪区域的宽度和高度。
  const { offsetX, offsetY } = e;
  const [startX, startY] = startPosition;
  const [rectWidth, rectHeight] = [offsetX - startX, offsetY - startY];
  console.log('rect', rectWidth, rectHeight);
  
  // 保存裁剪区域的相关信息。
  screenshotData = [startX, startY, rectWidth, rectHeight];
}

// 注销监听事件等后续操作。
function handleMouseUp() {
  canvas1.removeEventListener('mousemove', handleMouseMove, false);
  canvas1.removeEventListener('mouseup', handleMouseUp, false);
}

在 handleMouseMove 函数中,我们已经获取了裁剪区域的宽高,也就是生成截图的宽高。

接下来,我们需要在原图像上展示出我们所裁剪的区域,也就是这个效果:

记录--使用 JS 实现基本的截图功能

可以看到,原图像的上方、裁剪区域下方会覆盖一层半透明黑色蒙层,它的作用是区分原图层和裁剪部分图层。所以我们需要在绘制截图区域之前,添加一层蒙层。

注意,在已有内容的 canvas 画布上进行再次绘制之前,需要先清除整个画布的内容。 这里通过 clearRect() 方法清除 canvas1 画布上的所有内容,并添加蒙层。

我们继续来补充 handleMouseMovehandleMouseUp 函数中的逻辑:

const MASKER_OPACITY = 0.4;

function handleMouseMove(e) {
  // 获取裁剪区域的宽度和高度。
  const { offsetX, offsetY } = e;
  const [startX, startY] = startPosition;
  const [rectWidth, rectHeight] = [offsetX - startX, offsetY - startY];
  console.log('rect', rectWidth, rectHeight);
  // 保存裁剪区域的相关信息。
  screenshotData = [startX, startY, rectWidth, rectHeight];
  // 再次绘制前,清理 canvas1 画布上的内容。
  const { width, height } = canvas1;
  ctx.clearRect(0, 0, width, height);
  // 在 canvas1 画布上绘制蒙层。
  drawImageMasker(0, 0, width, height, MASKER_OPACITY);
  // 绘制截图区域。
  drawScreenShot(width, height, rectWidth, rectHeight);
}

// ...

// 绘制图片蒙层,填充范围和颜色,以便区分原图层和裁剪部分图层。
function drawImageMasker(x, y, width, height, opacity) {
  ctx.fillStyle = `rgba(0, 0, 0, ${opacity})`;
  ctx.fillRect(0, 0, width, height);
}

// 绘制裁剪的矩形区域。
function drawScreenShot(canWidth, canHeight, rectWidth, rectHeight) {
  // 在源图像外绘制新图像,只有源图像外的目标图像部分会被显示,源图像是透明的。
  ctx.globalCompositeOperation = 'destination-out';
  ctx.fillStyle = '#2c2c2c';
  ctx.fillRect(...startPosition, rectWidth, rectHeight);

  // 在现有画布上绘制新的图形。
  ctx.globalCompositeOperation = 'destination-over';
  ctx.drawImage(imageBox, 0, 0, canWidth, canHeight, 0, 0, canWidth, canHeight);
}

然后,当我们放开鼠标(结束截图动作)时,除了注销对 mousedownmousemove 事件的监听,还需要将所得的裁剪区域的图像放入另一个 canvas 中。

在绘制新图像的过程中,我们需要使用以下方法:

  • getImageData():读取 canvas 上的内容,返回一个 ImageData 对象,包含了每个像素的信息。
  • putImageData():将 ImagaData 对象的数据放入 canvas 中,覆盖 canvas 中的已有图像。
function handleMouseUp() {
  canvas1.removeEventListener('mousemove', handleMouseMove, false);
  canvas1.removeEventListener('mouseup', handleMouseUp, false);
  // 开始绘制截图区域图片。
  drawScreenshotImage(screenshotData);
  // 如果裁剪得到新图像后,不希望保留原图像,可以设置以下属性。
  // canvasContainer1.style.display = 'none';
}

// 在新容器 canvas2 上绘制新图像。
function drawScreenshotImage(screenshotData) {
  // 获取 canvas1 的数据。
  const data = ctx.getImageData(...screenshotData);
  // 创建 canvas2 画布。
  generateCanvas(canvasContainer2, canvas2, screenshotData[2], screenshotData[3]);
  // 每次绘制前,都先进行清除操作。
  ctx2.clearRect(...screenshotData);
  // 将 canvas1 的数据放入 canvas2 中。
  ctx2.putImageData(data, 0, 0);
}
经过以上步骤,就可以实现我们所需的效果

记录--使用 JS 实现基本的截图功能

本文转载于:

https://juejin.cn/post/7264920437242036284

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--使用 JS 实现基本的截图功能文章来源地址https://www.toymoban.com/news/detail-635549.html

到了这里,关于记录--使用 JS 实现基本的截图功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 记录--vue3 + mark.js | 实现文字标注功能

    1、监听鼠标抬起事件,通过 window.getSelection() 方法获取鼠标用户选择的文本范围或光标的当前位置。 2、通过 选中的文字长度是否大于0 或 window.getSelection().isCollapsed (返回一个布尔值用于描述选区的起始点和终止点是否位于一个位置,即是否框选了)来判断是否展示标签选择的

    2024年02月08日
    浏览(37)
  • 网易云音乐开发--search模块基本功能实现(除历史记录模块)

    老样子搭建一个search搜索页面  还有一块没有实现,那就是让输入框默认的文本变换颜色  微信小程序: input输入框placeholder样式的修改_微信小程序placeholder样式_酷伊奥的博客-CSDN博客  百度搜索了一下,找到了这个大佬的解决方案。很nice 查看文档 网易云音乐 NodeJS 版 API (b

    2024年02月06日
    浏览(68)
  • 原生JS实现视频截图

    要用原生js实现视频截图,可以利用 canvas 的绘图功能 ctx.drawImage ,只需要获取到视频标签,就可以通过 drawImage 把视频当前帧图像绘制在canvas画布上。 接下来,需要把画布转化为图片,canvas提供了两个2D转换为图片的方法: canvas.toDataURL() 和 canvas.toBlob() canvas.toDataURL(mimeType,

    2024年02月05日
    浏览(33)
  • MFC 截图功能实现(2)

    上篇文章里面所用的截图是点击按钮就截取当前打开的界面,链接: MFC 截图功能实现_春蕾夏荷_728297725的博客-CSDN博客 这里所用的截图是可以选中区域,另存为目录等的操作: 效果: 选中区域: 菜单: 代码调用实例: #include \\\"ScreenCapture.h\\\" #include string using namespace std; void

    2024年02月11日
    浏览(28)
  • 利用Selenium轻松实现网页截图功能

    引言 对于初涉 Python 编程的开发者来说,自动化工具的使用可以极大地提升工作效率。在众多Python库中, Selenium 是一个强大且易用的 Web 浏览器自动化工具,它不仅可以模拟用户行为进行页面交互,还能方便地实现网页截图功能。本文将一步步教大家如何借助Selenium和ChromeD

    2024年04月10日
    浏览(39)
  • Electron 应用实现截图并编辑功能

    Electron 应用如何实现截屏功能,有两种思路,作为一个框架是否可以通过框架实现截屏,另一种就是 javaScript 结合 html 中画布功能实现截屏。 在初步思考之后,本文优先探索使用 Electron 实现截屏功能。作为一个成熟的框架,如果能够完成截屏,那自然是已经考虑了各种会出

    2024年02月13日
    浏览(34)
  • 记录--手把手教你,用electron实现截图软件

    因为我们日常开发项目的时候,需要和同事对接 api 和 文档 还有 UI图 ,所以有时候要同时打开多个窗口,并在多个窗口中切换,来选择自己要的信息,如果 api 和 文档 不多的情况还好,但是有时候就是要做大量的页面,为了提升效率我决定自己做一个截图工具,并把自己要

    2024年02月12日
    浏览(53)
  • 记录使用EasyExcel实现导出功能

            之前项目中用的都是传统的POI格式导出。这个东西看起来很拉跨,而且如果数据量大的话还容易直接接口超时卡死,试过设置超时时间也没啥卵用。后来听说了阿里巴巴的EasyExcel,就小用了一下。反正目前来说用的还算舒服。 传统POI方式导出: 一大堆字段都扔这里

    2024年02月06日
    浏览(47)
  • flutter开发实战-RepaintBoundary实现Widget截图功能

    flutter开发实战-RepaintBoundary实现Widget截图功能 在开发中,遇到需要使用截图,像iOS可以截图UIView获取到UIImage,在flutter中可以使用RepaintBoundary实现截图功能 相机拍摄的图片: RepaintBoundary截图后的图片 RepaintBoundary是绘制边界。 如果CustomPaint有子节点,为了避免子节点不必要的

    2024年02月15日
    浏览(35)
  • 自适应插件autofit.js使用(这里演示vue项目)

    这个插件使用以后,页面会根据浏览器的缩放自适应的改变宽高 这里演示的是vue3项目,其他项目也可类似去写 如果要在整个项目做自适应,将配置配到App.vue,如果只要单个页面自适应,只需要配置当前页面即可 App.vue配置如下(单个页面自适应也是如此配置) 以下代码三步走

    2024年02月04日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包