当前位置: 首页 > news >正文

使用Canvas裁剪图片

使用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——前端小野森森

相关文章:

使用Canvas裁剪图片

使用Canvas裁剪图片 概述 在Web开发中&#xff0c;我们经常需要对图片进行裁剪&#xff0c;以满足不同尺寸需求或者实现图片的局部展示。本篇博客将带您深入了解如何使用Canvas技术来实现图片的裁剪功能。我们将通过一个实例来演示如何利用Canvas绘制图片&#xff0c;并通过蒙…...

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

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

势能线段树

目录 简单介绍 题目 1. 上帝造题的七分钟 2 2.SUM and REPLACE 3. And RMQ 总结 简单介绍 题目 1. 上帝造题的七分钟 2 链接&#xff1a;https://www.luogu.com.cn/problem/P4145 维护两种操作 1.区间开根号(下取整) 2.区间和询问 显然无法通过懒标记来计算区间开根号…...

【phaser微信抖音小游戏开发004】往画布上增加文本以及文本的操作

我们在states中创建st004.js的类&#xff0c;或者将states中的index.js直接重命名为st004.js&#xff0c;把里面的类名也修改为st004.如下图 在main.js中&#xff0c;引入st004,并设置启用的state为st004。如下图 接下来到states/st004里面&#xff0c;在create里面将文本修改一…...

【1.4】Java微服务:服务注册和调用(Eureka和Ribbon实现)

✅作者简介&#xff1a;大家好&#xff0c;我是 Meteors., 向往着更加简洁高效的代码写法与编程方式&#xff0c;持续分享Java技术内容。 &#x1f34e;个人主页&#xff1a;Meteors.的博客 &#x1f49e;当前专栏&#xff1a; 微服务 ✨特色专栏&#xff1a; 知识分享 &#x…...

QT中使用ffmpeg的api进行视频的播放

在了解ffmpeg使用api进行视频的播放之前&#xff0c;我们首先了解一下视频的播放流程。 一、视频的播放流程 首先是我们最常见的视频文件&#xff0c;在播放流程中首先是要打开视频文件&#xff0c;将视频文件中的数据进行解封装&#xff0c;之后再将解封装之后的视频进行解码…...

