如果稍微向下滚动,在画布上拖动文本时出现问题

Posted

技术标签:

【中文标题】如果稍微向下滚动,在画布上拖动文本时出现问题【英文标题】:Issue when dragging text on canvas if slightly scrolled down 【发布时间】:2022-01-19 13:38:21 【问题描述】:

当我在画布上稍微向下滚动时,它根本不允许我拖动文本。示例这些是 GIF)-

https://gyazo.com/e60d2efd924ced758c2c6441391804db

GIF 解释:所以当我在页面顶部但稍微向下滚动时,您看到拖动工作正常。它完全停止工作。我添加了一些console.logs,我知道画布的点击事件监听器正在工作,但是当我在页面上稍微向下滚动时没有检测到文本。

我的拖动代码来自:http://jsfiddle.net/m1erickson/9xAGa/ |你可以看到如果你改变画布大小宽度:667 和高度:800,当你稍微向下滚动时,你会遇到和我一样的问题。

HTML 代码:

<div id="middle_container">
        <div class="center_container">
            <canvas id="canvas"  ></canvas>
        </div>
</div>

JavaScript 代码:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var BB=canvas.getBoundingClientRect();
var offsetX = BB.left;
var offsetY = BB.top;
var mx;
var my;
var texts = [];
var images = [];
var dragF = -1;
var mode = "none";

function draw() 
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for(const  text, x, y, width, height  of texts) 
        ctx.fillText(text, x, y);
    


function addNewText(string_text) 
    var y = texts.length * 20 + 20;
    var text = 
        text: string_text,
        x: 20,
        y: y
    ;
    ctx.font = "32px verdana";
    ctx.textBaseline = "top";
    text.width = ctx.measureText(text.text).width;
    text.height = 32;

    texts.push(text);
    draw();




function hitDrag(x,y,textIndex) 
    var r=texts[textIndex];
    return (x>r.x && x<r.x+r.width && y>r.y && y<r.y+r.height);


function myDrag(a,e) 
    if (a == "down") 
        e.preventDefault();
        e.stopPropagation();
        mx=parseInt(e.clientX-offsetX);
        my=parseInt(e.clientY-offsetY);
        for(var i=0;i<texts.length;i++)
            if(hitDrag(mx,my,i))
                console.log("found");
                dragF = i;
            
        
    


addNewText("Hello World")

$("#canvas").mousedown(function(e) 
    myDrag("down", e);
);

【问题讨论】:

不幸的是,您的代码示例似乎不完整 - 例如它缺少 hitDrag() 的函数定义,我无法发现实际的拖动逻辑。您能否完成它,以便清楚地显示问题? @obscure 我为这个错误道歉。我已经编辑了我的论坛并添加了缺失的功能。 【参考方案1】:

问题出在这行代码:

var BB=canvas.getBoundingClientRect();

仅在脚本开始时填充一次.getBoundingClientRect() 方法将 html 元素 relative 的位置返回到视口。

如果您滚动窗口,视口会移动 - 作为画布元素 - 但 BB 对象在启动时仍保持画布的位置。

修复相当简单 - 您需要通过在鼠标按下和鼠标移动时再次调用 .getBoundingClientRect() 来使用画布元素的实际位置。

我已经根据你的代码和你链接的小提琴准备了一个小样本:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var BB = canvas.getBoundingClientRect();
var offsetX = BB.left;
var offsetY = BB.top;
var mx;
var my;
var texts = [];
var images = [];
var dragF = -1;
var mode = "none";

function draw() 
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (const 
      text,
      x,
      y,
      width,
      height
     of texts) 
    ctx.fillText(text, x, y);
  


function addNewText(string_text) 
  var y = texts.length * 20 + 20;
  var text = 
    text: string_text,
    x: 20,
    y: y
  ;
  ctx.font = "32px verdana";
  ctx.textBaseline = "top";
  text.width = ctx.measureText(text.text).width;
  text.height = 32;

  texts.push(text);
  draw();


function myDrag(a, e) 
  if (a == "down") 
    e.preventDefault();
    e.stopPropagation();
    let rect = canvas.getBoundingClientRect();
    mx = parseInt(e.clientX - rect.left);
    my = parseInt(e.clientY - rect.top);
    for (var i = 0; i < texts.length; i++) 
      if (hitDrag(mx, my, i)) 
        // console.log("found");
        dragF = i;
      
    
  


function hitDrag(x, y, textIndex) 
  var r = texts[textIndex];
  return (x > r.x && x < r.x + r.width && y > r.y && y < r.y + r.height);


function handleMouseMove(e) 
  if (dragF < 0) 
    return;
  
  e.preventDefault();
  let rect = canvas.getBoundingClientRect();
  mouseX = parseInt(e.clientX - rect.left);
  mouseY = parseInt(e.clientY - rect.top);

  var dx = mouseX - mx;
  var dy = mouseY - my;
  mx = mouseX;
  my = mouseY;

  var text = texts[dragF];
  text.x += dx;
  text.y += dy;
  draw();


function handleMouseUp(e) 
  e.preventDefault();
  dragF = -1;


addNewText("Hello World")

$("#canvas").mousedown(function(e) 
  myDrag("down", e);
);

$("#canvas").mousemove(function(e) 
  handleMouseMove(e);
);

$("#canvas").mouseup(function(e) 
  handleMouseUp(e);
);
body 
  background-color: ivory;


#canvas 
  border: 1px solid red;


#theText 
  width: 10em;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="middle_container">
  <div class="center_container">
    <canvas id="canvas"  ></canvas>
  </div>
</div>
<br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br>

【讨论】:

以上是关于如果稍微向下滚动,在画布上拖动文本时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

Photoshop 之类的画布图像可拖放、可缩放的图像在拖动时出现绝对位置问题

在 Chrome 中滚动时出现负 z-index 问题的画布

部分的 UITableView 标题仅在向下滚动时出现

无限滚动在向下滚动到下一页时出现模板错误

在 ncurses 中实现文本滚动的推荐方法是啥?

为啥我的导航栏在向下滚动时不隐藏而在向上滚动时出现?