Chart.js с предпочтительной цветовой схемой в Safari: цвет чешуи не меняется

#css #chart.js

#css #chart.js

Вопрос:

Я создаю HTML-файл, содержащий Chart.js диаграмма в нем. Когда я меняю системную цветовую схему со светлой на темную (или наоборот), цвет шрифта осей X и Y не меняется, хотя другие цвета меняются. Тем не менее, каждый цвет такой, каким он должен быть, когда я обновляю страницу, независимо от того, является ли системная цветовая схема светлой или темной.

Я тестирую это только в Safari 12.1, поскольку это единственный браузер, который поддерживает prefers-color-scheme медиа-запрос в версии, отличной от бета-версии.

Вот содержимое <script> элемента, который я использую:

 const white = 'hsl(42, 0%, 90%)';
const black = 'hsl(42, 0%, 10%)';

const perfectPrimaryLight = 'hsl(270, 50%, 40%)';
const perfectSecondaryLight = 'hsla(270, 50%, 40%, .2)';

const myPrimaryLight = 'hsl(0, 50%, 40%)';
const mySecondaryLight = 'hsla(0, 50%, 40%, .2)';

const perfectPrimaryDark = 'hsl(340, 50%, 80%)';
const perfectSecondaryDark = 'hsla(340, 50%, 80%, .2)';

const myPrimaryDark = 'hsl(0, 50%, 80%)';
const mySecondaryDark = 'hsla(0, 50%, 80%, .2)';

Chart.defaults.global.defaultFontFamily = 'system-ui, sans-serif';
Chart.defaults.global.defaultFontSize = 16; 
Chart.defaults.global.defaultFontColor = black;

function updateToLight(chart) {
    chart.options.legend.labels.fontColor = black;

    chart.options.scales.yAxes[0].ticks.fontColor = black;
    chart.options.scales.xAxes[0].ticks.fontColor = black;

    chart.data.datasets[0].borderColor = perfectPrimaryLight;
    chart.data.datasets[0].backgroundColor = perfectSecondaryLight;

    chart.data.datasets[1].borderColor = myPrimaryLight;
    chart.data.datasets[1].backgroundColor = mySecondaryLight;

    
    chart.update();
}

function updateToDark(chart) {
    chart.options.legend.labels.fontColor = white;

    chart.options.scales.yAxes[0].ticks.fontColor = white;
    chart.options.scales.xAxes[0].ticks.fontColor = white;

    chart.data.datasets[0].borderColor = perfectPrimaryDark;
    chart.data.datasets[0].backgroundColor = perfectSecondaryDark;

    chart.data.datasets[1].borderColor = myPrimaryDark;
    chart.data.datasets[1].backgroundColor = mySecondaryDark;

    
    chart.update();
}

const ctx = document.getElementById('myChart').getContext('2d');
const data = {
    datasets: [{
        label: 'Perfect-calibration dataset',
        data: [{"x":0.01,"y":0.01},{"x":0.05,"y":0.05},{"x":0.10,"y":0.10},{"x":0.15,"y":0.15},{"x":0.20,"y":0.20},{"x":0.25,"y":0.25},{"x":0.30,"y":0.30},{"x":0.35,"y":0.35},{"x":0.40,"y":0.40},{"x":0.45,"y":0.45},{"x":0.50,"y":0.50},{"x":0.55,"y":0.55},{"x":0.60,"y":0.60},{"x":0.65,"y":0.65},{"x":0.70,"y":0.70},{"x":0.75,"y":0.75},{"x":0.80,"y":0.80},{"x":0.85,"y":0.85},{"x":0.90,"y":0.90},{"x":0.95,"y":0.95},{"x":0.99,"y":0.99}],
    }, {
        label: 'My predictions',
        data: [{"x":0.10,"y":0.00},{"x":0.50,"y":0.25},{"x":0.60,"y":0.00},{"x":0.70,"y":0.62},{"x":0.80,"y":0.25},{"x":0.90,"y":0.68},{"x":0.95,"y":0.83}]
    }]
};

const options = {
    title: {
        display: false,
        text: 'A Chart.js Scatter Chart'
    },
    scales: {
        yAxes: [{
            ticks: {
                min: 0,
                max: 1
            }
        }],
        xAxes: [{
            ticks: {
                min: 0,
                max: 1
            }
        }]
    }
}

const c = new Chart(ctx, {
    type: 'scatter',
    data: data,
    options: options
});

const query = window.matchMedia("(prefers-color-scheme: dark)");

let darkMode = false;

function toggleDark() {
    darkMode = !darkMode;
    if (darkMode) {
        document.body.style.background = 'black';
        updateToDark(c);
    } else {
        document.body.style.background = 'white';
        updateToLight(c);    
    }
}

updateToLight(c);  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<canvas id="myChart" onclick="toggleDark()"></canvas>  

