Как решить проблему с пропорциями на chartJS?

Проблема заключается в том, что при подключении библиотеки chartJs и создании столбцов с нужными показателями, значения показываются не пропорционально. Т.е например, как в прикреплённом фото: 1. Реальный заработок - 80р 2. Возможный заработок - 100р Тут очевидно, реальный заработок должен занимать 80% от возможного, но он почему-то занимает менее 50%

Код привёл ниже, кто знает как, помогите пожалуйста решить вопрос.


const ctx = document.querySelector('#earningsChart').getContext('2d');
let earningsChart;
let isNightMode = localStorage.getItem('nightMode');
const dataSets = {
    months: {
        labels: ['Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь', 'Январь', 'Февраль', 'Март', 'Апрель', 'Май'],
        data: [10, 80, 0, 0, 0, 0, 0, 0, 0]
    },
    days: {
        labels: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'],
        data: [0, 0, 0, 0, 0, 0, 0]
    },
    years: {
        labels: ['2020', '2021', '2022', '2023', '2024'],
        data: [0, 0, 0, 0, 0]
    }
};

function updateChart(timePeriod, isNightmode ) {
    const { labels, data } = dataSets[timePeriod];

    if (earningsChart) {
        earningsChart.destroy();
    }
    if (isNightmode) {
        colors = {
            'bg' : '#B5F5BF',
            'bg1' : '#383535',
            'text-color' :'#fff',
            
        }
    } else {
        colors = {
            'bg' : '#1D4ECC',
            'bg1' : 'rgba(54, 162, 235, 0.1)',
            'text-color': '#000'
        }
    }

    earningsChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: labels,
            datasets: [{
                label: 'Реальный',
                barPercentage: 0.6, // Уменьшает ширину столбцов
                data: data,
                backgroundColor:colors['bg'],
                borderColor: 'rgba(54, 162, 235, 1)',
                stack: 'combined',
                borderRadius: 10 // Закругленные края столбцов
            }, {
                label: 'Возможный',
                barPercentage: 0.6, // Уменьшает ширину столбцов
                data: data.map(d => 100),  // Генерация случайных значений для демонстрации
                backgroundColor: colors['bg1'],
                borderColor: 'rgba(255, 206, 86, 0.1)',
                stack: 'combined',
                borderRadius: 10 // Закругленные края столбцов
            }]
        },
        options: {
            
            responsive: true,
            maintainAspectRatio: false,
            layout: {
                padding: {
                    left: 10,
                    right: 10,
                    top: 10,
                    bottom: 10
                }
            },
            plugins: {
                legend: {
                    display: false, // Убрать легенду
                    
                },
                tooltip: {
                    enabled: false,
                    external: function(context) {
                        let tooltipEl = document.getElementById('chartjs-tooltip');
                        if (!tooltipEl) {
                            tooltipEl = document.createElement('div');
                            tooltipEl.id = 'chartjs-tooltip';
                            tooltipEl.innerHTML = '<table></table>';
                            document.body.appendChild(tooltipEl);
                        }
                        const tooltipModel = context.tooltip;
                        if (tooltipModel.opacity === 0) {
                            tooltipEl.style.opacity = 0;
                            return;
                        }

                        if (tooltipModel.body) {
                            const titleLines = tooltipModel.title || [];
                            const bodyLines = tooltipModel.body.map(item => item.lines);
                            const header = titleLines.join(' ');
                            document.getElementById('chartjs-tooltip-header').innerText = header;
                            
                            const body = bodyLines[0][0].split(':');
                            document.getElementById('chartjs-tooltip-body').innerText = body[0];
                            const value = tooltipModel.dataPoints[0].parsed.y;
                            document.getElementById('chartjs-tooltip-value').innerText = `${Math.round(value)}₽`;
                        }

                        const position = context.chart.canvas.getBoundingClientRect();
                        tooltipEl.style.opacity = 1;
                        tooltipEl.style.left = tooltipModel.caretX + '' + 'px';
                        tooltipEl.style.top = tooltipModel.caretY + 100 + 'px';
                        tooltipEl.style.transform = 'translateX(-50%)';
                    }
                },
            },
            scales: {
                x: {
                    
                    border: {
                        display: false,
                    },
                    stacked: true,
                    grid: {
                        color: '#fff',
                        display: false
                    },
                    ticks: {
                        font: {
                            size: 10,
                            weight: 'normal',
                            family: 'Arvo'
                        },
                        color: colors['text-color']
                    },
                },
                y: {
                    border: {
                        display: false,
                    },
                    stacked: true,
                    beginAtZero: true,
                    grid: {
                        display: false
                    },
                    ticks: {
                        display: false,
                        font: {
                            size: 10,
                            weight: 'bold'
                        },
                        color: colors['text-color']
                    }
                }
            },
            barSpacing: 20 // Расстояние между столбцами
        },
    });
}

// Initialize the chart with 'months' data
if (isNightMode == 'true'){
    updateChart('months', true);
} else {
    updateChart('months', false);
}

switcher = document.querySelector('.switcher');
switcher.addEventListener('click', ()=>{
    isNightMode = document.body.classList.contains('night__mode'); 

    if (isNightMode) {
        updateChart('months', !isNightMode);
        document.querySelector('.drop-toggle').innerHTML = 'По месяцам';
    }
    else {
        updateChart('months', !isNightMode);
        document.querySelector('.drop-toggle').innerHTML = 'По месяцам';
    }
})

buttons = document.querySelectorAll('.btn-bar-chart');
container = document.querySelector('.drop-toggle')
menu = document.querySelector('.drop-menu')
buttons.forEach(btn =>{
    btn.addEventListener('click', ()=>{
        if (btn.dataset.period == 'days') {
            container.innerHTML = 'По дням'
            menu.style.display = 'none'
        }
        else if (btn.dataset.period == 'months') {
            container.innerHTML = 'По месяцам'
            menu.style.display = 'none'
        }
        else if (btn.dataset.period == 'years') {
            container.innerHTML = 'По годам'
            menu.style.display = 'none'
        }
    })
})

Ответы (1 шт):

Автор решения: Owlly

Исправьте данные для возможного заработка: Вместо использования data.map(d => 100), вы можете динамически указывать возможный заработок для каждого месяца.

Настройте ось y: Добавьте больше контроля над минимальным и максимальным значением оси, чтобы они точно отражали пропорции между реальным и возможным заработком.

Используйте categoryPercentage и barPercentage: Для того, чтобы изменить относительные размеры столбцов.

function updateChart(timePeriod, isNightmode ) {
    const { labels, data } = dataSets[timePeriod];

    if (earningsChart) {
        earningsChart.destroy();
    }

    if (isNightmode) {
        colors = {
            'bg' : '#B5F5BF',
            'bg1' : '#383535',
            'text-color' :'#fff',
        }
    } else {
        colors = {
            'bg' : '#1D4ECC',
            'bg1' : 'rgba(54, 162, 235, 0.1)',
            'text-color': '#000'
        }
    }

    earningsChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: labels,
            datasets: [{
                label: 'Реальный заработок',
                barPercentage: 0.6,
                categoryPercentage: 0.8, // Изменяем относительную ширину столбцов
                data: data,
                backgroundColor: colors['bg'],
                borderColor: 'rgba(54, 162, 235, 1)',
                stack: 'combined',
                borderRadius: 10
            }, {
                label: 'Возможный заработок',
                barPercentage: 0.6,
                categoryPercentage: 0.8, // Изменяем относительную ширину столбцов
                data: data.map(d => d * 1.25), // Делаем возможный заработок на 25% больше для демонстрации
                backgroundColor: colors['bg1'],
                borderColor: 'rgba(255, 206, 86, 0.1)',
                stack: 'combined',
                borderRadius: 10
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            layout: {
                padding: {
                    left: 10,
                    right: 10,
                    top: 10,
                    bottom: 10
                }
            },
            plugins: {
                legend: {
                    display: true, // Показать легенду
                },
                tooltip: {
                    enabled: true,
                },
            },
            scales: {
                x: {
                    stacked: true,
                    grid: {
                        display: false,
                    },
                    ticks: {
                        color: colors['text-color'],
                    },
                },
                y: {
                    beginAtZero: true, // Начало с нуля
                    max: 150, // Устанавливаем максимальное значение на оси Y
                    grid: {
                        display: true,
                    },
                    ticks: {
                        color: colors['text-color'],
                    },
                }
            },
        },
    });
}
→ Ссылка