こちらの記事の続きです。
HTMLドキュメント内のタグにdatasetを指定して進捗サークルチャートを表示させるためのスクリプトです。
ユーザー操作や時間経過等で可変させることは想定していません。
スクリプト
'use strict';
{
window.addEventListener('DOMContentLoaded', function() {
for(const e of document.querySelectorAll('[data-circleChart]')) {
if(e.querySelector('.circleChart') === null) {
e.innerHTML +=
'<div class="circleChart">' +
' <div class="graph"></div>' +
' <div class="percent"><div>**.*%</div></div>' +
'</div>';
const
d1 = e.querySelector('.circleChart'),
d2 = d1.querySelector('.graph'),
d3 = d1.querySelector('.percent');
d1.style.position = 'relative';
d1.style.display = 'inline-block';
d2.style.position = 'absolute';
d2.style.mixBlendMode = 'multiply';
d3.style.position = 'absolute';
d3.style.width = '100%';
d3.style.height = '100%';
const params = e.dataset.circlechart;
let size = 100,
weight = 10,
color = '#08f',
backcolor = '#ccc',
holecolor = 'transparent',
percent = 50,
fixed = 1,
textcolor = '#fff',
textmixblendmode = 'difference',
textleft = '',
textright = '',
texttop = '',
textbottom = '',
textdisplay = '';
params.split(';').forEach(v => {
if(v.trim() !== '') {
const
param = v.split(':'),
key = param[0].trim().toLowerCase(),
value = param[1].trim().toLowerCase();
if(key === 'size') {
size = parseInt(value);
}
else if(key === 'weight') {
weight = parseFloat(value);
if(weight <= 0) weight = -100;
}
else if(key === 'color') {
if(checkProperty(value)) color = value;
}
else if(key === 'backcolor') {
if(checkProperty(value)) backcolor = value;
}
else if(key === 'holecolor') {
if(checkProperty(value)) holecolor = value;
}
else if(key === 'textcolor') {
if(checkProperty(value)) textcolor = value;
}
else if(key === 'textmixblendmode') {
if(checkProperty(value, 'mixBlendMode')) textmixblendmode = value;
}
else if(key === 'textleft') {
if(checkProperty(value, 'left')) textleft = value;
}
else if(key === 'textright') {
if(checkProperty(value, 'right')) textright = value;
}
else if(key === 'texttop') {
if(checkProperty(value, 'top')) texttop = value;
}
else if(key === 'textbottom') {
if(checkProperty(value, 'bottom')) textbottom = value;
}
else if(key === 'textdisplay') {
if(checkProperty(value, 'display')) textdisplay = value;
}
else if(key === 'value') {
percent = parseFloat(value);
}
else if(key === 'fixed') {
fixed = Math.floor(value);
if(fixed < 0) fixed = 0;
else if(fixed > 10) fixed = 10;
}
}
});
d1.style.width =
d1.style.height =
d2.style.width =
d2.style.height = `${size}px`;
const r1 = size / 2;
const r2 = r1 - r1 / 100 * weight;
const deg = percent * 3.6;
d1.style.background = `radial-gradient(${holecolor} ${r2 - 1}px, #fff ${r2}px, #fff ${r1 - 1}px, #0000 ${r1}px)`;
d2.style.background = `radial-gradient(#fff ${r2 - 1}px, #0000 ${r2}px, #0000 ${r1 - 1}px, #fff ${r1}px), conic-gradient(${color} ${deg}deg, ${backcolor} 0)`;
const d3c = d3.querySelector('div');
d3c.textContent = `${percent.toFixed(fixed)}%`;
d3.style.fontSize = `${(r1 / 4).toFixed(1)}px`;
d3.style.color = textcolor;
d3.style.mixBlendMode = textmixblendmode;
if(textleft === '' && textright === '') {
d3c.style.position = 'relative';
d3.style.textAlign = 'center';
}
else {
d3c.style.position = 'absolute';
if(textleft !== '') d3c.style.left = textleft;
if(textright !== '') d3c.style.right = textright;
}
if(texttop === '' && textbottom === '') {
d3c.style.top = '60%';
}
else {
if(texttop !== '') d3c.style.top = texttop;
if(textbottom !== '') d3c.style.bottom = textbottom;
}
if(textdisplay !== '') d3c.style.display = textdisplay;
function checkProperty(str, p) {
const dummy = document.createElement('p');
if(p === undefined) p = 'color';
dummy.style[p] = str;
return dummy.style[p] === '' ? false : true;
}
}
}
});
}
使用方法
<script src='circle_chart.js'></script>
でスクリプトを読み込んでおき、チャートを表示させたい要素にdata-circleChartを付加することで表示できます。
<div data-circleChart='プロパティリスト'></div>
以下のプロパティを指定できます。
size: チャートの直径(pixel)
weight: チャートの半径に対する太さの割合(0~100)
color: チャートのメインカラー(CSSのcolorで指定可能な値)
backColor: チャートのバックカラー(CSSのcolorで指定可能な値)
holeColor: チャートの穴の色(CSSのcolorで指定可能な値 デフォルトは透明)
textColor: 文字カラー(CSSのcolorで指定可能な値)
textMixBlendMode: 文字ブレンドモード(CSSのmix-blend-modeで設定可能な値 デフォルトはdifference)
textLeft: 文字の横表示位置 左基準(CSSのleftで設定可能な値)
textRight: 文字の横表示位置 右基準(CSSのrightで設定可能な値)
textLeft,textRight共に無指定の場合は中央に表示
textTop: 文字の縦表示位置 上基準(CSSのtopで設定可能な値)
textBottom: 文字の縦表示位置 下基準(CSSのbottomで設定可能な値)
textTop,textBottom共に無指定の場合は上から60%の位置に表示
textDisplay: 文字の表示形式(CSSのdisplayで設定可能な値 非表示にするためにnoneを指定するケースが多いと思います)
value: チャートの進捗度(0~100)
fixed: 進捗度の数字の少数表示桁数(0~10)
サンプル
<script src='./circle_chart.js'></script>
<body bgcolor='#ddeedd'>
<!-- プロパティ無指定 -->
<div data-circleChart></div>
<!-- プロパティ指定例 -->
<span data-circleChart='size:150; weight:100; backColor:#fca; color:#fa0; value:45.67; fixed:1'></span>
<span data-circleChart='size:200; value:56.7; fixed:0; weight:30; color:#f8a; holecolor:pink; textColor:red; textMixBlendMode:normal; textright:5%; textTop:44%'></span>
<div data-circleChart='textDisplay:none;'></div>
<!-- 親要素のstyle併用 -->
<div data-circleChart='size:150; fixed:2' style='position:absolute; top:5px; right:5px;font-family:serif;'></div>
</body>