js使用canvas实现图片鼠标滚轮放大缩小拖拽预览,显示像素坐标,显示像素值

html代码

todo 实现画矩形框,圆形roi

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Image Viewer</title>
<style>canvas {border: 1px solid black;}
</style>
</head>
<body>
<div><button id="loadImageButton">Load Image</button>
</div>
<canvas id="mainCanvas" width="900" height="800"></canvas><div><span>坐标</span><span id="imageXY"></span><div><span id="imagePix"></span></div>
</div><script>const canvas = document.getElementById('mainCanvas');const ctx = canvas.getContext('2d');ctx.imageSmoothingEnabled = false;let imageObj = new Image();let imageWidth;let imageHeight;let scale = 1;let offsetX = 0;let offsetY = 0;let pixdata;canvas.addEventListener('mousedown', mouseDownListener);canvas.addEventListener('mouseup', mouseUpListener);canvas.addEventListener('mousemove', mouseMoveListener);canvas.addEventListener('mousewheel', mouseWheelListener);document.getElementById('loadImageButton').addEventListener('click', loadImage);function initPixData(image){const canvasHide = document.createElement('canvas');const context = canvasHide.getContext('2d');canvasHide.width = image.width;canvasHide.height = image.height;context.drawImage(image, 0, 0);const imageData = context.getImageData(0, 0, image.width, image.height);pixdata = imageData.data;console.log(pixdata)}function getPixelValue(x, y) {let pixelValue;if (pixdata.length === 4) {pixelValue = {red: pixel[0],green: pixel[1],blue: pixel[2],alpha: pixel[3]};} else if (ipixdata.length === 1) {pixelValue = {gray: pixel[0]};} else {throw new Error('Unsupported image format');}return pixelValue;}function loadImage() {const input = document.createElement('input');input.type = 'file';input.accept = 'image/*';input.click();input.onchange = e => {const file = e.target.files[0];const reader = new FileReader();reader.onload = readerEvent => {const url = readerEvent.target.result;imageObj.src = url;};reader.readAsDataURL(file);};}let isDragging = false;let lastX;let lastY;function mouseDownListener(e) {let rect = canvas.getBoundingClientRect();isDragging = true;lastX = e.clientX - rect.left;lastY = e.clientY - rect.top;}function mouseUpListener(e) {isDragging = false;}function mouseMoveListener(e) {if (isDragging) {let rect = canvas.getBoundingClientRect();offsetX += (e.clientX - rect.left) - lastX;offsetY += (e.clientY - rect.top) - lastY;lastX = e.clientX - rect.left;lastY = e.clientY - rect.top;ctx.clearRect(0, 0, canvas.width, canvas.height);drawImage();}showImageXY(e);}function mouseWheelListener(e) {let delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));if (scale > 0.1 && scale < 10 && delta < 0) {scale *= 0.9;}if (scale > 0.1 && scale < 10 && delta > 0) {scale *= 1.1;}ctx.clearRect(0, 0, canvas.width, canvas.height);drawImage();}function createBlock(a, b, r) {let rect = canvas.getBoundingClientRect();let canvasX = (a * scale) + offsetX + rect.left;let canvasY = (b * scale) + offsetY + rect.top;let radius=r*scale;ctx.beginPath();ctx.fillStyle = 'red';ctx.arc(canvasX, canvasY, radius, 0, Math.PI * 2);ctx.fill();}function drawImage() {ctx.drawImage(imageObj, offsetX, offsetY,imageWidth * scale,imageHeight * scale);createBlock(200,200,200)}//计算当前鼠标坐标对应的图片里的像素坐标function showImageXY(e) {let rect = canvas.getBoundingClientRect();let x=(e.clientX - rect.left- offsetX)/scalelet y=(e.clientY- rect.top - offsetY)/scalex=Math.round(x)y=Math.round(y)if(x<0 || x>imageWidth){x="-"}if(y<0 || y>imageHeight){y="-"}if(!(x=='-'|| y=='-')){showImagePixVal(x,y);}document.getElementById("imageXY").innerText = `x=${x} y=${y} xInCanvas=${offsetX} yInCanvas=${offsetY} width=${imageWidth} height=${imageHeight}`;}function showImagePixVal(x,y){let idx=((y * (imageWidth * 4)) + (x * 4));if(pixdata){let r=pixdata[idx]let g=pixdata[idx+1]let b=pixdata[idx+2]let a=pixdata[idx+3]document.getElementById("imagePix").innerText = `r=${r} g=${g} b=${b} a=${a}`;}}imageObj.onload = () => {imageWidth = imageObj.width;imageHeight = imageObj.height;drawImage();initPixData(imageObj);}
</script>
</body>
</html>

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

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

