【canvas】canvas基础使用(七):绘制图像

简言

学习canvas如何绘制图片或视频。

绘制图像

给定一个图像,一般使用drawImage()方法绘制。

drawImage 绘制图像

Canvas 2D API 中的 CanvasRenderingContext2D.drawImage() 方法提供了多种在画布(Canvas)上绘制图像的方式。
语法:
指定绘制位置快速绘制:
drawImage(image, dx, dy);
指定绘制位置宽高快速绘制:
drawImage(image, dx, dy, dWidth, dHeight);
指定图像被绘制区域和绘制区域绘制:
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
在这里插入图片描述

使用方法有三种

参数:

  • image
    绘制到上下文的元素。允许任何的画布图像源,例如:HTMLImageElement、SVGImageElement (en-US)、HTMLVideoElement、HTMLCanvasElement、ImageBitmap、OffscreenCanvas 或 VideoFrame (en-US)。

  • sx 可选
    需要绘制到目标上下文中的,image 的矩形(裁剪)选择框的左上角 X 轴坐标。可以使用 3 参数或 5 参数语法来省略这个参数。

  • sy 可选
    需要绘制到目标上下文中的,image 的矩形(裁剪)选择框的左上角 Y 轴坐标。可以使用 3 参数或 5 参数语法来省略这个参数。

  • sWidth 可选
    需要绘制到目标上下文中的,image 的矩形(裁剪)选择框的宽度。如果不说明,整个矩形(裁剪)从坐标的 sx 和 sy 开始,到 image 的右下角结束。可以使用 3 参数或 5 参数语法来省略这个参数。使用负值将翻转这个图像。

  • sHeight 可选
    需要绘制到目标上下文中的,image的矩形(裁剪)选择框的高度。使用负值将翻转这个图像。

  • dx
    image 的左上角在目标画布上 X 轴坐标。

  • dy
    image 的左上角在目标画布上 Y 轴坐标。

  • dWidth
    image 在目标画布上绘制的宽度。允许对绘制的 image 进行缩放。如果不说明,在绘制时 image 宽度不会缩放。注意,这个参数不包含在 3 参数语法中。

  • dHeight
    image 在目标画布上绘制的高度。允许对绘制的 image 进行缩放。如果不说明,在绘制时 image 高度不会缩放。注意,这个参数不包含在 3 参数语法中。

注意

  • 当 drawImage() 需要在 HTMLVideoElement 工作时,仅当 HTMLMediaElement.readyState 大于 1 时 drawImage() 才能正常工作。
  • 在绘制,裁剪和/或缩放时,drawImage() 将始终使用源元素的固有尺寸(以 CSS 像素为单位)。
  • 在某些旧版本浏览器中,drawImage() 将忽略图像中的所有 EXIF 元数据,包括方向。此行为在 iOS 设备上尤其麻烦。你应该自己检测方向并使用 rotate() 使其正确。

示例

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const image = document.getElementById("source");image.addEventListener("load", (e) => {ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
});

ImageData 绘制图像

获得一个ImageData 对象后,使用putImageData()方法绘制。

可以通过CanvasRenderingContext2D.getImageData()获得一个ImageData 对象,用来描述 canvas 区域隐含的像素数据。

语法:
ImageData ctx.getImageData(sx, sy, sw, sh);
参数:

  • sx
    将要被提取的图像数据矩形区域的左上角 x 坐标。

  • sy
    将要被提取的图像数据矩形区域的左上角 y 坐标。

  • sw
    将要被提取的图像数据矩形区域的宽度。

  • sh
    将要被提取的图像数据矩形区域的高度。

getImageData()

CanvasRenderingContext2D.getImageData() 返回一个ImageData对象,用来描述 canvas 区域隐含的像素数据,这个区域通过矩形表示,起始点为*(sx, sy)、宽为sw、高为sh。*

putImageData()