Вот как увидеть это в действии:

  1. Установите для системной цветовой схемы значение light.
  2. Откройте файл в Safari.
  3. Обратите внимание на черные метки осей и фиолетовый цвет метки набора данных идеальной калибровки.
  4. Переключите системную цветовую схему на темный. (В приведенном выше примере просто щелкните диаграмму.)
  5. Обратите внимание, что метки осей по-прежнему черные, но теперь на черном фоне.
  6. Обратите внимание, как цвет набора данных идеальной калибровки изменился на гораздо более красный цвет.
  7. Обратите внимание, что метки для наборов данных теперь белые.

Теперь, чтобы увидеть все это в обратном порядке. Давайте перезагрузим страницу, пока система настроена на темный режим. Обратите внимание, что цвета меток оси теперь белые.


  1. Верните системной цветовой схеме значение light.
  2. Обратите внимание, что метки осей почти белые на белом фоне.

Есть идеи, почему chart.options.scales.yAxes[0].ticks.fontColor не меняется, в то время как другие свойства есть?

Ответ №1:

Это была ошибка в Chart.js 2.8.0. Это было исправлено в версии 2.9.0:

 const white = 'hsl(42, 0%, 90%)';
const black = 'hsl(42, 0%, 10%)';

const perfectPrimaryLight = 'hsl(270, 50%, 40%)';
const perfectSecondaryLight = 'hsla(270, 50%, 40%, .2)';

const myPrimaryLight = 'hsl(0, 50%, 40%)';
const mySecondaryLight = 'hsla(0, 50%, 40%, .2)';

const perfectPrimaryDark = 'hsl(340, 50%, 80%)';
const perfectSecondaryDark = 'hsla(340, 50%, 80%, .2)';

const myPrimaryDark = 'hsl(0, 50%, 80%)';
const mySecondaryDark = 'hsla(0, 50%, 80%, .2)';

Chart.defaults.global.defaultFontFamily = 'system-ui, sans-serif';
Chart.defaults.global.defaultFontSize = 16; 
Chart.defaults.global.defaultFontColor = black;

function updateToLight(chart) {
    chart.options.legend.labels.fontColor = black;

    chart.options.scales.yAxes[0].ticks.fontColor = black;
    chart.options.scales.xAxes[0].ticks.fontColor = black;

    chart.data.datasets[0].borderColor = perfectPrimaryLight;
    chart.data.datasets[0].backgroundColor = perfectSecondaryLight;

    chart.data.datasets[1].borderColor = myPrimaryLight;
    chart.data.datasets[1].backgroundColor = mySecondaryLight;

    
    chart.update();
}

function updateToDark(chart) {
    chart.options.legend.labels.fontColor = white;

    chart.options.scales.yAxes[0].ticks.fontColor = white;
    chart.options.scales.xAxes[0].ticks.fontColor = white;

    chart.data.datasets[0].borderColor = perfectPrimaryDark;
    chart.data.datasets[0].backgroundColor = perfectSecondaryDark;

    chart.data.datasets[1].borderColor = myPrimaryDark;
    chart.data.datasets[1].backgroundColor = mySecondaryDark;

    
    chart.update();
}

const ctx = document.getElementById('myChart').getContext('2d');
const data = {
    datasets: [{
        label: 'Perfect-calibration dataset',
        data: [{"x":0.01,"y":0.01},{"x":0.05,"y":0.05},{"x":0.10,"y":0.10},{"x":0.15,"y":0.15},{"x":0.20,"y":0.20},{"x":0.25,"y":0.25},{"x":0.30,"y":0.30},{"x":0.35,"y":0.35},{"x":0.40,"y":0.40},{"x":0.45,"y":0.45},{"x":0.50,"y":0.50},{"x":0.55,"y":0.55},{"x":0.60,"y":0.60},{"x":0.65,"y":0.65},{"x":0.70,"y":0.70},{"x":0.75,"y":0.75},{"x":0.80,"y":0.80},{"x":0.85,"y":0.85},{"x":0.90,"y":0.90},{"x":0.95,"y":0.95},{"x":0.99,"y":0.99}],
    }, {
        label: 'My predictions',
        data: [{"x":0.10,"y":0.00},{"x":0.50,"y":0.25},{"x":0.60,"y":0.00},{"x":0.70,"y":0.62},{"x":0.80,"y":0.25},{"x":0.90,"y":0.68},{"x":0.95,"y":0.83}]
    }]
};

const options = {
    title: {
        display: false,
        text: 'A Chart.js Scatter Chart'
    },
    scales: {
        yAxes: [{
            ticks: {
                min: 0,
                max: 1
            }
        }],
        xAxes: [{
            ticks: {
                min: 0,
                max: 1
            }
        }]
    }
}

const c = new Chart(ctx, {
    type: 'scatter',
    data: data,
    options: options
});

const query = window.matchMedia("(prefers-color-scheme: dark)");

let darkMode = false;

function toggleDark() {
    darkMode = !darkMode;
    if (darkMode) {
        document.body.style.background = 'black';
        updateToDark(c);
    } else {
        document.body.style.background = 'white';
        updateToLight(c);    
    }
}

updateToLight(c);  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.0/Chart.bundle.min.js"></script>
<canvas id="myChart" onclick="toggleDark()"></canvas>  

Однако версия 2.9.0 также устарела. Однако адаптация примера кода к версии 3.8.0 потребует некоторой работы.