Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 滚动时如何保持在画布上绘制?_Javascript_Canvas_Html5 Canvas - Fatal编程技术网

Javascript 滚动时如何保持在画布上绘制?

Javascript 滚动时如何保持在画布上绘制?,javascript,canvas,html5-canvas,Javascript,Canvas,Html5 Canvas,我想实现画布作为我的网站的背景,这样用户就可以使用他们的光标在网页上绘制如下代码笔: (这是来自的示例代码) 问题是当我滚动时光标停止绘制,直到我再次移动鼠标。有没有关于如何在滚动时保持光标绘制的想法 提前谢谢!非常感谢 您必须存储最后一个鼠标事件,并在滚动事件中触发一个新的假鼠标事件 幸运的是,接受一个mouseEventInit对象,我们可以在该对象上设置新事件的clientX和clientY值,因此我们只需要存储上一个事件中的这些值,并将其发送到scroll事件中 现在,我不得不重写您代码

我想实现画布作为我的网站的背景,这样用户就可以使用他们的光标在网页上绘制如下代码笔: (这是来自的示例代码)

问题是当我滚动时光标停止绘制,直到我再次移动鼠标。有没有关于如何在滚动时保持光标绘制的想法


提前谢谢!非常感谢

您必须存储最后一个鼠标事件,并在滚动事件中触发一个新的假鼠标事件

幸运的是,接受一个mouseEventInit对象,我们可以在该对象上设置新事件的
clientX
clientY
值,因此我们只需要存储上一个事件中的这些值,并将其发送到
scroll
事件中

现在,我不得不重写您代码中的几乎所有内容。
它对旧浏览器进行了大量检查(比如非常旧的浏览器,无论如何都不应该再面对网络),如果您愿意,您可能希望再次添加它。
它没有清除上下文,这意味着每次它画一条新的线时,它也会在自己身上画上以前的线,导致更粗的线,开始时有很多噪音,最后是更平滑的线。
这可以通过多种方式修复,不那么麻烦的方法是在每一帧清除上下文。 为了获得相对鼠标位置,它现在使用事件的clientX和clientY属性

其余的更改将在代码段中进行注释

window.addEventListener('load',function(){
const canvas=document.getElementById('imageView');
context=canvas.getContext(“2d”);
let last_event;//我们将在此处存储鼠标事件
//现在我们听一下文档上的mousemove事件,
//不仅在画布上
文件。添加的文件列表器(“mousemove”,ev_mousemove);
document.addEventListener('scroll',fireLastMouseEvent,{capture:true});
//获取光标的初始位置
//即使老鼠从不动
//我们监听文档根元素上的一个mouseenter事件
//不幸的是,这在Chrome中似乎不起作用
document.documentElement.addEventListener(“mouseenter”,ev_mousemove,{once:true});
//在滚动事件中调用
函数fireLastMouseEvent(){
if(上次事件){
//使用相同的clientX和clientY值在文档上触发新事件
document.dispatchEvent(新的MouseeEvent(“mousemove”,最后一个事件));
}
}
//mousemove事件处理程序。
功能ev_鼠标移动(ev){
const previous_evt=最后一个事件| |{};
const was_offscreen=先前的_evt.offscreen;
//仅适用于“真实”鼠标事件
如果(电动汽车不受信任){
//将clientX和clientY道具存储在对象中
常数{clientX,clientY}=ev;
last_event={clientX,clientY};
}
//从鼠标事件获取相对的x和y位置
常量点=getRelativePointFromEvent(ev,画布);
//检查是否超出“画布”视口
如果(点.x<0 | |点.y<0 | |点.x>canvas.width | |点.y>canvas.height){
//还记得我们吗
last_event.offscreen=真;
//如果我们已经画了,就不要画了
if(was_offscreen){return;}
}
//我们从屏幕外来到屏幕内
否则如果(在屏幕外){
//移动到屏幕外记录的上一点
const previous_point=getRelativePointFromEvent(previous_evt,画布);
moveTo(上一个点x,上一个点y);
}
//将新点添加到上下文的子路径定义中
lineTo(点x,点y);
//清除以前的图形
clearRect(0,0,canvas.width,canvas.height);
//再画一遍
stroke();
}
函数getRelativePointFromEvent(ev,elem){
//首先找到元素的边界矩形
常量bbox=elem.getBoundingClientRect();
//从客户端坐标中减去边界矩形
常数x=ev.clientX-bbox.left;
const y=ev.clientY-bbox.top;
返回{x,y};
}
});
#容器{
宽度:400px;
高度:200px;
溢出:自动;
边框:1px实心;
}
#图像视图{边框:1px实心#000;}
帆布{
利润率:100像素;
}


你好,凯伊多,这太完美了,非常感谢!谢谢你的详细解释!但是,如果用户开始直接滚动而不移动鼠标,我应该如何更改您的代码以确保光标也会绘制?或者,在用户移动鼠标之前,浏览器不可能获取鼠标位置吗?@CocoYuan我认为您应该能够听到
mouseenter
事件,我认为应该在页面加载时激发documentElement。它在Safari和Firefox中是这样的,但在Chrome中不是这样的,我们显然运气不好,因为在这个浏览器中,他们甚至看不到documentElement一直在
:鼠标移动之前悬停
。嗨,Kaido,这是一个很好的工作代码,但是我的网站性能因为画布而遇到了问题。我用这个画布作为我的一页网站的背景,这是相当长的,我注意到在网站上呆了一段时间后,绘图变得缓慢和滞后。所以我想知道我们是否可以这样做:(如果你继续画,你可以看到它只画了一条固定长度的线),因为这可能会有助于它的性能?非常感谢。我想我也会就此提出另一个问题。你可以添加简单的检查,以避免鼠标在画布外时绘图。是的,如果我有时间,我明天会编辑。
if(window.addEventListener) {
window.addEventListener('load', function () {
  var canvas, context;

  // Initialization sequence.
  function init () {
    // Find the canvas element.
    canvas = document.getElementById('imageView');
    if (!canvas) {
      alert('Error: I cannot find the canvas element!');
      return;
    }

    if (!canvas.getContext) {
      alert('Error: no canvas.getContext!');
      return;
    }

    // Get the 2D canvas context.
    context = canvas.getContext('2d');
    if (!context) {
      alert('Error: failed to getContext!');
      return;
    }

    // Attach the mousemove event handler.
    canvas.addEventListener('mousemove', ev_mousemove, false);
  }

  // The mousemove event handler.
  var started = false;
  function ev_mousemove (ev) {
    var x, y;

    // Get the mouse position relative to the canvas element.
    if (ev.layerX || ev.layerX == 0) { // Firefox
      x = ev.layerX;
      y = ev.layerY;
    } else if (ev.offsetX || ev.offsetX == 0) { // Opera
      x = ev.offsetX;
      y = ev.offsetY;
    }

    // The event handler works like a drawing pencil which tracks the mouse 
    // movements. We start drawing a path made up of lines.
    if (!started) {
      context.beginPath();
      context.moveTo(x, y);
      started = true;
    } else {
      context.lineTo(x, y);
      context.stroke();
    }
  }

  init();
}, false); }