相关文章

单元测试开发必不可少的一项工作,C#怎么来写单元测试

单元测试在开发过程中非常重要&#xff0c;写单元测试有几个重要的理由&#xff1a; 确保代码质量和稳定性&#xff1a; 单元测试可以帮助你验证代码的正确性。通过编写测试用例&#xff0c;你可以确保代码按照预期的方式工作&#xff0c;并且在进行重构或修改时不会破坏原有的…

JMeter 面试题及答案整理,最新面试题

JMeter中如何进行性能测试的规划和设计&#xff1f; 进行JMeter性能测试的规划和设计主要遵循以下几个步骤&#xff1a; 1、确定测试目标&#xff1a; 明确性能测试的目的和目标&#xff0c;比如确定要测试的系统性能指标&#xff08;如响应时间、吞吐量、并发用户数等&#…

zookeeper快速入门一:zookeeper安装与启动

本文是zookeeper系列之快速入门中的第一篇&#xff0c;欢迎大家观看与指出不足。 写在前面&#xff1a; 不影响教程&#xff0c;笔者安装zookeeper用的是WSL(windows下的linux子系统&#xff09;&#xff0c;当然你想直接在windows上用zookeeper也是可以的。 如果你也想用ws…

怎么判断发票扫描OCR软件好用不好用?

发票扫描OCR&#xff08;Optical Character Recognition&#xff09;是一种将纸质发票上的文字、数字等信息转化为可编辑的文本格式的技术。在现代企业中&#xff0c;随着数字化转型的推进&#xff0c;发票扫描OCR技术变得越来越重要。然而&#xff0c;面对市场上众多的发票扫描…

spring boot集成redis实现共享存储session

spring boot集成redis实现共享存储session redis实现共享存储session 首先下载redis,我下载的版本是5.0.14,目前官网貌似找不到5.x版本&#xff0c;可以自行去网上寻找。我这里的springboot版本是2.6.4引入redis依赖 <!-- https://mvnrepository.com/artifact/org.spring…

重拾C++之菜鸟刷算法第13篇---回溯算法

子集 知识点 子集问题中&#xff0c;不能包含重复子集&#xff0c;那么就需要startIndex来防止重复取值 题目 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任…

Android 设计模式观察者

Java观察者模式实现观察者模式的接口Observer和目标接口Subject,并实现了一个具体的目标类WeatherData。 同时,还实现了一个观察者类CurrentConditionsDisplay,它在目标类注册后,会在测量变化时接收到更新,并打印当前状况。最后在main函数中,我们创建了目标类的实例,并设…

十、软考-系统架构设计师笔记-软件架构演化和维护

1、软件架构演化 软件架构的演化和维护的目的是为了使软件能够适应环境的变化而进行的纠错性修改和完善性修改。软件架构的演化和维护过程是一个不断迭代的过程&#xff0c;通过演化和维护&#xff0c;软件架构逐步得到完善&#xff0c;以满足用户需求。软件架构的演化就是软件…

校园闲置物品交易网站 |基于springboot框架+ Mysql+Java+Tomcat的校园闲置物品交易网站设计与实现(可运行源码+设计文档)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 用户功能模块 管理员功能登录前台功能效果图 系统功能设计 数据库E-R图设计 lunwen…

【NLP笔记】文本分词、清洗和标准化

文章目录 文本分词中文分词英文分词代码示例 文本清洗和标准化 文本分词 参考文章&#xff1a;​一文看懂NLP里的分词&#xff08;中英文分词区别3 大难点3 种典型方法&#xff09;; 文本分词处理NLP的基础&#xff0c;先通过对文本内容进行分词、文本与处理&#xff08;无用标…

