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

Issue when dragging text on canvas if slightly scrolled down

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

https://gyazo.com/e60d2efd924ced758c2c6441391804db

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

我的拖动代码来自:http://jsfiddle.net/m1erickson/9xAGa/ |您可以看到,如果您将 canvas 尺寸更改为宽度:667 和高度:800,当您稍微向下滚动时,您将遇到与我相同的问题。

HTML代码:

<div id="middle_container">
        <div class="center_container">
            <canvas id="canvas" width="667px" height="800px"></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);
});

问题是这行代码:

var BB=canvas.getBoundingClientRect();

它只在您的脚本开始时填充 一次.getBoundingClientRect() 方法 returns HTML 元素的位置 相对于 视口。

好吧,如果您滚动 window,视口移动 - 作为 canvas 元素 - 但 BB 对象在启动时仍然保持 canvas 的位置.

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

我根据您的代码和您链接的 fiddle 准备了一个小示例:

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" width="667px" height="800px"></canvas>
  </div>
</div>
<br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br>