js で綺麗なグラフを書く
今回は Apexcharts を利用して、簡単にグラフを書いてみました。
下は体重を範囲指定可能にして描画したものです。普通に書こうと思ったら結構しんどそうな見た目ですが、Apexchartsのテンプレを利用させてもらってます。
今回はそのサンプルコードだけ簡単に紹介させてもらいます。
準備
この github の js を、./apexcharts.js で保存する
./brush_charts.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>Brush charts</title> <link href="./brush.css" rel="stylesheet" /> <style> #wrapper { padding-top: 20px; padding-left: 10px; background: #fff; border: 1px solid #ddd; box-shadow: 0 22px 35px -16px rgba(0, 0, 0, 0.1); max-width: 650px; margin: 35px auto; } #chart-line { position: relative; margin-top: -40px; } </style> <script> window.Promise || document.write( '<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"><\/script>' ) window.Promise || document.write( '<script src="https://cdn.jsdelivr.net/npm/eligrey-classlist-js-polyfill@1.2.20171210/classList.min.js"><\/script>' ) window.Promise || document.write( '<script src="https://cdn.jsdelivr.net/npm/findindex_polyfill_mdn"><\/script>' ) </script> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> <script src="./apexcharts.js"></script> <script src="https://cdn.jsdelivr.net/npm/vue-apexcharts"></script> <script> // Replace Math.random() with a pseudo-random number generator to get reproducible results in e2e tests // Based on https://gist.github.com/blixt/f17b47c62508be59987b var _seed = 42; Math.random = function() { _seed = _seed * 16807 % 2147483647; return (_seed - 1) / 2147483646; }; </script> <script> const ADAY_MILISEC = 86400000; /* // this function will generate output in this format // data = [ [timestamp, 23], [timestamp, 33], [timestamp, 12] ... ] */ function generateDayWiseTimeSeries(baseval, count, yrange) { var i = 0; var series = []; while (i < count) { var x = baseval; var y = Math.floor(Math.random() * (yrange.max - yrange.min + 1)) + yrange.min; series.push([x, y]); baseval += ADAY_MILISEC; i++; } console.log(series[0]); return series; } var data = generateDayWiseTimeSeries(new Date('11 Mar 2021').getTime(), 142, { min: 82, max: 90 }); console.log(data); </script> </head> <body> <div id="app"> <div id="wrapper"> <div id="chart-line2"> <apexchart type="line" height="230" :options="chartOptions" :series="series"></apexchart> </div> <div id="chart-line"> <apexchart type="area" height="130" :options="chartOptionsLine" :series="seriesLine"></apexchart> </div> </div> </div> <!-- Below element is just for displaying source code. it is not required. DO NOT USE --> <div id="html"> <div id="wrapper"> <div id="chart-line2"> <apexchart type="line" height="230" :options="chartOptions" :series="series"></apexchart> </div> <div id="chart-line"> <apexchart type="area" height="130" :options="chartOptionsLine" :series="seriesLine"></apexchart> </div> </div> </div> <script> let init_min_time = '19 Jun 2021'; let init_max_time = '6 Aug 2021'; new Vue({ el: '#app', components: { apexchart: VueApexCharts, }, data: { series: [{ data: data }], chartOptions: { chart: { id: 'chart2', type: 'line', height: 230, toolbar: { autoSelected: 'pan', show: false } }, colors: ['#546E7A'], stroke: { width: 3 }, dataLabels: { enabled: false }, fill: { opacity: 1, }, markers: { size: 0 }, xaxis: { type: 'datetime' }, yaxis: { offsetY: 70, title: { text: "My Body Weight -70kg" }, } }, seriesLine: [{ data: data }], chartOptionsLine: { chart: { id: 'chart1', height: 130, type: 'area', brush:{ target: 'chart2', enabled: true }, selection: { enabled: true, xaxis: { min: new Date(init_min_time).getTime(), max: new Date(init_max_time).getTime() } }, }, colors: ['#008FFB'], fill: { type: 'gradient', gradient: { opacityFrom: 0.91, opacityTo: 0.1, } }, xaxis: { type: 'datetime', tooltip: { enabled: false } }, yaxis: { tickAmount: 4 } }, }, }) </script> </body> </html>
./brush.css
/*@import url('https://fonts.googleapis.com/css?family=Lato:300,400,600,700');*/ * { font-family: Arial; } body { height: 100vh; background: #f9f9f9; } #chart, .chart-box { padding-top: 20px; padding-left: 10px; background: #fff; border: 1px solid #ddd; box-shadow: 0 22px 35px -16px rgba(0,0,0, 0.1); } select.flat-select { -moz-appearance: none; -webkit-appearance: none; appearance: none; background: #008FFB url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\' width=\'60px\' height=\'60px\'><polyline fill=\'white\' points=\'46.139,15.518 25.166,36.49 4.193,15.519\'/></svg>") no-repeat scroll right 2px top 9px / 16px 16px; border: 0 none; border-radius: 3px; color: #fff; font-family: arial,tahoma; font-size: 16px; font-weight: bold; outline: 0 none; height: 33px; padding: 5px 20px 5px 10px; text-align: center; text-indent: 0.01px; text-overflow: ""; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); transition: all 0.3s ease 0s; width: auto; -webkit-transition: 0.3s ease all; -moz-transition: 0.3s ease all; -ms-transition: 0.3s ease all; -o-transition: 0.3s ease all; transition: 0.3s ease all; } select.flat-select:focus, select.flat-select:hover { border: 0; outline: 0; } .apexcharts-canvas { margin: 0 auto; } #html { display: none; }
おわりに
70kgくらいの体重に対し、変化量が1~2kgぐらいであったため、y軸のオートスケールがうまくいかなかった。
そのため、無理矢理 y 軸を「体重-70kg」みたいにすることで調整してみました。
Apex には様々なオプションやサンプルコードもありますので、もっと勉強してみたいと思います。