SeanSobey / ChartjsNodeCanvas

A node renderer for Chart.js using canvas.
MIT License
228 stars 70 forks source link

Using with ChartJS-Financial #47

Open vzhilov opened 3 years ago

vzhilov commented 3 years ago

I can’t make it work with ChartJS-Financial Official plugin. Is that ChartJS-Financial problem?

I do:

Git clone https://github.com/chartjs/chartjs-chart-financial/
cd chartjs-chart-financial
npm install
gulp build

As result I get a file in /dist directory and copy it to me NodeJS project folder.

In my NodeJS app I do:

const Chart = require(‘chart.js’)
const ChartFinancial = require(‘./chartjs-chart-financial.js’)

const chartJsFactory = () => {
    const Chart = require('chart.js');
    require('chartjs-plugin-datalabels');
    require('./chartjs-chart-financial.js');
    delete require.cache[require.resolve('chart.js')];
    delete require.cache[require.resolve('chartjs-plugin-datalabels')];
    delete require.cache[require.resolve('./chartjs-chart-financial.js')];
    return Chart;
}

const canvasRenderService = new CanvasRenderService(width, height, chartCallback, undefined, chartJsFactory);

(async () => {
    const configuration = {
         type: 'bar',
        data: {
            datasets: [
               {
                    type: 'candlestick',
                    label: 'Индкекс ММВБ',
                    data : [{t: 1491004800000, c: "29.76", h: "31.00", l: "26.90", o: "30.29"}, {t: 1491177600000, c: "29.76", h: "31.00", l: "26.90", o: "30.29"}],
                }, 
            ],
        },
    };
    const image = await canvasRenderService.renderToBuffer(configuration);

When I run the app I get:

chartjs-chart-financial.js:227
globalOpts.elements.financial = {
TypeError: Cannot set property ‘financial’ of undefined

I have checked content of Chart.defaults and found that .elements is in ‘global’ so I changed

225 const globalOpts = Chart.defaults.global
316 const globalOpts$1 = Chart.defaults.global
401 const globalOpts$2 = Chart.defaults.global

And eventually Error

Chart.defaults.set(‘ohlc’ ... 

on line 446

So I changed them to:

446 Chart.defaults.ohlc.datasets.barPercentage = 1.0,
447 Chart.defaults.ohlc.datasets.categoryPercentage = 1.0

Then I got

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'data' of undefined
at CandlestickController.draw (C:\inetpub\github\telegram-stream-trades\chartjs-chart-financial.js:213:32)

So I chagned:

213 const rects = me.getMeta();

That handled all the errors. But still no candles drawn.

So probably the way I initially started is incorrect

Originally posted by @vzhilov in https://github.com/SeanSobey/ChartjsNodeCanvas/issues/40#issuecomment-674016404

vzhilov commented 3 years ago

chartjs-chart-financial/package.json

Line 18 in f10c046

"chart.js": "^3.0.0-beta.3",

v3.0.0-beta.4 Breaking Changes

7886 Shorten alignment settings for axes

7871 Polar Area elements.arc.angle option now returns degrees

#7843 Provide method to lookup a chart from a canvas

7833 Enable per-dataset circumference and rotation for pie/doughnut charts

After upgrading to chart.js@3.0.0-beta.5

git clone https://github.com/chartjs/chartjs-chart-financial
cd chartjs-chart-financial
npm install
gulp build

take built file from /dist, copy to my project and then:

const chartJsFactory = () => {
        require('./dist/chartjs-chart-financial.js');
        delete require.cache[require.resolve('chart.js')];
        delete require.cache[require.resolve('./dist/chartjs-chart-financial.js')];
        return Chart;
    }

const canvasRenderService = new CanvasRenderService(width, height, undefined, undefined, chartJsFactory);

(node:6428) UnhandledPromiseRejectionWarning: ReferenceError: window is not defined at afterBuildTicks (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\dist\chartjs-chart-financial.js:154:22) at callback (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:305:15) at CategoryScale.afterBuildTicks (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:5112:5) at CategoryScale.update (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:5035:8) at fitBoxes (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:1538:9) at Object.update (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:1654:9) at Chart._updateLayout (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:6733:13) at Chart.update (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:6715:8) at new Chart (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chart.js\dist\chart.js:6477:10) at CanvasRenderService.renderChart (C:\inetpub\wwwroot\streamtrades.ru\telegram-stream-trades\node_modules\chartjs-node-canvas\dist\index.js:151:16)

SeanSobey commented 3 years ago

See the latest version (currently 3.0.6) for the updated plugin loading

vzhilov commented 3 years ago

Thank you for the more detailed write up. I have fixed my code now in accordance with that. I don't get any errors, but I don't get plugins registered too. No even dataLabels plugin showing up. Please point me out on my mistake. Here is my code:

х = "10:00,11:00,12:00,13:00,14:00,15:00,16:00,17:00,18:00,19:00"
y1 = "0,0,0,0,0,0,0,67,0,0"
y2 = "0,0,0,0,0,0,0,67,67,67"
m = "3062.61,3072.35,3047.62,3059.11,3055.88,3067.48,3064.12,3077.05,3075.43,3079.74"
period = "d"
ctx = null
cum = 67

let title = ""
if (period == 'd') title = "day"
if (period == 'w') title = "week"
if (period == 'm') title = "month"

const width = 600;
const height = 400;

const chartJsFactory = (ChartJS) => {
    ChartJS.plugins.register ({
        modern: ['chartjs-plugin-annotation'],
        requireLegacy: ['chartjs-plugin-datalabels'],
        requireLegacy: ['./dist/chartjs-chart-financial.js'],
    });
}

const canvasRenderService = new CanvasRenderService (width, height, chartJsFactory);

var barCount = 60;
var initialDateStr = '01 Apr 2017 00:00 Z';

(async () => {
const configuration = {
    type: 'bar',
    data: {
        datasets: [
            {
                type:"bar",
                yAxisID: 'left-y-axis',
                //barThickness: 24,
                label: 'hourly',
                data: y1,
                backgroundColor: 'rgba(54, 162, 135, 0.2)', //'rgba(75,192, 192, 0.2)',
                borderColor: 'rgba(54, 162, 135, 0.2)',
                borderWidth: 1,
                datalabels: {
                    align: 'center',
                    anchor: 'center',
                    borderRadius: 4,
                    color: 'rgba(54, 162, 135, 0.8)',//'rgba(75,192, 192, 0.8)',
                    formatter: function(value, context) {
                        if (value > 0)
                            return "+" + Math.round(value)
                        else 
                            return Math.round(value)
                    },
                    display: function(context) {
                        return context.dataset.data[context.dataIndex] != 0; // or >= 1 or ...
                    }
                }
            }, 
            {
                type:"line",
                yAxisID: 'left-y-axis',
                label: 'Cumulative',
                data: y2,
                backgroundColor: 'rgba(255, 255, 255, 0.2)',
                borderColor: 'rgba(54, 162, 135, 1)',
                borderWidth: 2,
                lineTension: 0.3,
                datalabels: {
                    //display: false,
                    align: 'end',
                    anchor: 'end',
                    color: 'rgba(54, 162, 135, 1)', //'rgba(75,192, 192, 1)',
                }
            }, 
            {
                type:"line",
                /*
                type: 'candlestick',
                data: {
                    datasets: [{
                        label: 'CHRT - Chart.js Corporation',
                        data: getRandomData(initialDateStr, barCount)
                    }]
                },
                */
                yAxisID: 'right-y-axis',
                //barThickness: 24,
                label: 'Another one',
                data: m,
                backgroundColor: 'rgba(255, 255, 255, 0.2)',
                borderColor: 'rgba(245, 120, 81, 0.5)',
                borderDash: [20, 3, 3, 3, 3, 3, 3, 3],
                borderWidth: 1,
                datalabels: {
                    display: false,
                }
            }, 
        ],
            labels: x,
    },
    options: {
        title: {
            display: true,
            text: 'Graph for ' + title,
            fontColor: 'rgba(104, 143, 133, 1)',
            fontSize: '16',
        },
        legend: {
            display: true,
            labels: {
                fontColor: 'rgba(54, 162, 135, 1)',
            },
        },   
        scales: {
            yAxes: [
                {
                    id: 'left-y-axis',
                    position: 'left',
                    //stacked: false,
                    ticks: {
                        beginAtZero: true,
                        callback: (value) => value + "₽",
                        fontColor: 'rgba(104, 143, 133, 1)',
                        max: cum + cum/5,
                    },
                    gridLines: {
                        color: 'rgba(104, 143, 133, 0.2)',
                        zeroLineColor: 'rgba(104, 143, 133, 0.5)',
                    },
                },
                {
                    id: 'right-y-axis',
                    position: 'right',
                    gridLines: {
                        display: false,
                    },
                    ticks: {
                        fontColor: 'rgba(245, 120, 81, 0.8)',
                    },
                }
            ],
            xAxes: [
                {
                    //stacked: true,
                    gridLines: {
                        color: 'rgba(104, 143, 133, 0.2)',
                        zeroLineColor: 'rgba(104, 143, 133, 0.5)',    
                        //tickMarkLength: 15                          
                    },
                    ticks: {
                        fontColor: 'rgba(104, 143, 133, 1)',
                    },
               }
            ],
        },
        plugins: {
            datalabels: {
                color: 'white',
                font: {
                    weight: 'bold'
                },
                formatter: Math.round
            }
        },        
    }
};

const image = await canvasRenderService.renderToBuffer(configuration);
})();