Javascript Konva.js:[自由绘制&拖动&缩放]在拖动或缩放后无法使用指针正确绘制

Javascript Konva.js:[自由绘制&拖动&缩放]在拖动或缩放后无法使用指针正确绘制,javascript,konvajs,Javascript,Konvajs,欢迎任何讨论。谢谢你的阅读 我想做什么 我正在尝试使用Konva.js实现简单的paperwhiteboard 到目前为止,我已经实现了在纸上拖动、缩放和自由绘图 我提到 用于缩放 免费绘画 我只想在米色背景的区域上绘制,并且我想在指针下精确绘制,即使它被缩放或拖动 但是,自由绘图和拖动和缩放功能不能很好地协同工作 缺陷 拖动或缩放后无法正确绘制 我认为错误的事情正在发生,但无法修复 我认为下面两部分有问题 缩放的实现 如何在绘图实现中使用stage.getPointerPosition 或者这

欢迎任何讨论。谢谢你的阅读

我想做什么 我正在尝试使用Konva.js实现简单的paperwhiteboard

到目前为止,我已经实现了在纸上拖动、缩放和自由绘图

我提到

用于缩放 免费绘画 我只想在米色背景的区域上绘制,并且我想在指针下精确绘制,即使它被缩放或拖动

但是,自由绘图和拖动和缩放功能不能很好地协同工作

缺陷 拖动或缩放后无法正确绘制

我认为错误的事情正在发生,但无法修复 我认为下面两部分有问题

缩放的实现 如何在绘图实现中使用stage.getPointerPosition 或者这两者的实现不适合在一起 密码 最低代码在这里

