2012-07-20 177 views
2

我做的HTML畫布一些工作,我發現,當我畫一條線,我無法清除或繪製了呢?HTML畫布繪製清晰的線條

所以我在做什麼:我有一個網格畫布,其中每個單元格繪製自己(一個填充的矩形,完成頁面加載),當鼠標在網格上時,鼠標所在的單元格應概述(在畫布上繪製四行不再重繪)。當鼠標移動到不同的小區中的新的小區應當概述(如前)和先前概述的細胞不應再被概述(意圖是重繪細胞,畫在線)。這是'未概述'被證明是問題的細胞。

我以爲這與畫家的算法工作,即在畫布上繪製的最後一件事是可見的,但我發現效果表明,填充形狀和線條都具有更高的層上線分開處理?

這裏的來源一個獨立的頁面進行論證:

<!DOCTYPE html> 
<html> 

<head> 

<script type="text/javascript"> 


var CANVAS_DIMENSION = 200; 
var CANVAS_WIDTH = 10; 
var CANVAS_HEIGHT = 10; 

var GRID_CELL_WIDTH = CANVAS_DIMENSION/CANVAS_WIDTH; 
var GRID_CELL_HEIGHT = CANVAS_DIMENSION/CANVAS_HEIGHT; 

var canvas; 
var context; 
var grid; 
var mouseCellColumn = -1; 
var mouseCellRow = -1; 

function init() 
{ 
    canvas = document.getElementById("myCanvas"); 

    context = canvas.getContext("2d"); 

    canvas.addEventListener('mousemove', updateMousePosition, false); 

    grid = new Array(CANVAS_WIDTH); 
    for (var i = 0; i < CANVAS_WIDTH; ++i) 
    { 
     grid[i] = new Array(CANVAS_HEIGHT); 

     for (var j = 0; j < CANVAS_HEIGHT; ++j) 
     { 
      grid[i][j] = "#0000FF"; 
     } 
    } 

    renderScene() 
} 


function updateMousePosition(event) 
{ 
    var initialColumn = mouseCellColumn; 
    var initialRow = mouseCellRow; 

    var objectPosition = findPos(this); 

    var gridPosition = new Point(event.pageX - objectPosition.x, event.pageY - objectPosition.y); 

    mouseCellColumn = getColumn(gridPosition.x); 

    mouseCellRow = getRow(gridPosition.y); 

    var cell_position = getCellPosition(mouseCellColumn, mouseCellRow); 

    // outline the current cell 
    drawRectangleOutlineWithColour(cell_position.x, 
            cell_position.y, 
            GRID_CELL_WIDTH, 
            GRID_CELL_HEIGHT, 
            "#FF0000"); 

    // if mouse has moved cell redraw 
    if (((initialColumn != mouseCellColumn) || 
     (initialRow != mouseCellRow)) && 
     (initialColumn > -1) && 
     (initialRow > -1)) 
    { 
     renderGridCell(initialColumn, initialRow); 
    } 

} 


function renderScene() 
{ 
    for (var i = 0; i < CANVAS_WIDTH; ++i) 
    { 
     for (var j = 0; j < CANVAS_HEIGHT; ++j) 
     { 
      renderGridCell(i, j);     
     } 
    } 
} 


function renderGridCell(Column, Row) 
{ 
    var position = getCellPosition(Column, Row); 

    drawRectangleWithColour(position.x, 
          position.y, 
          GRID_CELL_WIDTH, 
          GRID_CELL_HEIGHT, 
          grid[Column][Row]); 
} 


function drawRectangleWithColour(minX, minY, width, height, colour) 
{ 
    context.fillStyle = colour; 

    context.fillRect(minX, 
        minY, 
        width, 
        height); 
} 


function drawRectangleOutlineWithColour(minX, minY, width, height, colour) 
{ 
    context.strokeStyle = colour; 

    context.moveTo(minX, minY); 
    context.lineTo(minX + width, minY); 
    context.moveTo(minX + width, minY); 
    context.lineTo(minX + width, minY + height); 
    context.moveTo(minX + width, minY + height); 
    context.lineTo(minX, minY + height); 
    context.moveTo(minX, minY + height); 
    context.lineTo(minX, minY); 

    context.stroke(); 
} 


function Point(x, y) 
{ 
    this.x = x; 
    this.y = y; 
} 

function getColumn(xPosition) 
{ 
    if (xPosition < 0) 
    { 
     xPosition = 0; 
    } 

    if (xPosition > CANVAS_DIMENSION) 
    { 
     xPosition = CANVAS_DIMENSION; 
    } 

    return Math.floor(xPosition/GRID_CELL_WIDTH); 
} 

function getRow(yPosition) 
{ 
    if (yPosition < 0) 
    { 
     yPosition = 0; 
    } 

    if (yPosition > CANVAS_DIMENSION) 
    { 
     yPosition = CANVAS_DIMENSION; 
    } 

    return Math.floor(yPosition/GRID_CELL_HEIGHT); 
} 

