はじめに
-
こちらの投稿(【Qiita API】いろんな方法で Views、Likes、Stocksを取得(JavaScript、Google Script、Python, Vue.js)で、Qiitaの自分の投稿について、QiitaAPIの情報を取得し、「ページビュー(View)」・「いいね(Like)」「ストック(Stock)」などをテーブル表示をさせました。
-
そのときに、定期実行(1日1回)にて、データベースに毎日の情報を貯めていました(Python使用)。そのデータを使って、視覚的に見れるように、グラフ表示(複数軸)をさせようと思いました。
やりたいこと
<グラフ表示>
・現在日付から過去1カ月のデータを取得する。
・取得したデータをchart.jsにてグラフ表示する。
(X軸:日付、Y軸1-棒グラフ:Qiita-View数、Y軸2-折れ線グラフ:Qiitaいいね・ストックの合計)
<テーブル>
・取得したデータの中で最新日付のデータをテーブルを表示する。
使用技術
- Javascript
- Chart.js
デモサイト
※これをみると、投稿がまったく見られないなんてことはなく、毎日少なからずViewがあるんだなぁと思います。(さすがQiita)
コード・ポイント
- グラフの描画部分
sample.js
// グラフを描画する
var ctx = document.getElementById("canvas").getContext("2d");
window.myChart = new Chart(ctx, {
type: 'bar',
data: barChartData, //グラフデータをセット
options: complexChartOption //データオプションをセット
});
- グラフデータのセット
sample.js
// グラフデータのセット
var barChartData = {
labels: labelData, //ラベルデータのセット(日付)
datasets: [
{
type: 'line',
label: 'Total-Likes/Stocks',
data: lineData, //lineデータのセット(LIKES+STOCKSの合計)
borderColor: "rgba(060,179,113,0.8)",
pointBackgroundColor: "rgba(060,179,113,0.8)",
fill: false,
yAxisID: "y-axis-1",
},
{
type: 'bar',
label: 'Total Views',
data: barData, //barデータのセット(VIEWSの合計)
borderColor: "rgba(54,164,235,0.8)",
backgroundColor: "rgba(54,164,235,0.5)",
yAxisID: "y-axis-2",
},
],
};
- グラフオプションの設定
ticksは取得できた値に応じて、動的に算出する。
sample.js
// グラフオプションの設定
var complexChartOption = {
responsive: true,
scales: {
yAxes: [
{
id: "y-axis-1",
type: "linear",
position: "left",
ticks: {
max: setgoodsMax, //lineデータのメモリ最大値をセット
min: setgoodsMin, //lineデータのメモリ最小値をセット
stepSize: 10 //lineデータのメモリ幅をセット
},
},
{
id: "y-axis-2",
type: "linear",
position: "right",
ticks: {
max: setviewsMax, //barデータのメモリ最大値をセット
min: setviewsMin, //barデータのメモリ最小値をセット
stepSize: 1000 //barデータのメモリ幅をセット
},
gridLines: {
drawOnChartArea: false,
},
}
],
};
- 全体のコード
全体のコード
jsgraph.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Qiita Item Get Graph Display</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
<body onload="getData()">
<div class="container">
<br>
<h3>Qiitaデータグラフ表示</h3>
<br>
<div class="container">
<canvas id="canvas"></canvas>
</div>
<div class="container">
<div id="result"></div>
</div>
</div>
<script src="https://code.jquery.com/jquery-2.1.1.js" integrity="sha256-FA/0OOqu3gRvHOuidXnRbcmAWVcJORhz+pv3TX2+U6w=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.bundle.min.js"></script>
<script>
function getData(){
var qiitadata = [];
// 現在日付の設定
var date = new Date();
var yyyy = date.getFullYear();
var mm = toDoubleDigits(date.getMonth() + 1);
var dd = toDoubleDigits(date.getDate());
var yyyymmdd = yyyy + mm + dd;
var hyphendate = yyyy + "-" + mm + "-" + dd;
// 1桁の数字を0埋めで2桁にする
function toDoubleDigits(num){
num += "";
if (num.length === 1) {
num = "0" + num;
}
return num;
};
// DB情報の取得
var request = new XMLHttpRequest();
request.open('GET', 'xxxxxxxxxxxxxxxxxxxx.php?setdate=' + yyyymmdd, true);
request.responseType = 'json';
request.onload = function () {
qiitadata = this.response;
drawGraph(qiitadata); // グラフの描画
drawTable(qiitadata, hyphendate); // テーブルの描画
};
request.send();
};
// グラフの描画
function drawGraph(qiitadata) {
var nowdate;
var sumviews = 0;
var sumgoods = 0;
var labelData = [];
var lineData = [];
var barData = [];
// 取得データをループして、グラフ描画データにセットする
for(var i = 0; i < qiitadata.length; i++){
// 初回は日付のセット
if(i == 0){
nowdate = qiitadata[i].setdate;
}else{
// 日付が変わったとき
if(nowdate != qiitadata[i].setdate){
//データをセット
labelData.push(nowdate);
lineData.push(sumgoods);
barData.push(sumviews);
//日付のセットと合計初期化
nowdate = qiitadata[i].setdate;
sumgoods = 0;
sumviews = 0;
};
};
sumgoods = sumgoods + Number(qiitadata[i].likes) + Number(qiitadata[i].stocks);
sumviews = sumviews + Number(qiitadata[i].views);
// ループの最後の処理
if(i == (qiitadata.length - 1)){
labelData.push(nowdate);
lineData.push(sumgoods);
barData.push(sumviews);
}
};
// セットされたデータからticksを算出
var goodsMax = Math.max.apply(null, lineData);
var setgoodsMax = goodsMax + 10;
do {
setgoodsMax += 1;
} while ("00" != String(setgoodsMax).substr(-2,2));
var goodsMin = Math.min.apply(null, lineData);
var setgoodsMin = goodsMin - 10;
do {
setgoodsMin -= 1;
} while ("00" != String(setgoodsMin).substr(-2,2));
var viewsMax = Math.max.apply(null, barData);
var setviewsMax = viewsMax + 1000;
do {
setviewsMax += 1;
} while ("000" != String(setviewsMax).substr(-3,3));
var viewsMin = Math.min.apply(null, barData);
var setviewsMin = viewsMin - 1000;
do {
setviewsMin -= 1;
} while ("000" != String(setviewsMin).substr(-3,3));
// グラフデータのセット
var barChartData = {
labels: labelData,
datasets: [
{
type: 'line',
label: 'Total-Likes/Stocks',
data: lineData,
borderColor: "rgba(060,179,113,0.8)",
pointBackgroundColor: "rgba(060,179,113,0.8)",
fill: false,
yAxisID: "y-axis-1",
},
{
type: 'bar',
label: 'Total Views',
data: barData,
borderColor: "rgba(54,164,235,0.8)",
backgroundColor: "rgba(54,164,235,0.5)",
yAxisID: "y-axis-2",
},
],
};
// グラフオプションの設定
var complexChartOption = {
responsive: true,
scales: {
yAxes: [
{
id: "y-axis-1",
type: "linear",
position: "left",
ticks: {
max: setgoodsMax,
min: setgoodsMin,
stepSize: 10
},
},
{
id: "y-axis-2",
type: "linear",
position: "right",
ticks: {
max: setviewsMax,
min: setviewsMin,
stepSize: 1000
},
gridLines: {
drawOnChartArea: false,
},
}
],
}
};
// グラフを描画する
var ctx = document.getElementById("canvas").getContext("2d");
window.myChart = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: complexChartOption
});
};
// テーブルの描画
function drawTable(qiitadata, hyphendate) {
// 配列の中の最大値を取得する
var maxno = Math.max.apply(null, qiitadata.map(function(o){return o.no;}));
// console.log(maxno);
var sum_view = 0;
var sum_like = 0;
var sum_stock = 0;
var html = '<br><h3>Qiita記事一覧(' + hyphendate + '時点)</h3><br>' +
'<table class="table">' +
'<thead class="thead-dark">' +
'<tr><th scope="col">No</th><th scope="col">タイトル</th><th scope="col">VIEWS</th><th scope="col">LIKES</th><th scope="col">STOCKS</th><th scope="col">LIKE率</th><th scope="col">STOCK率</th></tr></thead><tbody>'
// 取得データをループして、グラフ描画データにセットする
for(var i = 0; i < qiitadata.length; i++){
// 本日日付になったら、格納処理
if(qiitadata[i].setdate == hyphendate){
html +=
'<tr>' +
'<th scope="row">' + (maxno + 1 - Number(qiitadata[i].no)) + '</th>' +
'<td><a href="' + qiitadata[i].url + '" target="_blank">' + qiitadata[i].title + '</a></td>' +
'<td>' + qiitadata[i].views + '</td>' +
'<td>' + qiitadata[i].likes + '</td>' +
'<td>' + qiitadata[i].stocks + '</td>' +
'<td>' + qiitadata[i].per_like + '</td>' +
'<td>' + qiitadata[i].per_stock + '</td>' +
'</tr>';
sum_view += Number(qiitadata[i].views);
sum_like += Number(qiitadata[i].likes);
sum_stock += Number(qiitadata[i].stocks);
};
};
// html に合計を設定し、書き出し
html +=
'<tr class="table-warning">' +
'<th scope="row">計</th>' +
'<td></td>' +
'<td>' + sum_view + '</td>' +
'<td>' + sum_like + '</td>' +
'<td>' + sum_stock + '</td>' +
'<td>' + '' + '</td>' +
'<td>' + '' + '</td>' +
'</tr>' +
'</tbody></table>';
var result = $("#result");
result.empty();
result.append(html);
};
</script>
</body>
</html>
まとめ
- DBなどに貯まっているデータをJavascriptでグラフ表示することができました。
- グラフの描画やグラフのオプションは、参考にさせていただいたサイトをみるととてもよくわかります(そのままのところも多々あります。感謝)
- 次は、Vue.jsで動的に動くグラフの作成を実施してみたいと思います。→2020/03月更新しました。実践!令和 500円貯金(投資)をするといくら貯まるのか?(Vue.jsでのグラフ&テーブル表示)