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); }