使用Canvas裁剪图片

news2024/11/15 12:08:53

使用Canvas裁剪图片

概述

在Web开发中,我们经常需要对图片进行裁剪,以满足不同尺寸需求或者实现图片的局部展示。本篇博客将带您深入了解如何使用Canvas技术来实现图片的裁剪功能。我们将通过一个实例来演示如何利用Canvas绘制图片,并通过蒙层和鼠标交互来进行裁剪操作。让我们开始这个Canvas之旅吧!

项目结构

首先,让我们来看一下项目的结构。我们将使用HTML、CSS和JavaScript来实现Canvas裁剪图片功能,代码如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- 省略部分代码 -->
</head>
<body>
  <!-- 省略部分代码 -->

  <div>
    <input type="file" id="imageFile" accept="image/*" />
  </div>

  <div class="canvas-container">
    <canvas id="can"></canvas>
  </div>

  <div class="canvas2-container">
    <canvas id="can2"></canvas>
  </div>

  <script>
    // JavaScript代码
  </script>

</body>
</html>

我们将使用三个div容器,分别用于显示原图、裁剪后的图和裁剪区域。其中,<input type="file" id="imageFile" accept="image/*" /> 用于上传图片。

初始化Canvas

在JavaScript部分,我们先获取Canvas元素和其上下文,如下所示:

const oContainer = document.querySelector('.canvas-container');
const oContainer2 = document.querySelector('.canvas2-container');
const oImageFile = document.querySelector('#imageFile');
const oCan = document.getElementById('can');
const oCan2 = document.getElementById('can2');
const ctx = oCan.getContext('2d');
const ctx2 = oCan2.getContext('2d');

我们使用querySelector方法获取了.canvas-container.canvas2-container元素作为图片容器,#imageFile为图片上传按钮。接着,我们获取了两个Canvas元素及其上下文。

图片加载与绘制

接下来,我们需要监听图片上传按钮的事件,并在选择图片后将其绘制在Canvas上:

const init = () => {
  bindEvent();
}

function bindEvent () {
  oImageFile.addEventListener('change', handleFileChange, false);
  // ... 其他事件监听 ...
}

function handleFileChange (e) {
  const file = e.target.files[0];
  const reader = new FileReader();

  reader.readAsDataURL(file);
  reader.onload = function (e) {
    const data = e.target.result;
    oImage.src = data;

    oImage.onload = function () {
      const { width, height } = this;
      generateCanvas(oContainer, oCan, width, height);
      ctx.drawImage(oImage, 0, 0, width, height);
      drawImageMask(0, 0, width, height, MASK_OPACITY);
    }
  }
}

function generateCanvas (container, canvas, width, height) {
  container.style.width = width + 'px';
  container.style.height = height + 'px';
  canvas.width = width;
  canvas.height = height;
  container.style.display = 'block';
}

 

bindEvent函数中,我们为图片上传按钮添加了change事件监听,并在选择图片后,通过FileReader读取图片文件,并将其绘制在Canvas上。我们使用drawImage方法将图片绘制在Canvas上,并调用generateCanvas函数,使Canvas的大小与图片保持一致。同时,我们调用drawImageMask函数绘制蒙层,用于裁剪时的显示。

裁剪操作

接下来,我们需要实现裁剪操作。当用户鼠标点击并拖动时,我们可以获取鼠标位置,然后绘制裁剪区域的矩形:

function handleCanvasMouseDown (e) {
  initPos = [ e.offsetX, e.offsetY ];

  oCan.addEventListener('mousemove', handleCanvasMouseMove, false);
  oCan.addEventListener('mouseup', handleCanvasMouseUp, false);
}

function handleCanvasMouseMove (e) {
  const endX = e.offsetX;
  const endY = e.offsetY;
  const [ startX, startY ] = initPos;
  const rectWidth = endX - startX;
  const rectHeight = endY - startY;
  const { width, height } = oCan;

  screenShotData = [ startX, startY, rectWidth, rectHeight ];

  ctx.clearRect(0, 0, width, height);
  drawImageMask(0, 0, width, height, MASK_OPACITY);
  drawScreenShot(width, height, rectWidth, rectHeight);
}

function handleCanvasMouseUp () {
  oCan.removeEventListener('mousemove', handleCanvasMouseMove, false);
  oCan.removeEventListener('mouseup', handleCanvasMouseUp, false);
  drawScreenShotImage(screenShotData);
}

handleCanvasMouseDown函数中,我们记录鼠标点击时的位置。在handleCanvasMouseMove函数中,根据鼠标移动的位置绘制裁剪区域的矩形,并在蒙层上绘制黑色的半透明蒙层。在handleCanvasMouseUp函数中,当鼠标松开后,我们绘制裁剪后的图片。 

图片裁剪

最后,我们需要实现图片的裁剪功能。通过ctx.getImageData方法获取裁剪区域的数据,并绘制在另一个Canvas上:

function drawScreenShot (canWidth, canHeight, rectWidth, rectHeight) {
  ctx.globalCompositeOperation = 'destination-out';
  ctx.fillStyle = '#000';
  ctx.fillRect(...initPos, rectWidth, rectHeight);

  ctx.globalCompositeOperation = 'destination-over';
  ctx.drawImage(oImage, 0, 0, canWidth, canHeight, 0, 0, canWidth, canHeight);
}

function drawScreenShotImage (screenShotData) {
  const data = ctx.getImageData(...screenShotData);
  generateCanvas(oContainer2, oCan2, screenShotData[2], screenShotData[3]);
  ctx2.clearRect(...screenShotData);
  ctx2.putImageData(data, 0, 0);
}

init();

 在drawScreenShot函数中,我们使用globalCompositeOperation属性来控制绘制的方式,先绘制裁剪区域并在蒙层上清除,然后再绘制原图。在drawScreenShotImage函数中,我们使用ctx.getImageData方法获取裁剪区域的数据,然后绘制在第二个Canvas上。

总结

通过以上步骤,我们已经成功实现了使用Canvas来裁剪图片的功能。通过监听鼠标事件,我们可以在图片上绘制裁剪区域,并最终实现图片的裁剪效果。Canvas技术是Web前端开发中不可或缺的一部分,希望本篇博客能够帮助您更好地了解Canvas的应用场景和实践技巧。感谢您的阅读! 

 

 学习自B站up——前端小野森森

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/832639.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二叉树的相关题目

目录 1、根据二叉树创建字符串 2、二叉树的层序遍历 3、二叉树的最近公共祖先 4、搜索二叉树与双向链表 5、从前序与中序遍历序列构造二叉树 6、 从中序与后序遍历序列构造二叉树 7、二叉树的前序遍历&#xff08;非递归实现&#xff09; 8、二叉树的中序遍历&#xff08…

宋浩高等数学笔记(十)重积分

本章更新第10章重积分&#xff0c;关于三重积分的应用部分暂时略过&#xff0c;本部分在考察的时候不会很难&#xff0c;困难在于对重积分本质的理解&#xff0c;以及极坐标下相关公式的计算。类比普通的定积分&#xff0c;如果对一个宽度不均匀的函数&#xff0c;求积分分后相…

工厂模式详解与应用场景

摘要&#xff1a; 工厂模式是一种常见的设计模式&#xff0c;它可以帮助我们在面向对象的程序设计中更好地组织和管理对象的创建过程。本文将详细介绍工厂模式的概念、三种常见的工厂模式应用场景&#xff0c;并提供高质量的C代码示例&#xff0c;旨在帮助初学者更好地理解和应…

【Spring Boot系列】-Spring Boot过滤器Filter

【Spring Boot系列】-Spring Boot过滤器Filter 文章目录 【Spring Boot系列】-Spring Boot过滤器Filter一、概述二、Filter&#xff08;过滤器&#xff09;数据流程三、Spring Boot 过滤器生命周期四、使用注解方式实现过滤器(WebFilter)4.1. 在springboot 启动类添加该注解Ser…

JAVA大神必备,IDEA自带的JVM监控神器

前言 开发阶段实时监测&#xff0c;自己的JVM信息&#xff0c;实时可视化 Hotspot JVM 垃圾回收监控工具, 支持查看本地和远程JVM进程, 支持G1 and ZGC算法。 插件安装 在线安装 IntelliJ IDEA 可通过在线安装的方式&#xff0c;安装插件 JDK VisualGC&#xff0c;安装步骤: …

过程:从虚拟机上添加 git 并成功提交到 GitLab 的全过程

Ⅰ、准备工作&#xff1a; 1、Git 查看&#xff1a; 其一、命令&#xff1a;git --version // 此时就能在虚拟机环境下看到 git 的版本为: git version 2.41.0 其二、如何在虚拟机上安装 git &#xff1a; A、命令 &#xff1a; sudo apt-get install git B、然后再输入虚…

JavaScript |(三)内建对象 | 数组 | string对象 | 尚硅谷JavaScript基础实战

学习来源&#xff1a;尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 文章目录 &#x1f4da;数组&#x1f407;数组介绍⭐️数组&#xff08;Array&#xff09;⭐️基本操作⭐️数组的字面量 &#x1f407;数组中的常用方法⭐️push()⭐️pop()⭐️unshift()⭐️shif…

微信小程序wx.getlocation接口权限申请总结

先附上申请通过截图 插播内容&#xff1a;可代开通&#xff0c;保证通过。wx.getLocation接口&#xff08;获取当前的地址位置&#xff09; qq&#xff1a; 308205428 如何申请 当申请微信小程序的wx.getLocation接口权限时&#xff0c;你可以…

