Javascript 在Html5中,如何将矩形坐标从一个画布转移到另一个画布?

Javascript 在Html5中,如何将矩形坐标从一个画布转移到另一个画布?,javascript,jquery,html5-canvas,Javascript,Jquery,Html5 Canvas,我正在使用一些代码动态地将画布上一个矩形的坐标转移到另一个画布上,以便在画布2的确切位置上绘制矩形 我经历过不同的类似问题和解决方案,如:和关于stackoverflow的问题和解决方案,但它们都不适用于我的情况 sendimg函数将矩形坐标从画布1传输到画布2。由于canvas2图像被缩放到较大的尺寸,矩形没有在正确的位置绘制 请检查所附的代码片段或了解详细信息 var canvas=document.getElementByIdcanvas1; var canvas2=document.g

我正在使用一些代码动态地将画布上一个矩形的坐标转移到另一个画布上,以便在画布2的确切位置上绘制矩形

我经历过不同的类似问题和解决方案,如:和关于stackoverflow的问题和解决方案,但它们都不适用于我的情况

sendimg函数将矩形坐标从画布1传输到画布2。由于canvas2图像被缩放到较大的尺寸,矩形没有在正确的位置绘制

请检查所附的代码片段或了解详细信息

var canvas=document.getElementByIdcanvas1; var canvas2=document.getElementByIdcanvas2; var ctx=canvas.getContext2d; var ctx2=canvas2.getContext2d; var img=新图像; var rect={}; var标度=0; var标度2=0; var x=0; var y=0; var x2=0; var y2=0; var-drag=false; img.onload=函数{ //设置画布的dpi 1 var dpi=window.devicePixelRatio | | 1; canvas.setAttribute'width',canvas.clientWidth*dpi; canvas.setAttribute'height',canvas.clientHeight*dpi; //设置画布的dpi 2 var dpi=window.devicePixelRatio | | 1; canvas2.setAttribute'width',canvas2.clientWidth*dpi; canvas2.setAttribute'height',canvas2.clientHeight*dpi; ctx.clearRect0,0,canvas.clientWidth,canvas.clientHeight; ctx.save; ctx2.clearRect0,0,canvas.clientWidth,canvas.clientHeight; ctx2.save; //将图像拟合到画布填充 scale=Math.maxcanvas.clientWidth/img.width,canvas.clientHeight/img.height;//canvas1 scale scale2=Math.maxcanvas2.clientWidth/img.width,canvas2.clientHeight/img.height;//canvas2 scale x=canvas.clientWidth/2-img.width/2*scale;//canvas1 x y=canvas.clientHeight/2-img.height/2*比例;//canvas1 y x2=canvas2.clientWidth/2-img.width/2*scale2;//canvas2 x y2=canvas2.clientHeight/2-img.height/2*scale2;//canvas2 y ctx.drawImageimg,x,y,img.宽度*比例,img.高度*比例; ctx2.drawImageimg,x2,y2,img.width*scale2,img.height*scale2; canvas.addEventListener'mousedown',mousedown,false; canvas.addEventListener'mouseup',mouseup,false; canvas.addEventListener'mousemove',mousemove,false; } img.crossOrigin=匿名; img.src=https://i.imgur.com/1n8sbrF.jpg'; 函数mouseDowne{ rect.startX=e.clientX-this.offsetLeft; rect.startY=e.clientY-this.offsetTop; 阻力=真; } 函数mouseUp{ 阻力=假; console.logrect; } 函数mousemove{ 如果拖动{ ctx.clearRect0,0,canvas.clientWidth,canvas.clientHeight; ctx.save; ctx.drawImageimg,x,y,img.宽度*比例,img.高度*比例; rect.w=e.clientX-this.offsetLeft-rect.startX; rect.h=e.clientY-this.offsetTop-rect.startY; ctx.lineWidth=2; ctx.strokeStyle=‘红色’; ctx.strokeRectrect.startX、rect.startY、rect.w、rect.h; } } 函数sendimg { ifrect.startX==未定义 { 首先在画布1上绘制任意矩形; 返回false; } ctx2.线宽=2; ctx2.strokeStyle=黄色; //以下代码未在正确位置绘制矩形 ctx2.strokeRectrect.startX*scale2+x2,rect.startY*scale2+y2,rect.w*scale2,rect.h*scale2; } html,正文{ 宽度:90%; 身高:90%; } 第一组{ 利润率:10px; 宽度:800px; 高度:600px; 边框:2倍纯红; } 第二组{ 位置:绝对位置; 顶部:20px; 左:900px; 利润率:10px; 宽度:1200px; 高度:800px; 边框:2倍纯红; } 帆布{ 宽度:100%; 身高:100%; } 在画布上发送矩形2
在应用第二个画布的变换和缩放因子之前,需要反转第一个画布的缩放和平移。这就像90%的情况一样,Y轴是正确的,但X轴平移错误。请参阅我对ctx2.strokeRect的调用以及它如何反转缩放和平移。我的代码可能被顶起了,因为画布原点位于左上角,而平移和缩放公式假定画布原点位于左下角

编辑:修复了代码-现在应该是正确的

var canvas=document.getElementByIdcanvas1; var canvas2=document.getElementByIdcanvas2; var ctx=canvas.getContext2d; var ctx2=canvas2.getContext2d; var img=新图像; var rect={}; var标度=0; var标度2=0; var x=0; var y=0; var x2=0; var y2=0; var-drag=false; img.onload=函数{ //设置画布的dpi 1 var dpi=window.devicePixelRatio | | 1; canvas.setAttribute'width',canvas.clientWidth*dpi; canvas.setAttribute'height',canvas.clientHeight*dpi; //设置画布的dpi 2 var dpi=window.devicePixelRatio | | 1; canvas2.setAttribute'width',canvas2.clientWidth*dpi; canvas2.setAttribute'height',canvas2.clientHeight*dpi; ctx.clearRect0,0,canvas.clientWidth,canvas.clientHeight; ctx.save; ctx2.clearRect0,0,canvas.clientWidth,canva s、 阴蒂; ctx2.save; //将图像拟合到画布填充 scale=Math.maxcanvas.clientWidth/img.width,canvas.clientHeight/img.height//拉票量表 scale2=Math.maxcanvas2.clientWidth/img.width,canvas2.clientHeight/img.height//拉票量表 x=canvas.clientWidth/2-img.width/2*比例//拉票1 x y=canvas.clientHeight/2-img.height/2*刻度//游说 x2=canvas2.clientWidth/2-img.width/2*刻度2//拉票2 x y2=画布2.clientHeight/2-img.height/2*刻度2//游说 ctx.drawImageimg,x,y,img.宽度*比例,img.高度*比例; ctx2.drawImageimg,x2,y2,img.width*scale2,img.height*scale2; canvas.addEventListener'mousedown',mousedown,false; canvas.addEventListener'mouseup',mouseup,false; canvas.addEventListener'mousemove',mousemove,false; 对数标度 console.logscale2 } img.crossOrigin=匿名; img.src=https://i.imgur.com/1n8sbrF.jpg'; 函数mouseDowne{ rect.startX=e.clientX-this.offsetLeft; rect.startY=e.clientY-this.offsetTop; 阻力=真; } 函数mouseUp{ 阻力=假; console.logrect; } 函数mousemove{ 如果拖动{ ctx.clearRect0,0,canvas.clientWidth,canvas.clientHeight; ctx.save; ctx.drawImageimg,x,y,img.宽度*比例,img.高度*比例; rect.w=e.clientX-this.offsetLeft-rect.startX; rect.h=e.clientY-this.offsetTop-rect.startY; ctx.lineWidth=2; ctx.strokeStyle=‘红色’; ctx.strokeRectrect.startX、rect.startY、rect.w、rect.h; } } 函数sendimg { ifrect.startX==未定义 { 首先在画布1上绘制任意矩形; 返回false; } ctx2.线宽=2; ctx2.strokeStyle=黄色; //以下代码未在正确位置绘制矩形 ctx2.strokeRect.startX-x/刻度*刻度2+x2, 垂直起始-y/比例*比例2+y2, 矩形w/比例*比例2, rect.h/scale*scale2; } html,正文{ 宽度:90%; 身高:90%; } 第一组{ 利润率:10px; 宽度:800px; 高度:600px; 边框:2倍纯红; } 第二组{ 位置:绝对位置; 顶部:20px; 左:900px; 利润率:10px; 宽度:1200px; 高度:800px; 边框:2倍纯红; } 帆布{ 宽度:100%; 身高:100%; } 在画布上发送矩形2 一些大问题和小问题 重要信息:调用时,将当前2D画布状态推送到堆栈中。如果你不打电话,打电话是没有意义的。更糟糕的是,每次调用save都会占用内存。 窗口是此窗口的全局窗口。你不需要使用它。例如window.devicePixelRatio与devicePixelRatio相同 您不需要使用setAttribute。仅当希望标记反映属性状态且属性未由DOM定义时,才使用setAttribute。 设置画布宽度或高度时,画布将被清除,状态将重置为默认值。设置画布大小后,无需清除画布,也无需保存其状态。 简化数学。当你计算原点时,你会得到a/2-b/2*c。它有一个公约数2,因此变成了-b*c/2 坐标系 使用公共坐标系,并在渲染到任一画布时进行转换。由于两个画布都渲染相同的图像,因此,作为相关坐标系的图像使用图像坐标系

您有4个坐标系,图像、缩放图像画布1、缩放图像画布2和rect作为画布1像素。问题是您正在从canvas1像素坐标rect转换为canvas2图像坐标

要修复缩放和定位,请将画布1像素坐标转换为图像坐标,请参见示例函数MouseeEvents。然后在渲染函数中,将图像坐标转换回画布像素坐标,参见示例函数updateCanvas

实例 我删除了大量不必要的重复代码,以降低复杂性,并使代码更具可读性和可维护性。使用现代JS并添加了一些UI

设置画布的单个函数 处理鼠标事件的单个函数 渲染矩形的单个函数 使用光标十字线提供反馈,无 对于这个示例,我删除了与问题无关的按钮,减小了两个画布的大小以适合非常小的代码段窗口,并在绘制第一个矩形时实时更新第二个矩形

请注意,rect在图像坐标中

常数COLOR1=F00,COLOR2=FF0,线宽=2; const ctx1=canvas1.getContext2d,ctx2=canvas2.getContext2d; const img=新图像; const rect={}; var-drag=false; img.src=https://i.imgur.com/1n8sbrF.jpg; img.addEventListenerload,=>{ 设置canvasctx1; 设置canvasct2; canvas1.addEventListenermousedown,mouseEvent; canvas1.addEventListenermouseup,mouseEvent; canvas1.addEventListenermousemove,MouseeEvent; },{once:true}; 函数setupCanvasctx,coords={}{ 有限公司 nst dPR=devicePixelRatio | | 1; const w=ctx.canvas.width=ctx.canvas.clientWidth*dPR; 常数h=ctx.canvas.height=ctx.canvas.clientHeight*dPR; 常量比例=坐标。比例=数学。最大宽度/最小高度,高度/最小高度; 常数x=coords.x=w-img.width*scale/2; 常数y=坐标y=h-惯性高度*刻度/2; ctx.drawImageimg,x,y,img.宽度*比例,img.高度*比例; ctx.canvas.coords=coords; } 功能鼠标通风{ var cursor=十字线; const co=canvas1.coords; const x=e.clientX-this.offsetLeft-co.x/co.scale; const y=e.clientY-this.offsetTop-co.y/co.scale; 如果e.type==mousedown{ rect.x=x; 矩形y=y; 阻力=真; canvas1.title=; }如果e.type==mouseup{drag=false} 如果拖动{ 游标=无; rect.w=x-rect.x; 矩形h=y-矩形y; 更新CANVASCTX1,COLOR1,co; 更新canvasctx2、COLOR2、canvas2.coords; } canvas1.style.cursor=光标; } 函数updateCanvasctx,color,{x,y,scale}{ ctx.clearRect0,0,ctx.canvas.width,ctx.canvas.height; ctx.drawImageimg,x,y,img.宽度*比例,img.高度*比例; ctx.lineWidth=线宽; ctx.strokeStyle=颜色; ctx.strokeRectx+rect.x*比例,y+rect.y*比例,rect.w*比例,rect.h*比例; } html,正文{ 宽度:90%; 身高:90%; } 第一组{ 利润率:10px; 宽度:200px; 高度:300px; 边框:2倍纯红; } 第二组{ 位置:绝对位置; 顶部:10px; 左:240px; 宽度:300px; 高度:200px; 边框:2倍实心FF0; } 帆布{ 宽度:100%; 身高:100%; }
我没有完全调试您的代码,但问题肯定来自您定义X坐标的地方。因为canvas.width