CanvasRenderingContext2D.putImageData() 是 Canvas 2D API 将数据从已有的 ImageData 对象绘制到位图的方法。如果提供了一个绘制过的矩形,则只绘制该矩形的像素。此方法不受画布转换矩阵的影响。
语法:
void ctx.putImageData(imagedata, dx, dy);
void ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
参数:

  • imageData
    ImageData,包含像素值的数组对象。

  • dx
    源图像数据在目标画布中的位置偏移量(x 轴方向的偏移量)。

  • dy
    源图像数据在目标画布中的位置偏移量(y 轴方向的偏移量)。

  • dirtyX 可选
    在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(x 坐标)。

  • dirtyY 可选
    在源图像数据中,矩形区域左上角的位置。默认是整个图像数据的左上角(y 坐标)。

  • dirtyWidth 可选
    在源图像数据中,矩形区域的宽度。默认是图像数据的宽度。

  • dirtyHeight 可选
    在源图像数据中,矩形区域的高度。默认是图像数据的高度。

示例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>图像剪辑</title><style>html,body {width: 100vw;height: 100%;margin: 0;padding: 0;}.box {box-sizing: border-box;width: 100%;height: 100%;padding: 24px;}.box-content {margin-top: 16px;box-sizing: border-box;width: 100%;/* height: 500px; *//* display: flex; */align-items: center;text-align: center;border: 1px solid #000;}#origin {width: 500px;height: 500px;border: 1px solid #000;}</style>
</head><body><div class="box"><div><h1>图像查看</h1><input type="file" name="file" id="file"></div><div class="box-content"><canvas id="origin" width="500" height="500"></canvas></div><div></div></div><script>const file = document.getElementById('file');const origin = document.getElementById('origin');const ctx = origin.getContext('2d');const img = document.createElement('img');//  辅助线let fx = 0let fy = 0let showf = false//  图片缩放let scale = 1 //  图片缩放比例let dx = 0 //  图片偏移 xlet dy = 0//  图片偏移 ylet dw = origin.widthlet dh = origin.heightlet modify = falseorigin.addEventListener("mousedown", (e) => {modify = trueshowf = truelastX = e.offsetXlastY = e.offsetY});origin.addEventListener("mousemove", (e) => {if (!ctx) returnlet x = e.offsetXlet y = e.offsetYif (modify) {fx = xfy = ydx += (x - lastX)dy += (y - lastY)lastX = xlastY = ydrawOperatingLine()}})origin.addEventListener('mouseup', (e) => {if (modify) {modify = falseshowf = falsedrawOperatingLine()}})origin.addEventListener("contextmenu", (e) => {e.preventDefault()if (img.width > img.height) {scale = origin.width / img.width} else {scale = origin.height / img.height}dx = (origin.width - scale * img.width) / (origin.width / e.offsetX)dy = (origin.height - scale * img.height) / (origin.height / e.offsetY)drawOperatingLine()})origin.addEventListener('wheel', (e) => {const { deltaY } = eif (deltaY > 0) { // 下滑放大scale += 0.1} else if (scale > 0.1) { // 上滑缩小scale -= 0.1}dx = (origin.width - scale * img.width) / (origin.width / e.offsetX)dy = (origin.height - scale * img.height) / (origin.height / e.offsetY)drawOperatingLine()})file.addEventListener('change', (e) => {const file = e.target.files[0];const reader = new FileReader();reader.readAsDataURL(file);reader.onload = (e) => {img.src = e.target.result;img.onload = () => {//  更新图片缩放比例if (img.width > img.height) {scale = origin.width / img.width} else {scale = origin.height / img.height}drawOperatingLine(true)}}})//  绘制裁剪控制图像function drawOperatingLine(init = false) {ctx.clearRect(0, 0, origin.width, origin.height)//  绘制图像dx = init ? (origin.width - scale * img.width) / 2 : dx  //  图片偏移 xdy = init ? (origin.height - scale * img.height) / 2 : dy //  图片偏移 ydw = scale * img.widthdh = scale * img.heightctx.drawImage(img, 0, 0, img.width, img.height, dx, dy, dw, dh);//  辅助线if (showf) {ctx.save()ctx.beginPath();ctx.strokeStyle = 'red'ctx.setLineDash([3, 3])ctx.moveTo(0, fy);ctx.lineTo(origin.width, fy);ctx.moveTo(fx, 0);ctx.lineTo(fx, origin.height);ctx.stroke();ctx.restore()}}</script>
</body></html>

在这里插入图片描述

结语

结束了。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言单链表详解

链表和顺序表的区别 顺序表的底层存储空间是连续的&#xff0c;链表的底层存储空间是不连续的&#xff0c;链表的每个节点需要额外的指针来指向下一个节点&#xff0c;占用更多的存储空间。 顺序表的随机访问性能好&#xff0c;时间复杂度为O(1)&#xff0c;链表的随机访问性能…

【C++软件调试技术】C++软件开发维护过程中典型调试问题的解答与总结

目录 1、引发C软件异常的常见原因有哪些&#xff1f; 2、排查C软件异常的常用方法有哪些&#xff1f; 3、为什么要熟悉常见的异常内存地址&#xff1f; 4、调试时遇到调用IsBadReadPtr或者IsBadWritePtr引发的异常&#xff0c;该如何处理&#xff1f; 5、如何排查GDI对象泄…

Oracle 获取最大值,第二大,第三大,第 N 大值

目录 1、原始数据2、获取最大值记录3、获取第二大值记录4、获取第三大值记录 1、原始数据 select * from test_2024_04_15_001 order by 销量 desc,渠道2、获取最大值记录 select 渠道,销量 from ( select a.渠道, a.销量 from test_2024_04_15_001 a order by a.销量 desc,…

Arcade 加载本地文本

参考 https://api.arcade.academy/en/latest/examples/text_loc_example.html#text-loc-example 代码 """ Example showing how to draw text to the screen.If Python and Arcade are installed, this example can be run from the command line with: pyth…

极大似然估计、最大后验估计、贝叶斯估计

机器学习笔记 第一章 机器学习简介 第二章 感知机 第三章 支持向量机 第四章 朴素贝叶斯分类器 第五章 Logistic回归 第六章 线性回归和岭回归 第七章 多层感知机与反向传播【Python实例】 第八章 主成分分析【PCA降维】 第九章 隐马尔可夫模型 第十章 奇异值分解 第十一章 熵…

【随笔】Git 高级篇 -- 获取远程分支数据 git fetch(二十七)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

代码随想录算法训练营DAY27|C++回溯算法Part.3|39.组合总和、40.组合总和II、组合问题小总结、131.分割回文串

文章目录 39.组合总和思路伪代码实现剪枝优化CPP代码普通版本剪枝版本 40.组合总和II思路伪代码CPP代码不采用used数组的去重方法 组合问题小总结131.分割回文串思路伪代码CPP代码 39.组合总和 力扣题目链接 文章讲解&#xff1a;39.组合总和 视频讲解&#xff1a;Leetcode:39.…

数据结构——顺序表——数组元素和与数字和的绝对差

数据结构——顺序表——数组元素和与数字和的绝对差 class Solution { public:int differenceOfSum(vector<int>& nums) {int a 0;int b 0;for(int i 0; i < nums.size(); i){a a nums[i];while(nums[i]){b b (nums[i] % 10);nums[i] nums[i] / 10;}}retu…

常见的Linux命令

linux操作系统 ctrl鼠标滚动 放大缩小字体 cd /目录进入目录下 ls查看当前目录下的所有内容 tar -zxvf 压缩包名字 对压缩包进行解压 sync将数据由内存同步到硬盘上 shutdown关机指令 shutdown -h 10 /10 表示十分钟后关机 shutdown -h now 表示现在关机 shutdown -h…

OpenCV4.9图像金字塔

目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 pyrUp()和 pyrDown()对给定图像进行下采样或上采样。 理论 注意 下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书。 通常&#xff0c;我们需要将图像转换为与原始图像不同的大小。为此…

springboot上传模块到私服,再用pom引用下来

有时候要做一个公司的公共服务模块。不能说大家都直接把代码粘贴进去&#xff0c;因为会需要维护很多份&#xff1b;这样就剩下两个方式了。 方式一&#xff1a;自己独立部署一个公共服务的服务&#xff0c;全公司都调用&#xff0c;通过http、rpc或者grpc的方式&#xff0c;这…

用 Python 写 3D 游戏,太赞了!

vizard介绍 Vizard是一款虚拟现实开发平台软件&#xff0c;从开发至今已走过十个年头。它基于C/C&#xff0c;运用新近OpenGL拓展模块开发出的高性能图形引擎。当运用Python语言执行开发时&#xff0c;Vizard同时自动将编写的程式转换为字节码抽象层(LAXMI)&#xff0c;进而运…