Reputation: 77
I was trying to contribute to this post, HTML5 Canvas and Line Width but it was deleted because it's not an official answer, because technically I'm also asking a question using the following code I get the same problem. "I'm drawing line graphs on a canvas. The lines draw fine. The graph is scaled, every segment is drawn, color are ok, etc. My only problem is visually the line width varies. It's almost like the nib of a caligraphy pen. If the stroke is upward the line is thin, if the stroke is horizontal, the line is thicker.
My line thickness is constant, and my strokeStyle is set to black. I don't see any other properties of the canvas that affect such a varying line width but there must be. "
<html>
<head>
<style>html{font-family:Verdana;}</style>
<script type="text/javascript">
var canvas ;
var context ;
var Val_max;
var Val_min;
var sections;
var xScale;
var yScale;
var Samsung = [21000,21000,23000,22000,22000,23000,23000];
function init() {
// set these values for your data
sections = 7;
Val_max = 25000;
Val_min = 10000;
var stepSize = 1500;
var columnSize = 75;
var rowSize = 75;
var margin = 10;
var xAxis = [""," Monday "," Tuesday"," Wednesday"," Thursday"," Friday"," Saturday"," Sunday"]//;
//
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.fillStyle = "#4d4d4d"
context.font = "10 pt Arial"
yScale = (canvas.height - columnSize - margin) / (Val_max - Val_min);
xScale = (canvas.width - rowSize) / sections;
context.strokeStyle="#4d4d4d"; // color of grid lines
context.beginPath();
// print Parameters on X axis, and grid lines on the graph
for (i=1;i<=sections;i++) {
var x = i * xScale;
context.fillText(xAxis[i], x,columnSize - margin);
context.moveTo(x, columnSize);
context.lineTo(x, canvas.height - margin);
}
// print row header and draw horizontal grid lines
var count = 0;
for (scale=Val_max;scale>=Val_min;scale = scale - stepSize) {
var y = columnSize + (yScale * count * stepSize);
context.fillText(scale, margin,y + margin);
context.moveTo(rowSize,y)
context.lineTo(canvas.width,y)
count++;
}
context.stroke();
context.lineWidth=20;
context.translate(rowSize,canvas.height + Val_min * yScale);
context.scale(1,-1 * yScale);
// Color of each dataplot items
context.strokeStyle="#2FBC3A";
plotData(Samsung);
}
function plotData(dataSet) {
// context.beginPath();
// context.moveTo(0, dataSet[0]);
// for (i=1;i<sections;i++) {
// context.lineTo(i * xScale, dataSet[i]);
// }
// context.stroke();
var love=0;
for (i=1;i<sections;i++) {
context.beginPath();
context.moveTo(love, dataSet[i-1]);
context.lineTo(i * xScale, dataSet[i]);
love=i*xScale;
context.stroke();
}
}
</script>
</head>
<body onLoad="init()">
<div align="center">
<canvas id="canvas" height="400" width="650">
</canvas>
<br>
<!--Legends for Dataplot -->
<span style="color:#4d4d4d"> Graph </span>
</div>
</body>
</html>
Upvotes: 1
Views: 715
Reputation: 137171
You are changing your context's scaleY in a non-uniform way.
So all the drawings after this operation will get shrunk on the Y axis.
To avoid that, apply this scaling only on your coordinates, at the time of drawing i.e
context.scale(1, -1 * yScale);
...
context.lineTo(x, y);
becomes
context.lineTo(x, y * -1 * yScale);
This way, your coordinate gets correctly scaled, but your stroke keeps its correct scale.
Also, you were drawing each segment separately, which would produce some holes in between of every segments, so I took the liberty of merging them in a single sub-path.
var canvas;
var context;
var Val_max;
var Val_min;
var sections;
var xScale;
var yScale;
var Samsung = [21000, 21000, 23000, 22000, 22000, 23000, 23000];
function init() {
// set these values for your data
sections = 7;
Val_max = 25000;
Val_min = 10000;
var columnSize = 75;
var rowSize = 75;
var margin = 10;
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.fillStyle = "#4d4d4d";
yScale = (canvas.height - columnSize - margin) / (Val_max - Val_min);
xScale = (canvas.width - rowSize) / sections;
context.lineWidth = 20;
context.translate(rowSize, canvas.height + Val_min * yScale);
//context.scale(1,-1 * yScale);
// ^-- Don't do that.
context.strokeStyle = "#2FBC3A";
plotData(Samsung);
}
function plotData(dataSet) {
var love = 0;
// make a single path from all the segments
context.beginPath();
for (var i = 0; i < sections; i++) {
// Here we scale the coordinate, not the drawings
context.lineTo(i * xScale, dataSet[i] * -1 * yScale);
love = i * xScale;
}
context.stroke();
}
init();
<canvas id="canvas" height="400" width="650">
</canvas>
Upvotes: 1