From 8f6c10b45abc5003e729a8e1f05efd71e3e65f88 Mon Sep 17 00:00:00 2001 From: WofWca Date: Wed, 22 Sep 2021 20:07:36 +0800 Subject: [PATCH] make all lines sharp Fixes #57 --- smoothie.js | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/smoothie.js b/smoothie.js index fe9a123..77c8d92 100644 --- a/smoothie.js +++ b/smoothie.js @@ -137,7 +137,17 @@ low = mid + 1; } return low; - } + }, + // So lines (especially vertical and horizontal) look a) consistent along their length and b) sharp. + pixelSnap: function(position, lineWidth) { + if (lineWidth % 2 === 0) { + // Closest pixel edge. + return Math.round(position); + } else { + // Closest pixel center. + return Math.floor(position) + 0.5; + } + }, }; /** @@ -813,17 +823,18 @@ dimensions = { top: 0, left: 0, width: canvas.clientWidth, height: canvas.clientHeight }, // Calculate the threshold time for the oldest data points. oldestValidTime = time - (dimensions.width * chartOptions.millisPerPixel), - valueToYPixel = function(value) { - var offset = value - this.currentVisMinValue; - return this.currentValueRange === 0 - ? dimensions.height - : dimensions.height - (Math.round((offset / this.currentValueRange) * dimensions.height)); + valueToYPosition = function(value, lineWidth) { + var offset = value - this.currentVisMinValue, + unsnapped = this.currentValueRange === 0 + ? dimensions.height + : dimensions.height * (1 - offset / this.currentValueRange); + return Util.pixelSnap(unsnapped, lineWidth); }.bind(this), - timeToXPixel = function(t) { - if(chartOptions.scrollBackwards) { - return Math.round((time - t) / chartOptions.millisPerPixel); - } - return Math.round(dimensions.width - ((time - t) / chartOptions.millisPerPixel)); + timeToXPosition = function(t, lineWidth) { + var unsnapped = chartOptions.scrollBackwards + ? (time - t) / chartOptions.millisPerPixel + : dimensions.width - ((time - t) / chartOptions.millisPerPixel); + return Util.pixelSnap(unsnapped, lineWidth); }; this.updateValueRange(); @@ -861,7 +872,7 @@ for (var t = time - (time % chartOptions.grid.millisPerLine); t >= oldestValidTime; t -= chartOptions.grid.millisPerLine) { - var gx = timeToXPixel(t); + var gx = timeToXPosition(t, chartOptions.grid.lineWidth); context.moveTo(gx, 0); context.lineTo(gx, dimensions.height); } @@ -871,7 +882,7 @@ // Horizontal (value) dividers. for (var v = 1; v < chartOptions.grid.verticalSections; v++) { - var gy = Math.round(v * dimensions.height / chartOptions.grid.verticalSections); + var gy = Util.pixelSnap(v * dimensions.height / chartOptions.grid.verticalSections, chartOptions.grid.lineWidth); context.beginPath(); context.moveTo(0, gy); context.lineTo(dimensions.width, gy); @@ -890,9 +901,10 @@ if (chartOptions.horizontalLines && chartOptions.horizontalLines.length) { for (var hl = 0; hl < chartOptions.horizontalLines.length; hl++) { var line = chartOptions.horizontalLines[hl], - hly = Math.round(valueToYPixel(line.value)) - 0.5; + lineWidth = line.lineWidth || 1, + hly = valueToYPosition(line.value, lineWidth); context.strokeStyle = line.color || '#ffffff'; - context.lineWidth = line.lineWidth || 1; + context.lineWidth = lineWidth; context.beginPath(); context.moveTo(0, hly); context.lineTo(dimensions.width, hly); @@ -923,8 +935,8 @@ // Retain lastX, lastY for calculating the control points of bezier curves. var firstX = 0, firstY = 0, lastX = 0, lastY = 0; for (var i = 0; i < dataSet.length && dataSet.length !== 1; i++) { - var x = timeToXPixel(dataSet[i][0]), - y = valueToYPixel(dataSet[i][1]); + var x = timeToXPosition(dataSet[i][0], seriesOptions.lineWidth), + y = valueToYPosition(dataSet[i][1], seriesOptions.lineWidth); if (i === 0) { firstX = x; @@ -1045,7 +1057,7 @@ for (var t = time - (time % chartOptions.grid.millisPerLine); t >= oldestValidTime; t -= chartOptions.grid.millisPerLine) { - var gx = timeToXPixel(t); + var gx = timeToXPosition(t, 0); // Only draw the timestamp if it won't overlap with the previously drawn one. if ((!chartOptions.scrollBackwards && gx < textUntilX) || (chartOptions.scrollBackwards && gx > textUntilX)) { // Formats the timestamp based on user specified formatting function