بررسی Chart.js

گردآوری و تالیف : عرفان کاکایی
تاریخ انتشار : 25 مهر 1397
دسته بندی ها : جاوا اسکریپت

Chart.js یک کتابخانه متن باز معروف است، که به ما در طراحی داده‌ها بر روی وب‌اپلیکیشن‌ها کمک می‌کند. این کتابخانه به شدت قابل سفارشی سازی است، اما پیکربندی تمام گزینه‌هایش برای برخی افراد،‌ یک چالش است. بیایید با شروع از یک مثال ساده، آن را بررسی کنیم.

پیاده‌سازی پایه

برای ساده نگه داشتن کار، من از نسخه CDN کتابخانه استفاده خواهم کرد. اگر شما از آن به همراه React یا Angular استفاده می‌کنید، پیشنهاد می‌کنم که از پکیج npm آن استفاده کنید. همچنین ما می‌خواهیم از jQuery برای ارسال درخواست‌های ajax استفاده کنیم. پیاده‌سازی پایه ما داده‌های درآمد یک رستوران را برای همه روز‌های هفته طرح خواهد کرد.

بیایید با فایل index.html شروع کنیم:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Exploring Chart.js</title>

</head>

<style>

    .container {

        width: 50%;

        height: 50%;

    }

</style>

<body>

    <button id="renderBtn">

        Render

    </button>

    <div class="container">

        <canvas id="myChart"></canvas>

    </div>

</body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<script src="./myChart.js"></script>

</html>

و فایل myChart.js:

function renderChart(data, labels) {

    var ctx = document.getElementById("myChart").getContext('2d');

    var myChart = new Chart(ctx, {

        type: 'line',

        data: {

            labels: labels,

            datasets: [{

                label: 'This week',

                data: data,

            }]

        },

    });

}

$("#renderBtn").click(

    function () {

        data = [20000, 14000, 12000, 15000, 18000, 19000, 22000];

        labels =  ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];

        renderChart(data, labels);

    }

);

ما با تعیین متغیر type، نمودار خطی را به یک نمودار نواری، یا حتی یک نمودار دایره‌ای تبدیل می‌کنیم. تمام انواع مختلف نمودارها را می‌توانید بر روی این لینک مشاهده کنید.

همانطور که می‌توانید ببینید، datasets یک آرایه است. این یعنی ما می‌توانیم دو یا چند مجموعه داده را در نمودار مشابه طراحی کنیم. در ادامه این مقاله، به این قابلیت باز خواهیم گشت.

نتیجه پروژه ما تا به اینجا:

چیزی که درباره آن دوست ندارم

  • محور Y با صفر شروع نمی‌شود. این محور با ۱۲۰۰۰، یعنی کمترین مقدار در مجموعه شروع می‌شود.
  • این نمودار خاکستری است، و من رنگ دیگری می‌خواهم.
  • این نمودار، داده‌ها را به صورت ارز نشان نمی‌دهد: 20000 -> 20,000.00.

پس من مقداری تغییرات به آن اعمال کردم:

function float2dollar(value){

    return "U$ "+(value).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');

}

function renderChart(data, labels) {

    var ctx = document.getElementById("myChart").getContext('2d');

    var myChart = new Chart(ctx, {

        type: 'line',

        data: {

            labels: labels,

            datasets: [{

                label: 'This week',

                data: data,

                borderColor: 'rgba(75, 192, 192, 1)',

                backgroundColor: 'rgba(75, 192, 192, 0.2)',

            }]

        },

        options: {            

            scales: {

                yAxes: [{

                    ticks: {

                        beginAtZero: true,

                        callback: function(value, index, values) {

                            return float2dollar(value);

                        }

                    }

                }]                

            }

        },

    });

}

خط ۱: 

float2dollar یک تابع است که یک مقدار float را به یک رشته ارز تبدیل می‌کند: 18000 -> 18,000.00.

خط ۱۴: 

boderColor و backgroundColor ویژگی‌هایی هستند که رنگ خط و محیط را تغییر می‌دهند.

خط ۲۲: 

beginAtZero: true محور را مجبور می‌کند تا با صفر شروع شود، نه با ۱۲۰۰۰.

خط ۲۳: 

Callback مربوط به تیک محورها، هر زمان که یک تیک رندر می‌شود، فراخوانی می‌شود. متغیر value، مقدار پیشفرض نمایش داده شده است. وقتی که ما این callback را بازنویسی می‌کنیم، می‌توانیم متنی که بر روی محور نمایش داده می‌شود را تغییر دهیم. در اینجا، ما تابع float2dollar خود را فراخوانی می‌کنیم.

در حال حاضر می‌توانیم تغییرات را ببینیم:

داده‌ها را از یک درخواست Ajax بارگذاری کنید:

برای داشتن backendای که ما را قادر سازد تا یک درخواست GET را بدون کار زیادی ارسال کنیم، ما از پکیج json-server استفاده می‌کنیم. این پکیج می‌تواند یک سرور REST را از یک فایل JSON شبیه‌سازی کند.

npm install json-server -save

بر روی package.json خود، ما اسکریپت npm start را طوری تنظیم می‌کنیم که json-server را با یک تاخیر ۲ ثانیه‌ای اجرا کند. از آنجایی که تمام داده‌ها داخلی هستند، پاسخ‌های سریعی خواهیم داشت. این تاخیر مصنوعی ما را قادر خواهد ساخت تا یک ارتباط اینترنت واقعی را شبیه‌سازی کنیم.

“start”: “json-server data.json --delay 2000”,

وقتی که ما اسکریپت npm start را اجرا می‌کنیم، سرویس مورد نظر بر روی پورت ۳۰۰۰ در دسترس خواهد بود.

برای به عمل در آوردن این مسئله، باید فایل data.json خود را بسازیم.

{

    "chartData": {

        "labels": [

            "sunday",

            "monday",

            "tuesday",

            "wednesday",

            "thursday",

            "friday",

            "saturday"

        ],

        "thisWeek": [

            20000,

            14000,

            12000,

            15000,

            18000,

            19000,

            22000

        ]

    }

}

ما همچنین به یک div جدید بر روی HTML نیاز خواهیم داشت، تا یک گیف «Loading» و یک پیغام خطا را نمایش دهد.

<style>

    .container {

        width: 50%;

        height: 50%;

        position: relative;

    }

    #loadingMessage{

        position: absolute;

        left: 50%;

        top: 50%;

        transform: translate(-50%, -50%);

    }

</style>

<body>

    <button id="renderBtn">

        Render

    </button>

    <div class="container">

        <div id="loadingMessage"></div>        

        <canvas id="myChart"></canvas>

    </div>

</body>

برای سازمان‌دهی‌تر کردن همه چیز، ما تابعی به نام getChartData() خواهیم ساخت، تا درخواست ajax را از کلیک دکمه جدا کنیم.

function getChartData() {

    $("#loadingMessage").html('<img src="./giphy.gif" alt="" srcset="">');

    $.ajax({

        url: "http://localhost:3000/chartdata",

        success: function (result) {

            $("#loadingMessage").html("");

            var data = [];

            data.push(result.thisWeek);

            data.push(result.lastWeek);

            var labels = result.labels;

            renderChart(data, labels);

        },

        error: function (err) {

            $("#loadingMessage").html("Error");

        }

    });

}

$("#renderBtn").click(

    function () {

        getChartData();

    }

);

پس از آن، ما گیف بارگذاری خود را داریم.

حال بیایید یک نمودار را با دو مجموعه داده آزمایش کنیم

فرض کنید که ما می‌خواهیم درآمدهای این هفته را با هفته اخیر مقایسه کنیم. بیایید مجموعه هفته فعلی را در رنگ آبی نگه داریم، و مجموعه مربوط به هفته قبل را در رنگ خاکستری اضافه کنیم.

اولین چیزی که باید بروزرسانی کنیم، فایل data.json است:

{

    "chartData": {

        "labels": [

            "sunday",

            "monday",

            "tuesday",

            "wednesday",

            "thursday",

            "friday",

            "saturday"

        ],

        "thisWeek": [

            20000,

            14000,

            12000,

            15000,

            18000,

            19000,

            22000

        ],

        "lastWeek": [

            19000,

            10000,

            14000,

            14000,

            15000,

            22000,

            24000

        ]

    }

}

سپس، ما باید فایل myChart.js را تغییر دهیم:

داده‌هایی که ما به تابع renderChart ارسال می‌کنیم، آرایه‌ای متشکل از دو آرایه خواهد بود. اولین مورد (data[0]) داده‌ها مربوط به درآمد این هفته، و دومین مورد (data[1]) هم داده‌های مربوط به هفته پیش خواهد بود.

در آخر، دیتاست‌های نمودار، یک آبجکت ثانویه خواهند داشت: مجموعه‌های مربوط به هفته پیش.

function float2dollar(value) {

    return "U$ " + (value).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');

}

