简体   繁体   中英

Javascript Canvas Draw Order

I am plotting a bar chart with some series values in a javascript loop. Even though the code drawing the series values lies below the code that draws the bars, in the next iteration of the loop the text that has just been drawn gets overwritten.

You can see this effect taking place in the code below as the alert boxes appear.

Why do drawing operations on another part of the canvas overwrite something drawn previously in a completely different place?

Update: Someone has helpfully pointed out that using fillRect() hides this issue, but my question is rather: why is it happening in the first place?

 var exampleData = { "Series 1": 10, "Series 2": 14, "Series 3": 2, "Series 4": 12 }; var BarChart = function(options) { this.options = options; this.canvas = options.canvas; this.ctx = this.canvas.getContext("2d"); this.colors = options.colors; this.plot = function() { var maxValue = 0; for (var categ in this.options.data) { maxValue = Math.max(maxValue, this.options.data[categ]); } var noBars = Object.keys(this.options.data).length; var barWidth = (this.canvas.height) / noBars; var barIdx = 0; for (categ in this.options.data) { var barLength = Math.round(this.canvas.width * this.options.data[categ] / maxValue); this.ctx.save(); alert("plotting series line " + categ); this.ctx.fillStyle = this.colors[barIdx % this.colors.length]; this.ctx.rect(30, barIdx * barWidth, barLength, barWidth); this.ctx.fill(); alert("plotting series value " + categ); this.ctx.fillStyle = "#000000"; this.ctx.font = "24px Georgia"; this.ctx.textBaseline = "middle"; this.ctx.fillText(this.options.data[categ], 25, barIdx * barWidth + barWidth / 2); //will be covered in the loop's next iteration. Why? this.ctx.restore(); barIdx++; } } } function init() { var myCanvas = document.getElementById("myCanvas"); myCanvas.width = 800; myCanvas.height = 300; var ctx = myCanvas.getContext("2d"); var myBarChart = new BarChart({ canvas: myCanvas, seriesName: "Example Series", padding: 40, data: exampleData, colors: ["#D1E3F3", "#D1E3F3", "#D1E3F3", "#D1E3F3"] }); myBarChart.plot(); } document.addEventListener("DOMContentLoaded", init, false); 
 <canvas id="myCanvas"></canvas> 

Changing :

this.ctx.rect(30, barIdx * barWidth, barLength, barWidth);
this.ctx.fill();

To instead use fillRect() fixes the problem:

this.ctx.fillRect(30, barIdx * barWidth, barLength, barWidth);

Working example here (compared to the original example here )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM