2013-07-29 49 views
2

我正在製作一個簡單的HTML5 Canvas繪圖應用程序,其中每次鼠標移動時將一個圓圈放置在x和y位置。 (相當常見但未解決的)問題是:當鼠標移動速度非常快時(因爲鼠標移動事件觸發的速度比較快),最終會在圓圈之間留出空間。畫布:如何使用Bresenham的線算法在兩點之間插值?

我已經使用Bresenham的線算法有點成功地繪製了間隙之間的圓圈。但是,我遇到了另一個問題:當顏色是半透明的顏色時,我會無意中淡化到黑暗的效果。

下面是一個例子:

http://i.stack.imgur.com/wY4BM.png

我不明白爲什麼會這樣。如何使用Bresenham的線算法在兩點之間插值?或者其他一些算法?

這裏是我的代碼:http://jsfiddle.net/E5NBs/

var x = null; 
var y = null; 
var prevX = null; 
var prevY = null; 
var spacing = 3; 
var drawing = false; 
var size = 5; 
var canvas = document.getElementById('myCanvas'); 
var context = canvas.getContext('2d'); 

function createFlow(x1, y1, x2, y2, callback) { 
    var dx = x2 - x1; 
    var sx = 1; 
    var dy = y2 - y1; 
    var sy = 1; 
    var space = 0; 

    if (dx < 0) { 
     sx = -1; 
     dx = -dx; 
    } 

    if (dy < 0) { 
     sy = -1; 
     dy = -dy; 
    } 

    dx = dx << 1; 
    dy = dy << 1; 

    if (dy < dx) { 
     var fraction = dy - (dx >> 1); 

     while (x1 != x2) { 
      if (fraction >= 0) { 
       y1 += sy; 
       fraction -= dx; 
      } 

      fraction += dy; 
      x1 += sx; 

      if (space == spacing) { 
       callback(x1, y1); 
       space = 0; 
      } else { 
       space += 1; 
      } 
     } 
    } else { 
     var fraction = dx - (dy >> 1); 

     while (y1 != y2) { 
      if (fraction >= 0) { 
       x1 += sx; 
       fraction -= dy; 
      } 

      fraction += dx; 
      y1 += sy; 

      if (space == spacing) { 
       callback(x1, y1); 
       space = 0; 
      } else { 
       space += 1; 
      } 
     } 
    } 

    callback(x1, y1); 
} 

context.fillStyle = '#FFFFFF'; 
context.fillRect(0, 0, 500, 400); 

canvas.onmousemove = function(event) { 
    x = parseInt(this.offsetLeft); 
    y = parseInt(this.offsetTop); 

    if (this.offsetParent != null) { 
     x += parseInt(this.offsetParent.offsetLeft); 
     y += parseInt(this.offsetParent.offsetTop); 
    } 

    if (navigator.appVersion.indexOf('MSIE') != -1) { 
     x = (event.clientX + document.body.scrollLeft) - x; 
     y = (event.clientY + document.body.scrollTop) - y; 
    } else { 
     x = event.pageX - x; 
     y = event.pageY - y; 
    } 

    context.beginPath(); 
    if (drawing == true) { 
     if (((x - prevX) >= spacing || (y - prevY) >= spacing) || (prevX - x) >= spacing || (prevY - y) >= spacing) { 
      createFlow(x, y, prevX, prevY, function(x, y) { 
       context.fillStyle = 'rgba(0, 0, 0, 0.1)'; 
       context.arc(x, y, size, 0, 2 * Math.PI, false); 
       context.fill(); 
      }); 

      prevX = x, prevY = y; 
     } 
    } else { 
     prevX = x, prevY = y; 
    } 
}; 

canvas.onmousedown = function() { 
    drawing = true; 
}; 

canvas.onmouseup = function() { 
    drawing = false; 
}; 

回答

0

我已經想通了。

「context.beginPath();」需要在這樣的createFlow回調函數:

createFlow(x, y, prevX, prevY, function(x, y) { 
    context.beginPath(); 
    context.fillStyle = 'rgba(0, 0, 0, 0.1)'; 
    context.arc(x, y, size, 0, 2 * Math.PI, false); 
    context.fill(); 
}); 
0

HTML畫布支持小數/浮點座標,因此使用的算法整數座標基於像素的畫布是沒有必要的,可以被視爲甚至適得其反。

一個簡單,通用的解決方案將是沿着這些路線的東西:

when mouse_down: 
    x = mouse_x 
    y = mouse_y 
    draw_circle(x, y) 
    while mouse_down: 
    when mouse_moved: 
     xp = mouse_x 
     yp = mouse_y 
     if (x != xp or y != yp): 
     dir = atan2(yp - y, xp - x) 
     dist = sqrt(pow(xp - x, 2), pow(yp - y), 2) 
     while (dist > 0): 
      x = x + cos(dir) 
      y = y + sin(dir) 
      draw_circle(x, y) 
      dist = dist - 1 

也就是說,只要將鼠標移動到從最後一圈得出的位置不同的位置,步行走向新的位置,步距爲1。

+0

也許我不完全明白你在說什麼,因爲這是我可以得到的最好結果:[鏈接](http: //i.imgur.com/EX0h7D4.png?1?1054) –

0

如果我理解的很好,你想每個點都有rgba(0, 0, 0, 0.1)。如果是這樣,那麼您可以在繪製新點之前清除該點。

// this is bad way to clear the point, just I don't know canvas so well 
context.fillStyle = 'rgba(255, 255, 255, 1)'; 
context.arc(x, y, size, 0, 2 * Math.PI, false); 
context.fill(); 

context.fillStyle = 'rgba(0, 0, 0, 0.1)'; 
context.arc(x, y, size, 0, 2 * Math.PI, false); 
context.fill();