Skip to content

Instantly share code, notes, and snippets.

@dexion
Created June 26, 2020 13:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dexion/ad3086eb83b8d330101e6c8dbcd90802 to your computer and use it in GitHub Desktop.
Save dexion/ad3086eb83b8d330101e6c8dbcd90802 to your computer and use it in GitHub Desktop.
<!doctype html>
<head>
<title>Chart.JS zoom test</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3"></script>
<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@0.7.7"></script>
</head>
<body>
<input type="number" id="last_ticks" name="last_ticks" min="1" value="1"/>
<div style="width:75%;">
<canvas id="myChart"></canvas>
</div>
<script>
function numberRoundDecimal(v, n) {
return Math.round((v + Number.EPSILON) * Math.pow(10, n)) / Math.pow(10, n)
}
Chart.defaults.LineWithLine = Chart.defaults.line;
Chart.controllers.LineWithLine = Chart.controllers.line.extend({
draw: function(ease) {
Chart.controllers.line.prototype.draw.call(this, ease);
if (this.chart.tooltip._active && this.chart.tooltip._active.length) {
var activePoint = this.chart.tooltip._active[0],
ctx = this.chart.ctx,
prev_ticks = document.getElementById("last_ticks").value || 1,
widthChart = this.chart.scales['x-axis-0'].right - this.chart.scales['x-axis-0'].left,
pieces = this.chart.config.data.labels.length - 1,
widthPiece = widthChart / pieces,
x = activePoint.tooltipPosition().x,
topY = this.chart.scales['y-axis-1'].top,
bottomY = this.chart.scales['y-axis-1'].bottom;
if(x - widthPiece * prev_ticks < this.chart.scales['x-axis-0'].left) {
x = this.chart.scales['x-axis-0'].left;
}
else {
x -= widthPiece * prev_ticks;
}
// draw line
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 2;
ctx.strokeStyle = '#07C';
ctx.stroke();
ctx.restore();
}
}
});
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
// type: 'line',
type: 'LineWithLine',
// The data for our dataset
data: {
labels: [1591394407, 1591398007, 1591401606, 1591405207, 1591408806, 1591412406, 1591416006,1591394407, 1591398007, 1591401606, 1591405207, 1591408806, 1591412406, 1591416006,1591394407, 1591398007, 1591401606, 1591405207, 1591408806, 1591412406, 1591416006,1591394407, 1591398007, 1591401606, 1591405207, 1591408806, 1591412406, 1591416006,1591394407, 1591398007, 1591401606, 1591405207, 1591408806, 1591412406, 1591416006,1591394407, 1591398007, 1591401606, 1591405207, 1591408806, 1591412406, 1591416006],
datasets: [{
label: 'Set-1',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
fill: false,
data: [0, 10, 5, 2, 20, 30, 45,0, 10, 5, 2, 20, 30, 45,0, 10, 5, 2, 20, 30, 45,0, 10, 5, 2, 20, 30, 45,0, 10, 5, 2, 20, 30, 45,0, 10, 5, 2, 20, 30, 45],
yAxisID: 'y-axis-1'
},
{
label: 'Set-2',
backgroundColor: 'rgb(122, 0, 132)',
borderColor: 'rgb(122, 0, 132)',
fill: false,
data: [100, 105, 102, 120, 130, 145, 110,100, 105, 102, 120, 130, 145, 110,100, 105, 102, 120, 130, 145, 110,100, 105, 102, 120, 130, 145, 110,100, 105, 102, 120, 130, 145, 110,100, 105, 102, 120, 130, 145, 110],
yAxisID: 'y-axis-2'
},
{
label: 'Set-3',
backgroundColor: 'rgb(255, 99, 0)',
borderColor: 'rgb(255, 99, 0)',
fill: false,
data: [1002, 10020, 10030, 10045, 1000, 1010, 1005,1002, 10020, 10030, 10045, 1000, 1010, 1005,1002, 10020, 10030, 10045, 1000, 1010, 1005,1002, 10020, 10030, 10045, 1000, 1010, 1005,1002, 10020, 10030, 10045, 1000, 1010, 1005,1002, 10020, 10030, 10045, 1000, 1010, 1005],
yAxisID: 'y-axis-3'
}]
},
// Configuration options go here
options: {
responsive: true,
tooltips: {
axis: 'x',
mode: 'index',
intersect: false,
callbacks: {
title: function(tooltipItem, data) {
var title = data.labels[tooltipItem[0].index] || '';
if (title) {
title = new Date(title * 1000).toLocaleString("en");
}
return title;
},
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var prev;
var prev_ticks = document.getElementById("last_ticks").value || 1;
if(tooltipItem.index - prev_ticks < 0){
prev = data.datasets[tooltipItem.datasetIndex].data[0];
}
else {
prev = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index-prev_ticks];
}
percentage = numberRoundDecimal(label*100/prev-100, 3);
label += ` (${ percentage }%)`;
return label;
},
labelTextColor: function(tooltipItem, chart) {
var label = chart.config.data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var prev;
var prev_ticks = document.getElementById("last_ticks").value || 1;
if(tooltipItem.index - prev_ticks < 0){
prev = chart.config.data.datasets[tooltipItem.datasetIndex].data[0];
}
else {
prev = chart.config.data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index-prev_ticks];
}
if(prev < label){
return "green";
}
if(prev > label){
return "red";
}
return "white";
}
}
},
hover: {
mode: 'nearest',
intersect: true
},
stacked: true,
title: {
display: false,
text: 'Chart.js Line Chart - Multi Axis'
},
scales: {
xAxes: [{
display: true,
ticks: {
callback: function(value, index, values) {
return new Date(value * 1000).toLocaleString("en");
}
}
}],
yAxes: [{
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'left',
id: 'y-axis-1',
ticks: {
min: 0.01
}
}, {
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'left',
id: 'y-axis-2',
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}, {
type: 'linear', // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: 'right',
id: 'y-axis-3',
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
},
plugins: {
zoom: {
// Container for pan options
pan: {
// Boolean to enable panning
enabled: false,
// Panning directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow panning in the y direction
// A function that is called as the user is panning and returns the
// available directions can also be used:
// mode: function({ chart }) {
// return 'xy';
// },
mode: 'x',
// rangeMin: {
// // Format of min pan range depends on scale type
// // x: null,
// // y: null
// },
// rangeMax: {
// // Format of max pan range depends on scale type
// // x: null,
// // y: null
// },
// On category scale, factor of pan velocity
speed: 20,
// Minimal pan distance required before actually applying pan
threshold: 100,
// Function called while the user is panning
onPan: function({chart}) { console.log(`I'm panning!!!`); },
// Function called once panning is completed
onPanComplete: function({chart}) { console.log(`I was panned!!!`); }
},
// Container for zoom options
zoom: {
// Boolean to enable zooming
enabled: true,
// Enable drag-to-zoom behavior
drag: true,
// Drag-to-zoom effect can be customized
// drag: {
// borderColor: 'rgba(225,225,225,0.3)'
// borderWidth: 5,
// backgroundColor: 'rgb(225,225,225)',
// animationDuration: 0
// },
// Zooming directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow zooming in the y direction
// A function that is called as the user is zooming and returns the
// available directions can also be used:
// mode: function({ chart }) {
// return 'xy';
// },
mode: 'x',
rangeMin: {
// Format of min zoom range depends on scale type
// x: null,
// y: null
},
rangeMax: {
// Format of max zoom range depends on scale type
// x: null,
// y: null
},
// Speed of zoom via mouse wheel
// (percentage of zoom on a wheel event)
speed: 1,
// Minimal zoom distance required before actually applying zoom
threshold: 2,
// On category scale, minimal zoom level before actually applying zoom
// sensitivity: 3,
// Function called while the user is zooming
onZoom: function({chart}) { console.log(`I'm zooming!!!`); },
// Function called once zooming is completed
onZoomComplete: function({chart}) { console.log(`I was zoomed!!!`); }
}
}
}
}
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment