2017-02-18 69 views
0

我將一個符號繪圖庫從Java移植到Javascript。符號將被繪製到HTML5 Canvas對象中。符號具有座標和形狀(正方形,圓形,十字形等等),大小和顏色的屬性。什麼是在HTML5 Canvas中實現符號繪圖庫的正確方法?

我在Java中有這樣一個工作符號繪圖庫多年。在Javascript中,我很難用顏色。通常用正確的形狀和大小繪製符號,但並不總是使用正確的顏色。一個符號的顏色也可以「流血」到我正在繪製的其他東西,如圖表軸(通常是黑色)。那麼,我該如何繪製一個符號作爲繪圖的「原子」單位,以便對我繪製的其他東西沒有副作用?我覺得我不理解路徑和子路徑的概念以及上下文存儲的狀態。我已經做了大量的搜索解決這個問題的方法,但沒有找到任何可行的方法。

這裏是我的符號庫中的一些典型代碼:

function plotSymbol(ctx, symbol, h, v, width, symcolor) { 
    var i; 
    if (width == 0) return; 

    if (symbol == Resources.PlotSymbolsEnum.SYMBOL_SQUARE) { 
     ctx.strokeStyle = symcolor; 
     ctx.strokeRect(h - width/2.0, v - width/2.0, width, width); 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_SQUAREFILLED) { 
     ctx.fillStyle = symcolor; 
     ctx.fillRect(h - width/2.0, v - width/2.0, width, width); 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_CIRCLE) { 
     var x = h - width/2; 
     var y = v - width/2; 
     drawCircle(ctx, x, y, width/2, 1, symcolor, false); 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_CIRCLEFILLED) { 
     var x = h - width/2; 
     var y = v - width/2; 
     drawCircle(ctx, x, y, width/2, 1, symcolor, true); 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_DIAMOND) { 
     var xpoints1 = [ h, h + width/2, h, h - width/2 ]; 
     var ypoints1 = [ v - width/2, v, v + width/2, v ]; 

     ctx.strokeStyle = symcolor; 
     ctx.beginPath(); 
     ctx.moveTo(xpoints1[0], ypoints1[0]); 
     for (i = 1; i < xpoints1.length; i++) { 
      ctx.lineTo(xpoints1[i], ypoints1[i]); 
     } 
//  ctx.closePath(); 
     ctx.stroke(); 
     ctx.strokeStyle = 'black'; 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_DIAMONDFILLED) { 
     var xpoints2 = [ h, h + width/2, h, h - width/2 ]; 
     var ypoints2 = [ v - width/2, v, v + width/2, v ]; 

     ctx.fillStyle = symcolor; 
     ctx.beginPath(); 
     ctx.moveTo(xpoints2[0], ypoints2[0]); 
     for (i = 1; i < xpoints2.length; i++) { 
      ctx.lineTo(xpoints2[i], ypoints2[i]); 
     } 

//  ctx.closePath(); 
     ctx.fill(); 
     ctx.stroke(); 
     ctx.fillStyle = 'white'; 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_TRIANGLE) { 
     var xpoints3 = [ h - width/2, h + width/2, h ]; 
     var ypoints3 = [ v + width/2, v + width/2, v - width/2 ]; 

     ctx.strokeStyle = symcolor; 
     ctx.beginPath(); 
     ctx.moveTo(xpoints3[0], ypoints3[0]); 
     for (i = 1; i < xpoints3.length; i++) { 
      ctx.lineTo(xpoints3[i], ypoints3[i]); 
     } 

//  ctx.closePath(); 
     ctx.stroke(); 
     ctx.strokeStyle = 'black'; 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_TRIANGLEFILLED) { 
     var xpoints3 = [ h - width/2, h + width/2, h ]; 
     var ypoints3 = [ v + width/2, v + width/2, v - width/2 ]; 

     ctx.strokeStyle = symcolor; 
     ctx.beginPath(); 
     ctx.moveTo(xpoints3[0], ypoints3[0]); 
     for (i = 1; i < xpoints3.length; i++) { 
      ctx.lineTo(xpoints3[i], ypoints3[i]); 
     } 

//  ctx.closePath(); 
     ctx.fill(); 
     ctx.stroke(); 
     ctx.strokeStyle = 'black'; 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_CROSS1) { 
     ctx.strokeStyle = symcolor; 
     width += 1; 
     ctx.beginPath(); 
     ctx.moveTo(h - width/2, v); 
     ctx.lineTo(h + width/2, v); 
     ctx.moveTo(h, v - width/2); 
     ctx.lineTo(h, v + width/2); 
//  ctx.closePath(); 
     ctx.stroke(); 
     ctx.strokeStyle = 'black'; 
    } 
    else if (symbol == Resources.PlotSymbolsEnum.SYMBOL_CROSS2) { 
     ctx.strokeStyle = symcolor; 
     ctx.beginPath(); 
     ctx.moveTo(h - width/2, v - width/2); 
     ctx.lineTo(h + width/2, v + width/2); 
     ctx.moveTo(h - width/2, v + width/2); 
     ctx.lineTo(h + width/2, v - width/2); 
//  ctx.closePath(); 
     ctx.stroke(); 
     ctx.strokeStyle = 'black'; 
    } 
} 

我已經註釋掉closepaths,因爲我並不總是想要的形狀返回到原點。我想我把它們放在最初是因爲我誤解了closePath()所做的事情,並認爲它們會繪製獨立於其他符號的符號。

這裏是它如何被稱爲:

ctx.save(); 
ctx.rect(left, y1, width, height); 
ctx.clip(); 
. 
. 
. 
y = this.mMonthlyMeans[i]; 
y = (y - yOrigin) * yScale; 
y = Math.floor(y) + 0.5; 
plotSymbol(ctx, theMeanSym, this.getPlotLeft() + xCtr, y, theMeanSymSize, theMeanSymbolColor); 
ctx.strokeStyle = 'black'; // this call is perhaps unnecessary in properly written code but seems to head off some problems 
. 
. 
. 
ctx.restore() // to restore the clip 

我將不勝感激在HTML5畫布正確地做這個有什麼建議和指針。它似乎並不簡單到只是繪製像素成Graphics2D對象,如Java,

回答

0

你應該叫ctx.stroke()ctx.strokeXXX()之前設置strokeStyle,並且ctx.fill()ctx.fillXXX()之前設置fillStyle,在每個條件塊的。

you missed strokeStyle in SYMBOL_DIAMONDFILLED block and fillStyle in SYMBOL_TRIANGLEFILLED block。

+0

感謝您指出那些遺漏! –

0

我相信我找到了解決方案。谷歌搜索今天我找到了一個教程(http://eloquentjavascript.net/16_canvas.html)繪製到畫布對象。作者聲明:

「一個路徑可以包含多個形狀 - 每moveTo運動開始一個新的。」

這是尋找的線索。我有使用moveTo和lineTo繪製交叉和x符號的方法。這是我的十字符號的代碼(從Java移植)看了喜歡:

ctx.strokeStyle = symcolor; 
    ctx.beginPath(); 
    ctx.moveTo(h - width/2, v); 
    ctx.lineTo(h + width/2, v); 
    ctx.moveTo(h, v - width/2); 
    ctx.lineTo(h, v + width/2); 
    ctx.stroke(); 

的錯誤是內部的moveTo開始一個新的子路徑和衝程命令似乎僅使第一子路徑中的StrokeStyle顏色或使用默認顏色。最終結果是大多數符號都以正確的顏色繪製,但是(我認爲)最後一個符號是以默認的顏色繪製的,看起來是黑色的。

更改代碼,使我行程段分別導致所有的符號在正確的顏色可以得出:

ctx.strokeStyle = symcolor; 
    ctx.beginPath(); 
    ctx.moveTo(h - width/2, v); 
    ctx.lineTo(h + width/2, v); 
    ctx.stroke(); 

    ctx.beginPath(); 
    ctx.moveTo(h, v - width/2); 
    ctx.lineTo(h, v + width/2); 
    ctx.stroke(); 
相關問題