/*-模式管理-*/ 让modeSelector=document.getElementById'mode-selector'; let mode=modeSelector.value; modeSelector.addEventListener'change',=>{ //旧模式使用的Discead事件处理程序 开关模式{ 案例“手”:{ 尾端; 打破 } “笔”一案:{ endPen; 打破 } } //为新模式设置事件处理程序 mode=modeSelector.value; 开关模式{ 案例“手”:{ 二手货; 打破 } “笔”一案:{ usePen; 打破 } } }; /*-Konva对象-*/ 让舞台=新康瓦舞台{ 容器:'容器', 宽度:window.innerWidth, 高度:window.innerHeight }; //仅用于背景色的图层 让backgroundLayer=新Konva.Layer; 让backgroundColor=新Konva.Image{ 宽度:window.innerWidth, 高度:window.innerHeight, 填充:“RGB242233226” } backgroundLayer.addbackgroundColor; stage.addbackgroundLayer; backgroundLayer.draw; //用于自由绘制的图层 设drawLayer=新Konva.Layer; stage.adddrawLayer; /*-模式转换功能--*/ 常用函数{ //使舞台拖拉 stage.draggabletrue; //使舞台可缩放 //***代码是从中复制和粘贴的 // *** https://konvajs.org/docs/sandbox/Zooming_Relative_To_Pointer.htmlhttps://konvajs.org/docs/sandbox/Zooming_Relative_To_Pointer.html 设scaleBy=1.3; 舞台。在“轮子”上,evt=>{ evt.evt.preventDefault; 设oldScale=stage.scaleX; 让mousepointo={ x:stage.getPointerPosition.x/oldScale-stage.x/oldScale, y:stage.getPointerPosition.y/oldScale-stage.y/oldScale }; 让newScale=evt.evt.deltaY>0?oldScale*scaleBy:oldScale/scaleBy; stage.scale{x:newScale,y:newScale}; 设newPos={ x:-mousepointo.x-stage.getPointerPosition.x/newScale*newScale, y:-mousepointo.y-stage.getPointerPosition.y/newScale*newScale }; stage.positionnewPos; 第二阶段:抽签; }; } 功能结束{ stage.draggablefalse; 舞台。脱离“轮子”; } 函数usePen{ 让isDrawing=false; 让电流线; 舞台。在“mousedown”上,evt=>{ //开始绘图 isDrawing=true; //创建新线对象 设pos=stage.getPointerPosition; currentLine=新的Konva.Line{ 笔画:“黑色”, 冲程宽度:3, 点数:[位置x,位置y] }; drawLayer.addcurrentLine; }; stage.on'mousemove',evt=>{ 如果!正在绘制{ 回来 } //如果是图形,请向当前直线对象添加新点 设pos=stage.getPointerPosition; 设newPoints=currentLine.points.concat[pos.x,pos.y]; currentLine.points新点; drawLayer.batchDraw; }; 舞台上的“鼠标”,evt=>{ //端部拉深 isDrawing=false; }; } 函数结束笔{ 舞台。离开“鼠标镇; 舞台。离“老鼠洞”远点; 舞台。离“鼠标”远点; } /*-初始化-*/ 二手货; 纸张 手 笔 -> stage.getPointerPosition返回画布容器左上角指针相关的绝对位置

在变换、移动和缩放舞台时,需要找到相对位置,以便将其用于线条

演示如何执行此操作:

函数GetRelativePositionNode{ //函数将返回指针相对于所传递节点的位置 var transform=node.getAbsoluteTransform.copy; //为了检测相对位置,我们需要反转变换 变换。反转; //让指针说出鼠标或触摸位置 var pos=node.getStage.getPointerPosition; //现在我们找到一个相对点 返回transform.pointpos; } /*-模式管理-*/ 让modeSelector=document.getElementById'mode-selector'; let mode=modeSelector.value; modeSelector.addEventListener'change',=>{ //旧模式使用的Discead事件处理程序 开关模式{ 案例“手”:{ 尾端; 打破 } “笔”一案:{ endPen; 打破 } } //为新模式设置事件处理程序 mode=modeSelector.value; 开关模式{ 案例“手”:{ 二手货; 打破 } “笔”一案:{ usePen; 打破 } } }; /*-Konva对象-*/ 让舞台=新康瓦舞台{ 容器:'容器', 宽度:window.innerWidth, 高度:window.innerHeight }; //仅用于背景色的图层 让backgroundLayer=新Konva.Layer; 让backgroundColor=新Konva.Image{ 宽度:window.innerWidth, 高度:window.innerHeight, 填充:“RGB242233226” } backgroundLayer.addbackgroundColor; stage.addbackgroundLayer; backgroundLayer.draw; //用于自由绘制的图层 设drawLayer=新Konva.Layer; stage.adddrawLayer; /*-模式转换功能--*/ 常用函数{ //使舞台拖拉 stage.draggabletrue; //使舞台可缩放 //***代码是从中复制和粘贴的 // *** https://konvajs.org/docs/sandbox/Zooming_Relative_To_Pointer.htmlhttps://konvajs.org/docs/sandbox/Zooming_Relative_To_Pointer.html 设scaleBy=1.3; 舞台。在“轮子”上,evt=>{ evt.evt.preventDefault; 设oldScale=stage.scaleX; 让mousepointo={ x:stage.getPointerPosition.x/oldScale-stage.x/oldScale, y:stage.getPointerPosition.y/oldScale-stage.y/oldScale }; 让newScale=evt.evt.deltaY>0?oldScale*scaleBy:oldScale/scaleBy; stage.scale{x:newScale,y:newScale}; 设newPos={ x:-mousepointo.x-stage.getPointerPosition.x/newScale*newScale, y:-mousepointo.y-stage.getPointerPosition.y/newScale*newScale }; stage.positionnewPos; 第二阶段:抽签; }; } 功能结束{ stage.draggablefalse; 舞台。脱离“轮子”; } 函数GetRelativePositionNode{ //函数将返回指针相对于所传递节点的位置 var transform=node.getAbsoluteTransform.copy; //为了检测相对位置,我们需要反转变换 变换。反转; //让指针说出鼠标或触摸位置 var pos=node.getStage.getPointerPosition; //现在我们找到相对点 返回transform.pointpos; } 函数usePen{ 让isDrawing=false; 让电流线; 舞台。在“mousedown”上,evt=>{ //开始绘图 isDrawing=true; //创建新线对象 设pos=GetRelativePositionStage; currentLine=新的Konva.Line{ 笔画:“黑色”, 冲程宽度:3, 点数:[位置x,位置y] }; drawLayer.addcurrentLine; }; stage.on'mousemove',evt=>{ 如果!正在绘制{ 回来 } //如果是图形,请向当前直线对象添加新点 设pos=GetRelativePositionStage; 设newPoints=currentLine.points.concat[pos.x,pos.y]; currentLine.points新点; drawLayer.batchDraw; }; 舞台上的“鼠标”,evt=>{ //端部拉深 isDrawing=false; }; } 函数结束笔{ 舞台。离开“鼠标镇; 舞台。离“老鼠洞”远点; 舞台。离“鼠标”远点; } /*-初始化-*/ 二手货; 纸张 手 笔 -> stage.getPointerPosition返回画布容器左上角指针相关的绝对位置

在变换、移动和缩放舞台时,需要找到相对位置,以便将其用于线条

演示如何执行此操作:

函数GetRelativePositionNode{ //函数将返回指针相对于所传递节点的位置 var transform=node.getAbsoluteTransform.copy; //为了检测相对位置,我们需要反转变换 变换。反转; //让指针说出鼠标或触摸位置 var pos=node.getStage.getPointerPosition; //现在我们找到一个相对点 返回transform.pointpos; } /*-模式管理-*/ 让modeSelector=document.getElementById'mode-selector'; let mode=modeSelector.value; modeSelector.addEventListener'change',=>{ //旧模式使用的Discead事件处理程序 开关模式{ 案例“手”:{ 尾端; 打破 } “笔”一案:{ endPen; 打破 } } //为新模式设置事件处理程序 mode=modeSelector.value; 开关模式{ 案例“手”:{ 二手货; 打破 } “笔”一案:{ usePen; 打破 } } }; /*-Konva对象-*/ 让舞台=新康瓦舞台{ 容器:'容器', 宽度:window.innerWidth, 高度:window.innerHeight }; //仅用于背景色的图层 让backgroundLayer=新Konva.Layer; 让backgroundColor=新Konva.Image{ 宽度:window.innerWidth, 高度:window.innerHeight, 填充:“RGB242233226” } backgroundLayer.addbackgroundColor; stage.addbackgroundLayer; backgroundLayer.draw; //用于自由绘制的图层 设drawLayer=新Konva.Layer; stage.adddrawLayer; /*-模式转换功能--*/ 常用函数{ //使舞台拖拉 stage.draggabletrue; //使舞台可缩放 //***代码是从中复制和粘贴的 // *** https://konvajs.org/docs/sandbox/Zooming_Relative_To_Pointer.htmlhttps://konvajs.org/docs/sandbox/Zooming_Relative_To_Pointer.html 设scaleBy=1.3; 阶段 .在“方向盘”上,evt=>{ evt.evt.preventDefault; 设oldScale=stage.scaleX; 让mousepointo={ x:stage.getPointerPosition.x/oldScale-stage.x/oldScale, y:stage.getPointerPosition.y/oldScale-stage.y/oldScale }; 让newScale=evt.evt.deltaY>0?oldScale*scaleBy:oldScale/scaleBy; stage.scale{x:newScale,y:newScale}; 设newPos={ x:-mousepointo.x-stage.getPointerPosition.x/newScale*newScale, y:-mousepointo.y-stage.getPointerPosition.y/newScale*newScale }; stage.positionnewPos; 第二阶段:抽签; }; } 功能结束{ stage.draggablefalse; 舞台。脱离“轮子”; } 函数GetRelativePositionNode{ //函数将返回指针相对于所传递节点的位置 var transform=node.getAbsoluteTransform.copy; //为了检测相对位置,我们需要反转变换 变换。反转; //让指针说出鼠标或触摸位置 var pos=node.getStage.getPointerPosition; //现在我们找到相对点 返回transform.pointpos; } 函数usePen{ 让isDrawing=false; 让电流线; 舞台。在“mousedown”上,evt=>{ //开始绘图 isDrawing=true; //创建新线对象 设pos=GetRelativePositionStage; currentLine=新的Konva.Line{ 笔画:“黑色”, 冲程宽度:3, 点数:[位置x,位置y] }; drawLayer.addcurrentLine; }; stage.on'mousemove',evt=>{ 如果!正在绘制{ 回来 } //如果是图形,请向当前直线对象添加新点 设pos=GetRelativePositionStage; 设newPoints=currentLine.points.concat[pos.x,pos.y]; currentLine.points新点; drawLayer.batchDraw; }; 舞台上的“鼠标”,evt=>{ //端部拉深 isDrawing=false; }; } 函数结束笔{ 舞台。离开“鼠标镇; 舞台。离“老鼠洞”远点; 舞台。离“鼠标”远点; } /*-初始化-*/ 二手货; 纸张 手 笔 ->
谢谢!此解决方案解决了指针位置问题!但目前,似乎有可能在米色区域之外绘制。我如何缩放舞台的宽度和高度,以便在缩放时舞台的大小与米色区域的大小完全相等?我希望只能在米色区域上绘图。因为米色区域是模拟纸张的区域。我们不能在纸的外面画画。最好有两层:一层是书桌层,另一层是纸层。纸层在桌子层上。然后,我们可以通过拖动桌面层上的任意位置来移动纸张层,也可以通过鼠标滚轮在桌面层上的任意位置缩放纸张层。而且,任何时候我们只能在纸层上画画。嘿,我自己解决了这个问题。我选择使用组而不是图层进行绘图。通过将背景图像设置为组,我可以检测鼠标指针是否位于组上,并且使用您告诉我的函数计算指针相对于组的相对位置,从而可以在组上正确绘制!谢谢谢谢!此解决方案解决了指针位置问题!但目前,似乎有可能在米色区域之外绘制。我如何缩放舞台的宽度和高度,以便在缩放时舞台的大小与米色区域的大小完全相等?我希望只能在米色区域上绘图。因为米色区域是模拟纸张的区域。我们不能在纸的外面画画。最好有两层:一层是书桌层,另一层是纸层。纸层在桌子层上。然后,我们可以通过拖动桌面层上的任意位置来移动纸张层,也可以通过鼠标滚轮在桌面层上的任意位置缩放纸张层。而且,任何时候我们只能在纸层上画画。嘿,我自己解决了这个问题。我选择使用组而不是图层进行绘图。通过将背景图像设置为组,我可以检测鼠标指针是否位于组上,并且使用您告诉我的函数计算指针相对于组的相对位置,从而可以在组上正确绘制!谢谢