Rocky Linux - Primavera P6 EPPM 安装及分享

引言 继上一期发布的Redhat Linux版环境发布之后&#xff0c;近日我又制作了基于Rocky Enterprise Linux 的P6虚拟机环境&#xff0c;同样里面包含了全套P6 最新版应用服务 此虚拟机仅用于演示、培训和测试目的。如您在生产环境中使用此虚拟机&#xff0c;请先与Oracle Primav…

Day48| 121 买卖股票的最佳时机 122 买卖股票的最佳时机II

目录 121 买卖股票的最佳时机 122 买卖股票的最佳时机II 121 买卖股票的最佳时机 class Solution { public:int maxProfit(vector<int>& prices) {int len prices.size();//dp[i] 表示当前的最大利润vector<vector<int>> dp(len, vector<int>…

算法学习(持续更新中)

时间复杂度 一个操作如果和样本的数据量没有关系&#xff0c;每次都是固定时间内完成的操作&#xff0c;叫做常数操作。 时间复杂度为一个算法流程中&#xff0c;常数操作数量的一个指标。常用O&#xff08;读作big O&#xff09;来表示。具体来说&#xff0c;先要对一个算法…

AI - 支持向量机算法

&#x1f9e8;概念 支持向量机&#xff08;Support Vector Machine, SVM&#xff09;是一种强大的机器学习算法&#xff0c;主要用于解决二分类问题。 SVM的核心思想是找到一个超平面&#xff0c;这个超平面能够最好地将数据分为两类&#xff0c;即在保证分类准确的情况下&am…

Hive SQL必刷练习题:同时在线人数问题(*****)

问题描述&#xff1a; 思路&#xff1a; ​ 因为有进直播间时间&#xff0c;和出直播间人数。所以我可以统计&#xff0c;进来一个是不是人数就会加1&#xff0c;出去一个&#xff0c;人数就会减1。 ​ 所以可以给进直播间的时间标记一个1&#xff0c;出直播间的时间标记一个…

【机器学习-02】矩阵基础运算---numpy操作

在机器学习-01中&#xff0c;我们介绍了关于机器学习的一般建模流程&#xff0c;并且在基本没有数学公式和代码的情况下&#xff0c;简单介绍了关于线性回归的一般实现形式。不过这只是在初学阶段、为了不增加基础概念理解难度所采取的方法&#xff0c;但所有的技术最终都是为了…

sparksql简介

什么是sparksql sparksql是一个用来处理结构话数据的spark模块&#xff0c;它允许开发者便捷地使用sql语句的方式来处理数据&#xff1b;它是用来处理大规模结构化数据的分布式计算引擎&#xff0c;其他分布式计算引擎比较火的还有hive&#xff0c;map-reduce方式。 sparksql…

GUROBI之数学启发式算法Matheuristics

参考运小筹的帖子&#xff1a;优化求解器 | Gurobi 数学启发式算法&#xff1a;参数类型与案例实现 - 知乎 (zhihu.com) 简言之&#xff0c;数学启发式是算法就是数学规划和启发式算法的融合&#xff0c;与元启发式算法相比&#xff0c;数学启发式算法具有更强的理论性。 在GUR…

python--模块导入+路径处理+常见异常类型

python--模块导入路径处理常见异常类型 模块导入import 模块名from 模块名 import 类、变量、函数from 模块名 import *from 项目名.包.py文件名称 import 类、变量、函数导包快捷键 os 模块 路径处理路径获取os.path.dirname(__file__)os.path.abspath(test.txt)os.getcwd() 路…

React低代码平台实战:构建高效、灵活的应用新范式

文章目录 每日一句正能量前言一、React与低代码平台的结合优势二、基于React的低代码平台开发挑战三、基于React的低代码平台开发实践后记好书推荐编辑推荐内容简介作者简介目录前言为什么要写这本书 读者对象如何阅读本书 赠书活动 每日一句正能量 人生之美&#xff0c;不在争…