chartjs-plugin-piechart-outlabels
Version:
Chart.js plugin to display float data labels on pie/doughnut chart outside the border.
358 lines (318 loc) • 13.1 kB
HTML
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="icon" type="image/ico" href="./favicon.ico">
<script src="https://rawgit.com/chartjs/chartjs.github.io/master/dist/master/Chart.min.js"></script>
<script src="../dist/chartjs-plugin-piechart-outlabels.js"></script>
<script src="./utils.js"></script>
<script src="./jscolor.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<title>Pie Chart Outlabels</title>
</head>
<body class="container-fluid">
<div class="row">
<div class="col-3 side">
<div class="header">Pie Chart Outlabels</div>
<div class="actions">
<button class="btn btn-info" onclick="randomize(this)">Randomize</button>
<button class="btn btn-success" onclick="addData(this)">Add Data</button>
<button class="btn btn-danger" onclick="removeData(this)">Remove Data</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dataModel">
Update Dataset
</button>
<div class="form-group">
<label>Label</label>
<div class="input-group">
<label class="input-group-addon" for="text">Text</label>
<textarea class="form-control" oninput="changeParam('text', this.value)" id="text">%l %p VALUE: %v</textarea>
</div>
<div class="input-group">
<label class="input-group-addon" for="lineColor">Border</label>
<span class="input-group-addon">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" checked name="lineColor" onchange="changeParam('borderColor', undefined)" value="left" id="borderColorCheckbox"/>
Adapt
</label>
</span>
<input class="form-control jscolor" value="FFFFFF" onchange="changeParam('borderColor', '#' + this.value)" id="borderColor">
</div>
<div class="input-group">
<label class="input-group-addon">Border Width</label>
<span class="input-group-addon" style="width: 100%">
<input oninput="changeParam('borderWidth', +this.value)" type="range" min="0" max="20" value="2" step="1" class="slider">
</span>
</div>
<div class="input-group">
<label class="input-group-addon">Border Radius</label>
<span class="input-group-addon" style="width: 100%">
<input oninput="changeParam('borderRadius', +this.value)" type="range" min="0" max="20" value="2" step="1" class="slider">
</span>
</div>
<div class="input-group">
<label class="input-group-addon" for="lineColor">Background</label>
<span class="input-group-addon">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" checked name="lineColor" onchange="changeParam('backgroundColor', undefined)" value="left" id="backgroundColorCheckbox"/>
Adapt
</label>
</span>
<input class="form-control jscolor" value="FFFFFF" onchange="changeParam('backgroundColor', '#' + this.value)" id="backgroundColor">
</div>
<div class="input-group">
<span class="input-group-addon">Color</span>
<input class="form-control jscolor" value="FFFFFF" onchange="changeParam('color', '#' + this.value)">
</div>
<div class="input-group">
<label class="input-group-addon" for="lineColor">Align</label>
<span class="input-group-addon">
<label class="form-check-label">
<input type="radio" class="form-check-input" name="textAlign" onchange="changeParam('textAlign', this.value)" id="left" value="left" />
L
</label>
</span>
<span class="input-group-addon" style="width: 100%;">
<label class="form-check-label" style="margin: 0 auto;">
<input type="radio" checked class="form-check-input" name="textAlign" onchange="changeParam('textAlign', this.value)" value="center" />
C
</label>
</span>
<span class="input-group-addon">
<label class="form-check-label">
<input type="radio" class="form-check-input" name="textAlign" onchange="changeParam('textAlign', this.value)" value="right" />
R
</label>
</span>
</div>
<div class="input-group">
<label class="input-group-addon">Padding</label>
<span class="input-group-addon" style="width: 100%">
<input oninput="changeParam('padding', +this.value)" type="range" min="0" max="20" value="3" step="1" class="slider">
</span>
</div>
</div>
<div class="form-group">
<label>Line</label>
<div class="input-group">
<label class="input-group-addon" for="lineColor">Color</label>
<span class="input-group-addon">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" checked name="lineColor" onchange="changeParam('lineColor', undefined)" value="left" id="lineColorCheckbox"/>
Adapt
</label>
</span>
<input class="form-control jscolor" value="000000" onchange="changeParam('lineColor', '#' + this.value)" id="lineColor">
</div>
<div class="input-group">
<label class="input-group-addon">Width</label>
<span class="input-group-addon" style="width: 100%">
<input oninput="changeParam('lineWidth', +this.value)" step="0.1" type="range" min="1" max="10" value="2" class="slider">
</span>
</div>
<div class="input-group">
<label class="input-group-addon">Length</label>
<span class="input-group-addon" style="width: 100%">
<input oninput="changeParam('stretch', +this.value)" type="range" min="20" max="100" value="45" step="0.5" class="slider">
</span>
</div>
</div>
</div>
</div>
<div class="col-9">
<div>
<canvas id="pieChart"></canvas>
</div>
<!-- Modal -->
<div class="modal fade" id="dataModel" tabindex="-1" role="dialog" aria-labelledby="dataModelLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="dataModelLabel">Data Set Editor</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div id="modal-body" class="container-fluid"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="updateDataSet(this)">Update</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<script id="script-init">
var DATA_COUNT = 10;
Samples.srand(4);
var bgColors = Samples.colors({
color: Samples.color(2),
count: DATA_COUNT
});
Chart.helpers.merge(Chart.defaults.global, {
tooltips: false,
layout: {
padding: 10
},
elements: {
line: {
fill: false
},
point: {
hoverRadius: 7,
radius: 5
}
},
plugins: {
legend: false,
title: true
}
});
var params = {
display: true,
text: [
'%l (%p.3) \n VALUE: (%v.3)',
'%l (%p) \n VALUE: (%v)',
'SIMPLE VALUE \n => %v',
'VALUE WITH PRECISION 4 \n => %v.4',
'SIMPLE PERCENT \n => %p',
'PERCENT WITH PRECISION 3 \n => %p.3',
'JUST LABEL \n => %l',
'JUST TEXT'
],
borderWidth: 2,
lineWidth: 2,
padding: 3,
textAlign: 'center',
stretch: 45,
font: {
resizable: true,
minSize: 12,
maxSize: 18
},
valuePrecision: 1,
percentPrecision: 2
}
var data = Samples.numbers({
count: DATA_COUNT,
min: 0,
max: 100
});
var body = '<div class="row"><div class="col">Label</div><div class="col">Value</div><div class="col">Bg</div><div class="col">BgLabel</div><div class="col">Border</div><div class="col">Line</div><div class="col">Font</div><div class="col-1"></div></div>';
for(var i = 0; i < data.length; ++i) {
body += '<div class="row dataSet"><div class="col input-group"><input type="text" class="form-control" value="${Samples.LABELS[i]}" /></div><div class="col input-group"><input type="text" class="form-control" value="${data[i]}" /></div><div class="col input-group"><input class="form-control jscolor" value="${bgColors[i].slice(1)}"></div><div class="col input-group"><input class="form-control jscolor" value="${bgColors[i].slice(1)}"></div><div class="col input-group"><input class="form-control jscolor" value="${bgColors[i].slice(1)}"></div><div class="col input-group"><input class="form-control jscolor" value="${bgColors[i].slice(1)}"></div><div class="col input-group"><input class="form-control jscolor" value="FFFFFF"></div><div class="col-1 input-group"><button type="button" class="close" onclick="removeRow(this)"><span aria-hidden="true">×</span></button></div></div>';
}
$('#modal-body').html(body);
</script>
<script id="script-construct">
var chart = new Chart('pieChart', {
type: 'outlabeledPie',
data: {
labels: Samples.LABELS,
datasets: [{
backgroundColor: bgColors,
data: data
}]
},
options: {
zoomOutPercentage: 60,
plugins: {
outlabels: params
}
}
});
</script>
<script id="script-actions">
function removeRow(el) {
var parents = $(el).parents();
parents[1].remove(parents[0]);
}
function updateDataSet(el) {
var LABELS = [];
var DATA = [];
var BGCOLORS = [];
var BGLCOLORS = [];
var BORDERCOLORS = [];
var LINECOLORS = [];
var FONTCOLORS = [];
$('#dataModel').modal('toggle');
var els = Array.from($('.dataSet'));
els.forEach(function(el, i) {
var children = $(el).children();
LABELS.push($(children[0]).children('input').val());
DATA.push($(children[1]).children('input').val());
BGCOLORS.push('#' + $(children[2]).children('input').val());
BGLCOLORS.push('#' + $(children[3]).children('input').val());
BORDERCOLORS.push('#' + $(children[4]).children('input').val());
LINECOLORS.push('#' + $(children[5]).children('input').val());
FONTCOLORS.push('#' + $(children[6]).children('input').val());
});
chart.data.labels = chart.data.labels.map(function(label, i) {
return LABELS[i];
});
chart.data.datasets.forEach(function(dataset, i) {
dataset.data = DATA;
dataset.backgroundColor = BGCOLORS;
});
chart.options.plugins.outlabels.backgroundColor = BGLCOLORS;
chart.options.plugins.outlabels.lineColor = LINECOLORS;
chart.options.plugins.outlabels.borderColor = BORDERCOLORS;
chart.options.plugins.outlabels.color = FONTCOLORS;
chart.update();
}
function changeParam(p, value) {
var arr = [
'lineColor',
'backgroundColor',
'borderColor'
];
if(~arr.indexOf(p)) {
if(value) {
$('#' + p + 'Checkbox').prop('checked', false);;
}
if(!$('#' + p + 'Checkbox').is(':checked')) {
value = '#' + $('#' + p).val();
}
}
params[p] = value;
chart.options.plugins.outlabels[p] = value;
chart.update();
}
function randomize() {
chart.data.datasets.forEach(function(dataset, i) {
dataset.backgroundColor = dataset.data.map(function(value) {
return Samples.color();
});
dataset.data = dataset.data.map(function(value) {
return Samples.rand(0, 100);
});
});
chart.update();
}
function addData() {
chart.data.labels.push(chart.data.labels.length);
chart.data.datasets.forEach(function(dataset, i) {
dataset.backgroundColor.push(Samples.color());
dataset.data.push(Samples.rand(0, 100));
});
chart.update();
}
function removeData() {
chart.data.labels.shift();
chart.data.datasets.forEach(function(dataset, i) {
dataset.backgroundColor.shift();
dataset.data.shift();
});
chart.update();
}
</script>
</body>
</html>