function renderChart(data, labels) {

    var ctx = document.getElementById("myChart").getContext('2d');

    var myChart = new Chart(ctx, {

        type: 'line',

        data: {

            labels: labels,

            datasets: [

                {

                    label: 'This week',

                    data: data[0],

                    borderColor: 'rgba(75, 192, 192, 1)',

                    backgroundColor: 'rgba(75, 192, 192, 0.2)',

                },

                {

                    label: 'Last week',

                    data: data[1],

                    borderColor: 'rgba(192, 192, 192, 1)',

                    backgroundColor: 'rgba(192, 192, 192, 0.2)',

                }

            ]

        },

        options: {

            scales: {

                yAxes: [{

                    ticks: {

                        beginAtZero: true,

                        callback: function (value, index, values) {

                            return float2dollar(value);

                        }

                    }

                }]

            },

        }

    });

}

function getChartData() {

    $("#loadingMessage").html('<img src="./giphy.gif" alt="" srcset="">');

    $.ajax({

        url: "http://localhost:3000/chartdata",

        success: function (result) {

            $("#loadingMessage").html("");

            var data = [];

            data.push(result.thisWeek);

            data.push(result.lastWeek);

            var labels = result.labels;

            renderChart(data, labels);

        },

        error: function (err) {

            $("#loadingMessage").html("Error");

        }

    });

}

$("#renderBtn").click(

    function () {

        getChartData();

    }

);

نتایج بسیار زیبا هستند، و مقایسه دو هفته اخیر را آسان می‌کنند.

انواع دیگر نمودارها

همانطور که پیش‌تر اشاره شد، Chart.js تنوع خوبی از انواع نمودار را فراهم می‌کند.

ویژگی‌هایی که در اینجا مطالعه می‌کنیم، در میان انواع مختلف گرافیک با مقداری تفاوت، مشترک هستند. برای مثال در نمودار دایره‌ای، به جای این که فقط یک رنگ را به اضای هر مجموعه منتقل کنیم، ممکن است آرایه‌ای از رنگ‌ها را منتقل کنیم؛ زیرا قطعه‌های مختلف دایره باید رنگ متفاوتی داشته باشند.

بیایید با استفاده از ویژگی text مربوط به title، یک عنوان هم به نمودار خود اضافه کنیم.

var labels = [

    "Vote for blue",

    "vote for red",

];

var data = [

    70,

    30,

];

var pie = document.getElementById("pieChart").getContext('2d');

var myChart = new Chart(pie, {

    type: 'pie',

    data: {

        labels: labels,

        datasets: [

            {

                data: data,

                borderColor: ['rgba(75, 192, 192, 1)', 'rgba(192, 0, 0, 1)'],

                backgroundColor: ['rgba(75, 192, 192, 0.2)', 'rgba(192, 0, 0, 0.2)'],

            }

        ]

    },

    options: {

        title: {

            display: true,

            text: "Colors election"

        }

    }

});

نتیجه:

ترکیب انواع نمودار

Chart.js شما را قادر می‌سازد تا نو دوع نمودار را بر روی صفحه مشابه ترکیب کنید. بیایید به مثال رستوران برگردیم. حال ما می‌خواهیم تجزیه و تحلیل کنیم تا ببینیم که هر روزه چند مشتری داشته‌ایم، اما همچنان مقدار درآمد را نیز ببینیم. در این مثال، می‌توانیم از یک نمودار نواری برای مشتری‌ها، به همراه یک نمودار خطی برای درآمد استفاده کنیم.

جای دارد اشاره کنم که در این مورد، باید از یک محور Y ثانویه استفاده کنیم. علت آن این است که درآمد از نظر تعداد، بیشتر از تعداد مشتری‌ها خواهد بود و از این رو نوارها در مقیاس درآمد، بسیار کوچک‌تر خواهند بود.

برای این کار، فایل دیگری به نام mixChart.js خواهیم ساخت:

var labels = [

    "sunday",

    "monday",

    "tuesday",

    "wednesday",

    "thursday",

    "friday",

    "saturday"

];

var revenues = [

    20000,

    14000,

    12000,

    15000,

    18000,

    19000,

    22000

];

var clients = [

    201,

    140,

    80,

    150,

    190,

    170,

    202

];

var mix = document.getElementById("mixChart").getContext('2d');

