一段时间后画布停止跟踪鼠标

时间:2017-10-06 06:54:11

标签: javascript html5-canvas electron

我有一种奇怪的错误,我很难搞清楚。首先,这里是代码:



const canvas = document.getElementById('canvas');
const canvasContainer = document.getElementById('canvas-container');
const ctx = canvas.getContext('2d');


function resizeCanvas() {
    canvas.width = canvasContainer.clientWidth;
    canvas.height = canvasContainer.clientHeight;
}



async function init() {
    window.addEventListener('resize', resizeCanvas)
    resizeCanvas();



    window.requestAnimationFrame(draw);

    let poly = [];

    canvas.addEventListener('click', ev => {
        let x = ev.clientX - canvas.offsetLeft;
        let y = ev.clientY - canvas.offsetTop;
        poly.push([x,y]);
    })



    window.addEventListener('keyup', ev => {
        if(ev.key === 'Escape') {
            poly.length = 0;
        }
    });

    let mousePos = null;

    canvas.addEventListener('mouseleave', ev => {
        mousePos = null;
    })

    canvas.addEventListener('mousemove', ev => {
        let x = ev.clientX - canvas.offsetLeft;
        let y = ev.clientY - canvas.offsetTop;
        mousePos = {x,y};
        console.log(x,y);
    })



    function draw() {
        // ctx.save();

        ctx.fillStyle = '#ADD5F8';

        ctx.fillRect(0, 0, canvas.width, canvas.height);

        ctx.fillStyle = '#C38F4C';

        if(poly.length >= 3) {
            ctx.beginPath();
            ctx.moveTo(...poly[0]);
            for(let i=1; i<poly.length; ++i) {
                ctx.lineTo(...poly[i]);
            }
            ctx.closePath();
            ctx.fill();
        }

        if(poly.length && mousePos) {
            ctx.beginPath();
            ctx.moveTo(...poly[0]);
            for(let i=1; i<poly.length; ++i) {
                ctx.lineTo(...poly[i]);
            }
            if(mousePos) {
                console.log(mousePos);
                ctx.lineTo(mousePos.x, mousePos.y);
            }
            ctx.strokeStyle = '#ff0000';
            ctx.stroke();
        }


        window.requestAnimationFrame(draw);
    }
}

function createImage(path) {
    return new Promise((resolve,reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = err => reject(err);
        img.src = path;
    })
}

async function createPattern(path, repetition='repeat') {
    // TODO: https://stackoverflow.com/a/21128933/65387
    const img = await createImage(path);
    return ctx.createPattern(img, repetition);
}



init();

// TODO: add physics https://github.com/shakiba/planck.js
&#13;
* {
    box-sizing: border-box;
}

.toolbox {
    width: 100px;
    background-color: #535353;
}

.content {
    overflow: hidden;
    background-color: green;
    flex: 1;
}

.main {
    display: flex;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;

}
&#13;
    <div class="main">
      <div class="toolbox">toolbox</div>
      <div id="canvas-container" class="content">
        <canvas id="canvas"></canvas>
      </div>
    </div>
&#13;
&#13;
&#13;

有趣的是,它似乎在这个小提琴中工作得很好。但是当我在Electron下运行它时,this is what happens(gifv链接) - (请忽略光标在视频中有点偏离的事实 - 我的屏幕录像机搞砸了) - 但请注意,只需点击几下,最后一条红线就会搞砸。

当我移动鼠标时,mousemove处理程序中的console.log会触发,并且它会记录正确的坐标。但是,我在mousePos中使用的draw() var会固定在某个位置,然后不再更新。

我在每次鼠标移动事件中都更新了相同的变量,我不明白这两个console.logs会有什么不同?

如果我这样记录,watch what happens

canvas.addEventListener('mousemove', ev => {
    let x = ev.clientX - canvas.offsetLeft;
    let y = ev.clientY - canvas.offsetTop;
    mousePos = {x,y};
    console.log('a',x,y);
})



function draw() {
    if(mousePos) {
        console.log('b', mousePos.x, mousePos.y);
    }

&#34; B&#34;卡在{102,570},即使&#34; a&#34;不断更新。它是同一个变量!

1 个答案:

答案 0 :(得分:1)

奇怪的行为,解决方案

让我看到你的代码的第一件事就是主init函数被定义为async函数,但却没有等待。

我不确定没有async的{​​{1}}函数的预期行为,但问题似乎发生在同一时间段之后。

这是一个有趣的问题,值得进一步研究。在spec (async function definitions)中有很多东西需要阅读,快速浏览并没有显示任何明显的原因。

轻松修复。

修复很简单,从函数await中移除async令牌,一切正常。

更改

init

async function init() {

实施例

function init() {
const canvas = document.getElementById('canvas');
const canvasContainer = document.getElementById('canvas-container');
const ctx = canvas.getContext('2d');


function resizeCanvas() {
    canvas.width = canvasContainer.clientWidth;
    canvas.height = canvasContainer.clientHeight;
}



function init() {
    window.addEventListener('resize', resizeCanvas)
    resizeCanvas();



    window.requestAnimationFrame(draw);

    let poly = [];

    canvas.addEventListener('click', ev => {
        let x = ev.clientX - canvas.offsetLeft;
        let y = ev.clientY - canvas.offsetTop;
        poly.push([x,y]);
    })



    window.addEventListener('keyup', ev => {
        if(ev.key === 'Escape') {
            poly.length = 0;
        }
    });

    let mousePos = null;

    canvas.addEventListener('mouseleave', ev => {
        mousePos = null;
    })

    canvas.addEventListener('mousemove', ev => {
        let x = ev.clientX - canvas.offsetLeft;
        let y = ev.clientY - canvas.offsetTop;
        mousePos = {x,y};


    })



    function draw() {
        // ctx.save();

        ctx.fillStyle = '#ADD5F8';

        ctx.fillRect(0, 0, canvas.width, canvas.height);

        ctx.fillStyle = '#C38F4C';

        if(poly.length >= 3) {
            ctx.beginPath();
            ctx.moveTo(...poly[0]);
            for(let i=1; i<poly.length; ++i) {
                ctx.lineTo(...poly[i]);
            }
            ctx.closePath();
            ctx.fill();
        }

        if(poly.length && mousePos) {
            ctx.beginPath();
            ctx.moveTo(...poly[0]);
            for(let i=1; i<poly.length; ++i) {
                ctx.lineTo(...poly[i]);
            }
            if(mousePos) {
     
                ctx.lineTo(mousePos.x, mousePos.y);
            }
            ctx.strokeStyle = '#ff0000';
            ctx.stroke();
        }


        window.requestAnimationFrame(draw);
    }
}

function createImage(path) {
    return new Promise((resolve,reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = err => reject(err);
        img.src = path;
    })
}

async function createPattern(path, repetition='repeat') {
    // TODO: https://stackoverflow.com/a/21128933/65387
    const img = await createImage(path);
    return ctx.createPattern(img, repetition);
}



init();

// TODO: add physics https://github.com/shakiba/planck.js
* {
    box-sizing: border-box;
}

.toolbox {
    width: 100px;
    background-color: #535353;
}

.content {
    overflow: hidden;
    background-color: green;
    flex: 1;
}

.main {
    display: flex;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;

}