【问题标题】:Optimize canvas drawing to make a continuous path优化画布绘制,使路径连续
【发布时间】:2013-07-04 14:13:21
【问题描述】:

这是一个用红色填充画布网格方块的脚本。 我正在寻找如何优化我的脚本以连续填充正方形的技巧,而不像这里那样切碎:

我试图分离和合并一些函数,但找不到解决方案。 这是updated jsFiddle 和我的代码:


HTML:

<canvas id="plan" width="501px" height="301px"></canvas>

JavaScript(更新):

var canvas = document.getElementById('plan');
var context = canvas.getContext('2d'),
    wt = canvas.width,
    ht = canvas.height;
var down = false;
var draw = function (e) {};

window.onload = grid();

var oldPos = {
    mX: 0,
    mY: 0
};

var dPos = {
    mX: 0,
    mY: 0
};

var curPos = {
    mX: 0,
    mY: 0
};

draw.to = function (X, Y) {
    oldPos = getMousePos(canvas, e); //update position
    var mposX = X,
        mposY = Y;
    mposX = mposX - mposX % 5;
    mposY = mposY - mposY % 5;
    context.fillStyle = "red";
    context.fillRect(mposX + 0.5, mposY + 0.5, 5, 5);
};

draw.single = function (e) {
    oldPos = getMousePos(canvas, e);
    var mpos = getMousePos(canvas, e);
    mpos.mX = mpos.mX - mpos.mX % 5;
    mpos.mY = mpos.mY - mpos.mY % 5;
    context.fillStyle = "red";
    context.fillRect(mpos.mX + 0.5, mpos.mY + 0.5, 5, 5);
};

draw.move = function (e) {
    if (down) {
        curPos = getMousePos(canvas, e);
        dPos.mX = Math.abs(curPos.mX - oldPos.mX); // distance between old & new (delta X)
        dPos.mY = Math.abs(curPos.mY - oldPos.mY); // delta Y
        if (dPos.mX >= 5 || dPos.mY >= 5) { // if the distance is bigger than 5px hz OR 5px vertical
            lightIntermediateSquares(oldPos.mX, oldPos.mY, curPos.mX, curPos.mY); // ^ connect them
        } else {
            draw.single(e); // simple
        }
    }
};

draw.start = function (e) {
    e.preventDefault();
    down = true;
    draw.single(e);
};

draw.stop = function (e) {
    down = false;
};

function lightIntermediateSquares(startX, startY, endX, endY) {
    for (var pct = 0; pct <= 1; pct += 0.03) {
        var dx = endX - startX;
        var dy = endY - startY;
        var X = startX + dx * pct;
        var Y = startY + dy * pct;
        draw.to(X, Y); // is it okay?
    }
}

function grid() {
    context.strokeStyle = "#f0f0f0";
    var h = 2.5,
        p = 2.5;
    context.strokeRect(0.5, 0.5, 5, 5);
    for (i = 0; i < wt; i += p) {
        p *= 2;
        context.drawImage(canvas, p, 0);
    }
    for (i = 0; i < ht; i += h) {
        h *= 2;
        context.drawImage(canvas, 0, h);
    }
}

function getMousePos(canvas, e) {
    var rect = canvas.getBoundingClientRect();
    return {
        mX: e.clientX - rect.left - 1,
        mY: e.clientY - rect.top - 1
    };
}

canvas.addEventListener('mouseup', draw.stop, false);
canvas.addEventListener('mousedown', draw.start, false);
canvas.addEventListener('mousemove', draw.move, false);
canvas.addEventListener('mouseout', draw.stop, false);