使用idea实现git操作大全(在项目开发中遇到的实际情况

使用idea实现git操作大全&#xff08;在项目开发中遇到的实际情况&#xff09; 1.安装git插件2.在开发中切记拉一个自己的分支 1.安装git插件 2.在开发中切记拉一个自己的分支 选中需要拉的分支&#xff0c;右键该分支&#xff0c;选中new breach from “分支”&#xff0c;点…...

SQL面试题:一个优化案例

问题描述 假如存在以下两个表&#xff1a; CREATE TABLE customer ( C_CUSTKEY int NOT NULL, C_NAME varchar(25) NOT NULL, C_ADDRESS varchar(40) NOT NULL, C_NATIONKEY int NOT NULL, C_PHONE char(15) NOT NULL, C_ACCTBAL decimal(15,2) NOT NULL, C_MKTSEGMENT char(…...

链表的总体涵盖以及无哨兵位单链表实现——【数据结构】

&#x1f60a;W…Y&#xff1a;个人主页 在学习之前看一下美丽的夕阳&#xff0c;也是很不错的。 如果觉得博主的美景不错&#xff0c;博客也不错的话&#xff0c;关注一下博主吧&#x1f495; 在上一期中&#xff0c;我们说完了顺序表&#xff0c;并且提出顺序表中的问题 1. 中…...

网页版Java五子棋项目(一)websocket【服务器给用户端发信息】

网页版Java五子棋项目&#xff08;一&#xff09;websocket【服务器给用户端发信息】 一、为什么要用websocket二、websocket介绍原理解析 三、代码演示1. 创建后端api&#xff08;TestAPI&#xff09;新增知识点&#xff1a;extends TextWebSocketHandler重写各种方法 2. 建立…...

企业大数据可视化案例专题分享-入门

一、什么是数据可视化&#xff1f; 基本概念&#xff1a;数据可视化是以图示或图形格式表示的数据。让决策者可以看到以直观方式呈现的分析&#xff0c;以便他们可以掌握困难的概念或识别新的模式。借助交互式可视化&#xff0c;可以使用技术深入挖掘图表和图形以获取更多详细…...

GoogLeNet卷积神经网络-笔记

GoogLeNet卷积神经网络-笔记 GoogLeNet是2014年ImageNet比赛的冠军&#xff0c; 它的主要特点是网络不仅有深度&#xff0c; 还在横向上具有“宽度”。 由于图像信息在空间尺寸上的巨大差异&#xff0c; 如何选择合适的卷积核来提取特征就显得比较困难了。 空间分布范围更广的…...

腾讯云TencentOS Server镜像系统常见问题解答

腾讯云TencentOS Server镜像是腾讯云推出的Linux操作系统&#xff0c;完全兼容CentOS生态和操作方式&#xff0c;TencentOS Server操作系统为云上运行的应用程序提供稳定、安全和高性能的执行环境&#xff0c;TencentOS可以运行在腾讯云CVM全规格实例上&#xff0c;包括黑石物理…...

【项目 进程13】2.28共享内存(1) 2.29共享内存(2)

文章目录 2.28共享内存&#xff08;1&#xff09;共享内存&#xff08;效率最高&#xff0c;比内存映射更高。因为内存映射还需一个文件做载体&#xff09;共享内存使用步骤共享内存操作函数头文件 2.29共享内存&#xff08;2&#xff09;共享内存相关问题共享内存和内存映射的…...

Flask框架-流量控制:flask-limiter的使用

一、flask使用flask-limiter存在版本问题 Flask1.1.4 Flask-Bootstrap3.3.7.1 Flask-Caching1.9.0 Flask-Cors3.0.10 Flask-Limiter1.4 Flask-Migrate2.5.3 Flask-RESTful0.3.8 Flask-Script2.0.6 Flask-SocketIO5.0.1 Flask-Sockets0.2.1 Flask-SQLAlchemy2.4.4 Jinjia22.11.…...

【机器学习】西瓜书习题3.5Python编程实现线性判别分析,并给出西瓜数据集 3.0α上的结果

参考代码 结合自己的理解&#xff0c;添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt导入数据&#xff0c;进行数据处理和特征工程 得到数据集 D { ( x i , y i ) } i 1 m , y i ∈ { 0 ,…...

Elasticsearch:通过动态修剪实现更快的基数聚合

作者&#xff1a;Adrien Grand Elasticsearch 8.9 通过支持动态修剪&#xff08;dynamic pruning&#xff09;引入了基数聚合加速。 这种优化需要满足特定的条件才能生效&#xff0c;但一旦实现&#xff0c;通常会产生惊人的结果。 我们观察到&#xff0c;通过此更改&#xff0…...

Webpack5 生产模式压缩图片ImageMinimizerPlugin

文章目录 一、 ImageMinimizerPlugin是什么&#xff1f;二、已经有了asset&#xff0c;为什么需要ImageMinimizerPlugin&#xff1f;三、怎么使用ImageMinimizerPlugin&#xff1f;四、ImageMinimizerPlugin压缩的成果 一、 ImageMinimizerPlugin是什么&#xff1f; 它的实际依…...

时序预测 | Matlab实现基于BP神经网络的电力负荷预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 时序预测 | Matlab实现基于BP神经网络的电力负荷预测模型 BP神经网络是一种多层的前馈神经网络,其主要的特点是:信号是前向传播的,而误差是反向传播的。B...

基于回溯算法实现八皇后问题

八皇后问题是一个经典的计算机科学问题&#xff0c;它的目标是将8个皇后放置在一个大小为88的棋盘上&#xff0c;使得每个皇后都不会攻击到其他的皇后。皇后可以攻击同一行、同一列和同一对角线上的棋子。 一、八皇后问题介绍 八皇后问题最早由国际西洋棋大师马克斯贝瑟尔在18…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...