var mixChart = new Chart(mix, {

    type: 'bar',

    data: {

        labels: labels,

        datasets: [

            {

                type: 'line',

                label: "Revenues",

                data: revenues,

                borderColor: 'rgba(75, 192, 192, 1)',

                backgroundColor: 'rgba(0, 0, 0, 0)',

                yAxisID: 'revenues',

            },

            {

                label: "Clients",

                data: clients,

                borderColor: 'rgba(0, 0, 0, 0)',

                backgroundColor: 'rgba(192, 75, 192, 0.5)',

                yAxisID: 'clients',

            }

        ]

    },

    options: {

        scales: {

            yAxes: [

                {

                    id: "revenues",

                    ticks: {

                        beginAtZero: true,

                    },

                    scaleLabel: {

                        display: true,

                        labelString: 'Revenues (U$)'

                      }

                },

                {

                    id: "clients",

                    position: 'right',

                    ticks: {

                        beginAtZero: true,

                    },

                    scaleLabel: {

                        display: true,

                        labelString: 'Clients'

                      }

                },

            ]

        },

    }

});

برای ترکیب کردن انواع، باید یک type اصلی برای نمودار تعریف کنید، و برای موردی که می‌خواهیم تغییر دهید، باید متغیر type را داخل دیتاست جداگانه مجددا تعریف کنید. برای مثال ما، ما type اصلی را برابر با type: “bar” قرار می‌دهیم، اما داخل دیتاست اول، ما آن را به صورت type: “line” مجددا تعریف می‌کنیم.

yAxes ویژگی‌‌ای از scales است، که خود یک آبجکت از options می‌باشد. این yAxes در واقع یک آرایه است و ما را قادر می‌سازد تا از چندین مقیاس برای مجموعه‌های مختلف استفاده کنیم. در این مثال، ما از دو محور Y استفاده می‌کنیم. به همین علت، باید برای هر کدام یک id تعیین کنیم. اولین محور Y، آیدی «id: “revennues”»، و دومین مورد هم آیدی «id: “clients”» را دارد.

ما از position: ‘right’ بر روی محور مشتری استفاده کرده‌ایم، تا تیک‌های آن را در سمت راست نمودار نمایش دهیم. برای خواناتر کردن همه چیز، ما یک labelString هم بر روی هر محور اضافه می‌کنیم، تا افراد بدانند که محور سمت چپ درآمدها بوده، و محور سمت راست، تعداد مشتری‌ها است.

حال چه؟

در واقع مواردی زیادی باقی‌اند! همانطور که می‌توانید ببینید، Chart.js بسیار قابل سفارشی بوده، و همچنان موضوعات زیادی مربوط به قابلیت‌های آن وجود دارند:

  • نمایش داده‌های انباشه
  • سفارشی سازی tooltipها
  • انواع داده دو بعدی
  • رویدادهای تعاملی (مانند کلیک)
  • مقیاس لگاریتمی
  • و...

همچنین پلاگین‌هایی وجود دارند که کاربرد Chart.js را ارتقا می‌دهند. من فکر می‌کنم که پلاگین chartjs-plugin-datalabels به خصوص پرکاربردد است و پیشنهاد می‌کنم که آن را امتحان کنید.

شما می‌توانید فایل‌هایی مربوط به این مقاله را در repository گیت‌هاب مربوطه پیدا کنید.

منبع

مقالات پیشنهادی

بررسی مقالات هفته چهارم فروردین ۹۷

در هفته چهارم فروردین ۹۷ ما نگاه بسیار وسیعی روی موضوعات مختلف داشته‌ایم. در این هفته به موضوعات تجربه‌کاربری،‌ رابط کاربری، جاوااسکریپت، نودجی‌اس، با...

بررسی اولیه Laravel Horizon

Laravel Horizon یک نرم افزار متن باز هست که صف های Redis لاراول رو با یک داشبورد زیبا و سیستم پیکربندی کدمحور همراه میکنه. داشبورد Horizon یک اپلیکیشن...

چگونه متا‌ تگ‌های وبسایت را بررسی و تولید کنیم؟

در این آموزش سریع قرار است که به صورت کامل ابزاری ساده و در عین حال بسیار مفید به نام Hey Meta را معرفی کنم. اگر می‌خواهید بدانید که وبسایت‌تان چه چیز...

بررسی تفاوت‌های SQL و NoSQL – همراه با مثال

بیشتر ما در حال حاضر با بانک‌های اطلاعاتی SQL آشنایی داریم، حال تفاوتی در نام آن‌ها نیست، خواه MySql باشد یا اوراکل و یا هر مورد دیگری. در کنار SQL، د...