yolov8-制作数据集,数据集格式转换(yolo格式-voc格式)附完整代码

yolo训练时可使用的数据集格式为yolo格式以及voc格式&#xff0c; voc格式的数据集在训练时需要先转换为yolo格式&#xff0c;然后根据自己的数据集的位置更改yaml配置文件的文件路径即可。基于目前对Yolo系列训练模型的讲解已经很全面&#xff0c;所以本文主要讲解yolo数据集与…

记录 FreeRTOS 信号量 的简单用法

FreeRTOS 信号量 最简单的应用场景是 两个任务间的同步 &#xff0c;这里以 二值信号量 Binary Semaphore为例 用法 &#xff1a; 1&#xff0c;定义与 创建 /* Definitions for myBinarySem01 */ osSemaphoreId_t myBinarySem01Handle; const osSemaphoreAttr_t myBinarySe…

c++类与对象详解

c类与对象详解 对象类方法自定义类型类的特性this类的六个默认成员函数static成员友元内部类 对象 在C中&#xff0c;对象是类的实例。定义对象的语法为&#xff1a; <class_name> object_name;其中&#xff0c;class_name 是定义类时指定的类名&#xff0c;object_nam…

二分查找【Java算法】

文章目录 1. 概念2. 思路3. 代码实现 1. 概念 二分查找又叫折半查找&#xff0c;要求待查找的序列有序&#xff0c;每次取中间位置的值与待查关键字比较&#xff0c;如果待查关键字比中间位置的值小&#xff0c;则在前半部分循环这个查找的过程&#xff0c;反之&#xff0c;在后…

7_分类算法—逻辑回归

文章目录 逻辑回归&#xff1a;1 Logistic回归&#xff08;二分类问题&#xff09;1.1 sigmoid函数1.2 Logistic回归及似然函数&#xff08;求解&#xff09;1.3 θ参数求解1.4 Logistic回归损失函数1.5 LogisticRegression总结 2 Softmax回归&#xff08;多分类问题&#xff0…

单元测试之 - Review一个微服务的单元测试

这里以github上一个microservice的demo代码为例&#xff0c;来看看如何为一个完整的服务编写单元测试。具体代码如下所示&#xff0c;我们重点查看一下catalog和customer&#xff0c;order中的单元测试有哪些。 首先来看catalog服务的单元测试,这个服务下面主要编写了CatalogWe…

时序数据异常检测算法

引言 异常检测的场景很多&#xff0c;例如&#xff1a;硬件的故障检测、流量的异常点的检测等场景。针对时间序列类数据的异常检测算法也有很多&#xff0c;业界比较流行的比如普通的统计学习方法–3σ原则和箱线图识别数据离群点&#xff0c;它利用检测点偏移量来检测出异常。…

Michael.W基于Foundry精读Openzeppelin第19期——EnumerableSet.sol

Michael.W基于Foundry精读Openzeppelin第19期——EnumerableSet.sol 0. 版本0.1 EnumerableSet.sol 1. 目标合约2. 代码精读2.1 结构体Set2.1.1 _contains(Set storage set, bytes32 value) && _length(Set storage set) && _at(Set storage set, uint256 inde…

Linux的基本指令(2)

指令1&#xff1a;man 作用&#xff1a;可以查询linux指令语法内容。 格式&#xff1a; man 指令 安装man指令&#xff1a; yum install -y man-pages 例如&#xff1a; 查询 指令 ls 的语法内容。 man ls 查询 fork 指令的语法内容。 man fork 在man中存在9个手册&…

2023年08月编程语言流行度排名

点击查看最新编程语言流行度排名&#xff08;每月更新&#xff09; 2023年08月编程语言流行度排名 编程语言流行度排名是通过分析在谷歌上搜索语言教程的频率而创建的 一门语言教程被搜索的次数越多&#xff0c;大家就会认为该语言越受欢迎。这是一个领先指标。原始数据来自…

word转pdf怎么转?几种常用方法分享

word转pdf怎么转&#xff1f;在日常工作和学习中&#xff0c;将Word文档转换为PDF格式是一项必要的任务。不仅可以保证文档的格式不变&#xff0c;还可以防止文档被他人篡改。但是&#xff0c;Word文档并不是所有人都能够轻松打开和编辑的&#xff0c;而PDF文件则可以在各种设备…

Python---Matplotlib

文章目录 1.什么是matplotlib?2.实现一个简单的matplotlib绘图3.matplotlib图像结构4.matplotlib基础绘图多个坐标系显示— plt.subplots(面向对象的画图方法) 5.常见图形种类 1.什么是matplotlib? Matplotlib是一个用于绘制数据可视化图形的Python库。它是一个广泛使用的数…