【问题讨论】:

    标签: javascript html canvas drawing


    【解决方案1】:

    以下是点亮缺失方块的方法

    计算前一个鼠标移动位置和当前鼠标移动位置之间的一条线。

    然后使用插值法走这条线,并为该线穿过的任何网格方块着色。

            // walk along a line from the last mousemove position
            // to the current mousemove position.
            // Then color any cells we pass over on our walk
            for(var pct=0;pct<=1;pct+=0.06){
                  var dx = mouseX-lastX;
                  var dy = mouseY-lastY;
                  var X = parseInt(lastX + dx*pct);
                  var Y = parseInt(lastY + dy*pct);
                  if( !(X==lastForX && Y==lastForY) ){ 
                      draw.ColorCell(X,Y); 
                  }
    

    这是代码和小提琴:http://jsfiddle.net/m1erickson/WvuHL/

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; }
        canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var context=canvas.getContext("2d");
    
        var canvasOffset=$("#canvas").offset();
        var offsetX=canvasOffset.left;
        var offsetY=canvasOffset.top;
    
    
        var wt = canvas.width;
        var ht = canvas.height;
        var down = false;
    
        var lastX=-20;
        var lastY=-20;
    
        var points=[];
    
        var draw = function (e) {};
    
    
        draw.started = false;
    
        var count;
    
    
        function interpolateLine(startX,startY,endX,endY){
    
            var lastForX;
            var lastForY;
            //
            for(var pct=0;pct<=1;pct+=0.06){
                  var dx = endX-startX;
                  var dy = endY-startY;
                  var X = startX + dx*pct;
                  var Y = startY + dy*pct;
                  if( !(X==lastForX && Y==lastForY) ){ 
                      draw.ColorCell(X,Y); 
                  }
                  lastForX=X;
                  lastForY=Y;
            }
    
        }
    
    
        draw.ColorCell=function(x,y){
            var rw = x - 1;
            var rh = y - 1;
            rw = rw - rw % 5 + 0.5;
            rh = rh - rh % 5 + 0.5;
            context.fillStyle = "red";
            context.fillRect( rw, rh, 5, 5);
        };
    
    
        draw.single = function (e) {
            var mouseX=parseInt(e.clientX-offsetX);
            var mouseY=parseInt(e.clientY-offsetY);
            draw.ColorCell(mouseX,mouseY);
        };
    
    
        // mousemove
        draw.move = function (e) {
    
            if(!down){return;}
    
            // get the current mouse position
            var mouseX=parseInt(e.clientX-offsetX);
            var mouseY=parseInt(e.clientY-offsetY);
    
            // if we haven't moved off this XY, then don't bother processing further
            if(mouseX==lastX && mouseY==lastY){return;}
    
            // When running the for-loop below,
            // many iterations will not find a new grid-cell
            // so lastForX/lastForY will let us skip duplicate XY
            var lastForX=lastX;
            var lastForY=lastY;
    
            // walk along a line from the last mousemove position
            // to the current mousemove position.
            // Then color any cells we pass over on our walk
            for(var pct=0;pct<=1;pct+=0.06){
                  var dx = mouseX-lastX;
                  var dy = mouseY-lastY;
                  var X = parseInt(lastX + dx*pct);
                  var Y = parseInt(lastY + dy*pct);
                  if( !(X==lastForX && Y==lastForY) ){ 
                      draw.ColorCell(X,Y); 
                  }
                  lastForX=X;
                  lastForY=Y;
            }
    
            // set this mouse position as starting position for next mousemove
            lastX=mouseX;
            lastY=mouseY;    
        };
    
    
        // mousedown
        draw.start = function (e) {
            e.preventDefault();
            lastX=parseInt(e.clientX-offsetX);
            lastY=parseInt(e.clientY-offsetY);
            down = true;
        };
    
    
        // mouseup
        draw.stop = function (e) {
            e.preventDefault();
            down = false;
        };
    
    
        function grid() {
            context.strokeStyle = "#f0f0f0";
            var h = 2.5;
            var p = 2.5;
            context.strokeRect(0.5, 0.5, 5, 5);
            for (i = 0; i < wt; i += p) {
                p *= 2;
                context.drawImage(canvas, p, 0);
            }
            for (i = 0; i < ht; i += h) {
                h *= 2;
                context.drawImage(canvas, 0, h);
            }
        }
    
    
        canvas.addEventListener('mouseup', draw.stop, false);
        canvas.addEventListener('mouseout', draw.stop, false);
        canvas.addEventListener('mousedown', draw.start, false);
        canvas.addEventListener('click', draw.single, false);
        canvas.addEventListener('mousemove', draw.move, false);
    
        grid();
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=501 height=301></canvas>
    </body>
    </html>
    

    【讨论】:

    • 哦,我花了两个多小时才写完那部分!请帮助我一点:/(我已经改变了很多,我只需要修复一件事)。我不知道为什么它没有连接到 current 光标位置。它像磁铁一样工作,当您将光标移到您停止的地方附近时,它会吸附到您的光标上。可以看看this?
    • 我采用了您的代码并整合了在最后一次 mousemove 和当前 mousemove 之间为所有网格单元着色的想法。请参阅我编辑的答案。
    • 完美。看起来我需要开始在 JavaScript 中学习 jQuery。谢谢。
    • 既然没有私信,请问jQuery对于web应用是否比纯JS更高效?
    • 是的!尽管 jQuery (JQ) 确实“只是” javascript,但它是非常出色的代码,使用它可以充分利用这种才华。 John Resig(创建者)和所有其他作者一直在与新的 JS 选项和效率保持同步。此外,JQ 消除了跨浏览器的问题,因此编写脚本变成了创建有用的应用程序,而不是追逐跨浏览器的差异。如果您使用 CDN,那么 JQ 可能已经缓存在用户计算机上。如果我只能使用 1 个附加脚本,jQuery 绝对是那个!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 1970-01-01
    • 1970-01-01
    • 2019-04-12
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    相关资源
    最近更新 更多