function getCellPosition(column, row) 
{ 
    if (row < 0) 
    { 
     row = 0; 
    } 

    if (row > CANVAS_HEIGHT) 
    { 
     row = CANVAS_HEIGHT - 1; 
    } 

    if (column < 0) 
    { 
     row = 0; 
    } 

    if (column > CANVAS_WIDTH) 
    { 
     column = CANVAS_WIDTH - 1; 
    } 

    var result = new Point(column * GRID_CELL_WIDTH, row * GRID_CELL_HEIGHT); 
    return result; 
} 


function findPos(obj) 
{ 
    var result = new Point(0, 0); 

    if (obj.offsetParent) 
    { 
     do 
     { 
      result.x += obj.offsetLeft; 
      result.y += obj.offsetTop; 
     } while (obj = obj.offsetParent); 
    } 

    return result; 
} 


</script> 
</head> 

<body onload="init()"> 


<div id="test" style="width: 200px; height:200px; margin: 0px auto;"> 
    <canvas id="myCanvas" width="200" height="200"> 
    Your browser does not support the canvas element. 
    </canvas> 
</div> 

</body> 
</html> 

有問題的區域是在這裏:

// outline the current cell 
drawRectangleOutlineWithColour(cell_position.x, 
           cell_position.y, 
           GRID_CELL_WIDTH, 
           GRID_CELL_HEIGHT, 
           "#FF0000"); 

// if mouse has moved cell redraw 
if (((initialColumn != mouseCellColumn) || 
    (initialRow != mouseCellRow)) && 
    (initialColumn > -1) && 
    (initialRow > -1)) 
{ 
    renderGridCell(initialColumn, initialRow); 
} 

,沒有任何效果,輪廓積累。

一些挖掘到畫布上重繪建議「clearRect」但這似乎並沒有幫助,輪廓堅持:

// outline the current cell 
drawRectangleOutlineWithColour(cell_position.x, 
           cell_position.y, 
           GRID_CELL_WIDTH, 
           GRID_CELL_HEIGHT, 
           "#FF0000"); 

// if mouse has moved cell redraw 
if (((initialColumn != mouseCellColumn) || 
    (initialRow != mouseCellRow)) && 
    (initialColumn > -1) && 
    (initialRow > -1)) 
{ 
    context.clearRect(position.x, 
         position.y, 
         GRID_CELL_WIDTH, 
         GRID_CELL_HEIGHT); 

    renderGridCell(initialColumn, initialRow); 
} 

讓我們具體重繪外形部位用不同的顏色?

// outline the current cell 
drawRectangleOutlineWithColour(cell_position.x, 
           cell_position.y, 
           GRID_CELL_WIDTH, 
           GRID_CELL_HEIGHT, 
           "#FF0000"); 

// if mouse has moved cell redraw 
if (((initialColumn != mouseCellColumn) || 
    (initialRow != mouseCellRow)) && 
    (initialColumn > -1) && 
    (initialRow > -1)) 
{ 
    var position = getCellPosition(initialColumn, initialRow); 

    drawRectangleWithColour(position.x, 
          position.y, 
          GRID_CELL_WIDTH, 
          GRID_CELL_HEIGHT, 
          "#00FF00"); 
} 

不,網格重繪,但它對線條沒有影響。重新繪製整個網格?

renderScene(); 

    // outline the current cell 
    drawRectangleOutlineWithColour(cell_position.x, 
            cell_position.y, 
            GRID_CELL_WIDTH, 
            GRID_CELL_HEIGHT, 
            "#FF0000"); 
/* 
    // if mouse has moved cell redraw 
    if (((initialColumn != mouseCellColumn) || 
     (initialRow != mouseCellRow)) && 
     (initialColumn > -1) && 
     (initialRow > -1)) 
    { 
     var position = getCellPosition(initialColumn, initialRow); 

     drawRectangleWithColour(position.x, 
           position.y, 
           GRID_CELL_WIDTH, 
           GRID_CELL_HEIGHT, 
           "#00FF00"); 
    } 
*/ 

我似乎無法找到的畫布是如何處理這個,我得到的Safari MacOSX上與Chrome和Firefox上的Windows7相同的行爲一個很好的解釋。

回答

4

有兩件事情怎麼回事。

第一個也是最重要的是,你永遠不會調用context.beginPath()

你以爲你是繪製一個新的紅色輪廓,實際上是增加了上下文的當前路徑,並使其不再每次。第一次的情況下只有一個矩形,然後它有兩個,那麼它有三個等

每次你打電話給你的撫摸着你曾經繪製每一個矩形的行程時間,因爲上下文的當前路徑包括他們所有。要解決此問題,您必須通過調用beginPath來重置當前路徑。

的第二個問題是,你的線未被繪製上完美的像素,所以當你去清除它們,你會看到,由於反走樣圖形的問題。要解決這個問題,你需要畫出完美的像素,並小心你正在擦除的矩形。欲瞭解更多關於此看到Loktar的答案在這裏:HTML5 Canvas and Line Width

這裏是你的代碼,與這兩個補丁來實現:

http://jsfiddle.net/QjKAp/

+0

感謝這個整理,並感謝完美像素的東西太多。 – Paddy 2012-07-20 21:31:40