Избавляемся от подпикселей холста 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/

Вы можете увидеть разницу лучше, если вы увеличите масштаб.


Верхний - расширенный график

введите описание изображения здесь

Другие вопросы по тегам