Избавляемся от подпикселей холста Chart.js
Я работаю над очень маленьким виджетом, который отображает простую гистограмму:
Я использую Chart.js для этой конкретной задачи.
var canvas = this.$(".chart-canvas")[0];
if (canvas) {
var ctx = canvas.getContext("2d");
ctx.translate(0.5, 0.5);
window.barChart = new Chart(ctx).Bar(barChartData, {
responsive: true,
maintainAspectRatio: false,
showScale: false,
scaleShowGridLines: false,
scaleGridLineWidth: 0,
barValueSpacing: 1,
barDatasetSpacing: 0,
showXAxisLabel: false,
barShowStroke: false,
showTooltips: false,
animation: false
});
Как видите, я пытался
ctx.translate(0,5, 0,5);
но это не очень помогло.
Есть ли способ избавиться от субпиксельного рендеринга? Я читал о линейном алгоритме Брезенхэма, но не знаю, как реализовать его там.
Любые идеи / предложения приветствуются.
Заранее спасибо!
1 ответ
Предполагая, что у вас есть только один цвет, вы можете сделать это, расширяя диаграмму и переопределяя рисование, чтобы выполнить getImageData, "округляя" (если пиксель имеет значение R, G или B, установите его в цвет), цвета пикселя и putImageData.
Вы можете сделать это и для нескольких цветов, но это становится немного сложнее, когда рядом два цвета.
Однако различие в интервале значений баров, которое вы видите, связано с тем, как Chart.js вычисляет позицию х для баров - происходит округление.
Вы можете расширить график и переопределить метод, который вычисляет позицию х, чтобы избавиться от округления
Chart.types.Bar.extend({
// Passing in a name registers this chart in the Chart namespace in the same way
name: "BarAlt",
initialize: function (data) {
Chart.types.Bar.prototype.initialize.apply(this, arguments);
// copy paste from library code with only 1 line changed
this.scale.calculateX = function (index) {
var isRotated = (this.xLabelRotation > 0),
innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
valueWidth = innerWidth / Math.max((this.valuesCount - ((this.offsetGridLines) ? 0 : 1)), 1),
valueOffset = (valueWidth * index) + this.xScalePaddingLeft;
if (this.offsetGridLines) {
valueOffset += (valueWidth / 2);
}
// the library code rounds this off - we don't
return valueOffset;
}
// render again because the original initialize call does a render
// when animation is off this is the only render that happens
this.render();
}
});
Вы бы назвали это так
var ctx = document.getElementById('canvas').getContext('2d');
var myBarChart = new Chart(ctx).BarAlt(data, {
...
Скрипка - http://jsfiddle.net/gf2c4ue4/
Вы можете увидеть разницу лучше, если вы увеличите масштаб.
Верхний - расширенный график