Is it possible to use mouseenter and mouseleave event in chart js? - javascript

Right now I'm using onHover into each pie to add some scale/zoom, but I want to use mouseenter and mouseleave. So on mouseenter on each pie it will add some scale/zoom, and on mouseleave, I want it back to its original state.
either mouseenter-mouseleave or mouseover-mouseout is fine.
here is the codepen:
https://codepen.io/graydirt/pen/NWNZNyQ
Thanks guys!
var ctx = document.getElementById('chartPie').getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['Red', 'Blue', 'Green'],
datasets: [{
label: '# of Votes',
data: [12, 19, 20],
backgroundColor: [
'red',
'blue',
'green'
],
datalabels: {
color: '#000'
}
}]
},
options: {
legend: {
display: false
},
layout: {
padding: 5
},
onHover: function (evt, elements) {
let segment;
if (elements && elements.length) {
segment = elements[0];
this.chart.update();
selectedIndex = segment["_index"];
segment._model.outerRadius += 5;
} else {
if (segment) {
segment._model.outerRadius -= 5;
}
segment = null;
}
}
}
});
.chart-pie {
width: 400px;
height: 400px;
margin: auto;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.7.0"></script>
<div class="container p-4">
<div class="chart-pie position-relative">
<canvas id="chartPie"></canvas>
</div>
</div>

Your code is already designed to return to the original size on mouseout, but you have a subtle bug.
You need to define the segment variable outside the chart. With a saved reference to the segment, the mouseout event will fire and the onHover handler will return the pie to its original size.
Please see the attached example below:
let segment;
var ctx = document.getElementById('chartPie').getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['Red', 'Blue', 'Green'],
datasets: [{
label: '# of Votes',
data: [12, 19, 20],
backgroundColor: [
'red',
'blue',
'green'
],
datalabels: {
color: '#000'
}
}]
},
options: {
legend: {
display: false
},
layout: {
padding: 5
},
onHover: function(evt, elements) {
if (elements && elements.length) {
segment = elements[0];
this.chart.update();
selectedIndex = segment["_index"];
segment._model.outerRadius += 5;
} else {
if (segment) {
segment._model.outerRadius -= 5;
}
segment = null;
}
}
}
});
.chart-pie {
width: 400px;
height: 400px;
margin: auto;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.7.0"></script>
<div class="container p-4">
<div class="chart-pie position-relative">
<canvas id="chartPie"></canvas>
</div>
</div>

Related

How to hide label of specific data?, chartjs plugin datalabels

I made a radial progress bar using the nested doughnut chart, the object works fine.
I wanted to show the progress on a label, but the label became visible in the data I used as the background.
q1:How can i hide the label i just use as background?
q2:Do you think it is good to make progress bar using chartjs? (real time) I would be very happy if you could provide information about another alternative library.
My code:
var _gaugeValue = 5;
var _gaugeValue2 = 43;
var _gagueMaxVal = 100;
var _gagueMaxVal2 = 150;
var ctxGauge = document.getElementById("myCanvasGauge");
var myGauge = new Chart(ctxGauge, {
type: "doughnut",
data: {
datasets: [
{
data: [_gaugeValue2, _gagueMaxVal2 - _gaugeValue2],
backgroundColor: ["rgba(255,0,0,1)", "rgba(220,220,220,1)"],
hoverOffset: 4,
cutout: "80%",
},
{
data: [_gaugeValue, _gagueMaxVal - _gaugeValue],
backgroundColor: ["rgba(71,148,218,1)", "rgba(220,220,220,1)"],
hoverOffset: 4,
cutout: "70%",
options: {
plugins: {
datalabels: {
display: false,
},
},
},
},
],
},
options: {
response: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
enabled: false,
},
datalabels: {
backgroundColor: function (context) {
return context.dataset.backgroundColor;
},
borderColor: "white",
borderRadius: 25,
borderWidth: 2,
color: "white",
display: function (context) {
var dataset = context.dataset;
var count = 2;
var value = dataset.data[1];
return value > count * 1.5;
},
font: {
weight: "bold",
},
padding: 6,
formatter: Math.round,
},
},
},
plugins: [ChartDataLabels],
});
function changeData() {
_gaugeValue = Math.floor(Math.random() * 100) - 1;
myGauge.data.datasets[1].data = [
_gaugeValue,
_gagueMaxVal - _gaugeValue,
];
myGauge.update();
}
function changeData2() {
_gaugeValue2 = Math.floor(Math.random() * 100) - 1;
myGauge.data.datasets[0].data = [
_gaugeValue2,
_gagueMaxVal2 - _gaugeValue2,
];
myGauge.update();
}
.gauge-container {
margin: auto;
}
.button-container {
margin: auto;
padding: 10px;
}
<script
src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"
integrity="sha512-TW5s0IT/IppJtu76UbysrBH9Hy/5X41OTAbQuffZFU6lQ1rdcLHzpU5BzVvr/YFykoiMYZVWlr/PX1mDcfM9Qg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"
integrity="sha512-R/QOHLpV1Ggq22vfDAWYOaMd5RopHrJNMxi8/lJu8Oihwi4Ho4BRFeiMiCefn9rasajKjnx9/fTQ/xkWnkDACg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<div class="gauge-container">
<canvas id="myCanvasGauge"></canvas>
</div>
<div class="button-container">
<button onclick="changeData()">Change Data 1</button>
</div>
<div class="button-container">
<button onclick="changeData2()">Change Data 2</button>
</div>
you can use the display callback to determine which labels are displayed
if I follow correctly, you do not want labels to appear on the gray portion of the chart...?
if so, only display the first value...
display: function (context) {
return context.dataIndex === 0;
},
see following working snippet...
var _gaugeValue = 5;
var _gaugeValue2 = 43;
var _gagueMaxVal = 100;
var _gagueMaxVal2 = 150;
var ctxGauge = document.getElementById("myCanvasGauge");
var myGauge = new Chart(ctxGauge, {
type: "doughnut",
data: {
datasets: [
{
data: [_gaugeValue2, _gagueMaxVal2 - _gaugeValue2],
backgroundColor: ["rgba(255,0,0,1)", "rgba(220,220,220,1)"],
hoverOffset: 4,
cutout: "80%",
},
{
data: [_gaugeValue, _gagueMaxVal - _gaugeValue],
backgroundColor: ["rgba(71,148,218,1)", "rgba(220,220,220,1)"],
hoverOffset: 4,
cutout: "70%",
options: {
plugins: {
datalabels: {
display: false,
},
},
},
},
],
},
options: {
response: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
enabled: false,
},
datalabels: {
backgroundColor: function (context) {
return context.dataset.backgroundColor;
},
borderColor: "white",
borderRadius: 25,
borderWidth: 2,
color: "white",
display: function (context) {
return context.dataIndex === 0;
},
font: {
weight: "bold",
},
padding: 6,
formatter: Math.round,
},
},
},
plugins: [ChartDataLabels],
});
function changeData() {
_gaugeValue = Math.floor(Math.random() * 100) - 1;
myGauge.data.datasets[1].data = [
_gaugeValue,
_gagueMaxVal - _gaugeValue,
];
myGauge.update();
}
function changeData2() {
_gaugeValue2 = Math.floor(Math.random() * 100) - 1;
myGauge.data.datasets[0].data = [
_gaugeValue2,
_gagueMaxVal2 - _gaugeValue2,
];
myGauge.update();
}
.gauge-container {
margin: auto;
}
.button-container {
margin: auto;
padding: 10px;
}
<script
src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"
integrity="sha512-TW5s0IT/IppJtu76UbysrBH9Hy/5X41OTAbQuffZFU6lQ1rdcLHzpU5BzVvr/YFykoiMYZVWlr/PX1mDcfM9Qg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.0.0/chartjs-plugin-datalabels.min.js"
integrity="sha512-R/QOHLpV1Ggq22vfDAWYOaMd5RopHrJNMxi8/lJu8Oihwi4Ho4BRFeiMiCefn9rasajKjnx9/fTQ/xkWnkDACg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
<div class="gauge-container">
<canvas id="myCanvasGauge"></canvas>
</div>
<div class="button-container">
<button onclick="changeData()">Change Data 1</button>
</div>
<div class="button-container">
<button onclick="changeData2()">Change Data 2</button>
</div>

Make highcharts fullscreen also fullscreen the div wrapping the chart

Is there a way to make the div wrapping the chart part of the fullscreen as well?
This is my code: fiddle
THis code only fulscreens the chart. When I try and do to point the div I need in the fullscreen:
Highcharts.FullScreen = function(container) {
this.init(ontainer.parentNode.parentNode);
};
My fullscreen is getting cut off and also not adding the parent div to the full screen. Is there to make the whole div with id yo and the other div inside (<div>Random Data and text.......</div>) as part of the fullscreen?
You can connect the content of a custom element through chart.renderer.text().add() by specifying this element with the html() method:
chart.renderer.text(selector.html(), 0, 0).add();
...hiding this element through css, set the display: none:
.random_data {
display: none;
}
This is the piece of code to add:
function (chart) {
chart.renderer
.text($(".random_data").html(), 10, 10)
.css({
color: "green",
fontSize: "12px",
})
.add();
}
JavaScript:
let chart = Highcharts.chart(
"container",
{
chart: {
type: "column",
},
title: {
text: "",
},
xAxis: {
categories: ["one", "two", "three"],
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0,
},
},
yAxis: {
title: {
text: "",
},
endOnTick: false,
},
series: [
{
name: "books",
data: [
["one", 64161.71548379661],
["two", 3570.6197029028076],
["three", -200.70625619033547],
],
marker: {
symbol: "circle",
},
},
],
},
function (chart) {
chart.renderer
.text($(".random_data").html(), 10, 10)
.css({
color: "green",
fontSize: "12px",
})
.add();
}
);
let btn = document.getElementById("btn");
btn.addEventListener("click", function () {
Highcharts.FullScreen = function (container) {
console.log(container.parentNode.parentNode);
this.init(container.parentNode); // main div of the chart
};
Highcharts.FullScreen.prototype = {
init: function (container) {
if (container.requestFullscreen) {
container.requestFullscreen();
} else if (container.mozRequestFullScreen) {
container.mozRequestFullScreen();
} else if (container.webkitRequestFullscreen) {
container.webkitRequestFullscreen();
} else if (container.msRequestFullscreen) {
container.msRequestFullscreen();
}
},
};
chart.fullscreen = new Highcharts.FullScreen(chart.container);
});
CSS:
.random_data {
display: none;
}
HTML:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="yo">
<div class="random_data">Random Data and text.......</div>
<div id="container" style="height: 400px; margin-top: 1em;"></div>
</div>
<button id="btn">
Show full screen
</button>

Adding Context to Django View Causing My Highcharts Map to Disappear

This is my first Django project, and I am working on a Django html template that should contain a Chart.JS bar graph (https://www.chartjs.org/docs/latest/charts/bar.html) alongside a Highcharts drilldown map of the US (https://www.highcharts.com/demo/maps/map-drilldown).
I've successfully implemented my Chart.JS bar graph and passed data to it from our AWS RDS. But now when I try to implement even just the stock Highcharts code from their website, the map fails to render at all. After trying to isolate the problem, I've found that the map does render if I simply delete "context" from the return statement in my view (i.e. delete "context" from the final line in my first block of code below). But this obviously then inhibits my bar graph from rendering. I think I must be missing something with how the highcharts data is loaded in the presence of other context data, but I've been unable to fix it such that both the graph and map render. Any help would be greatly appreciated!
My Django View:
def index(request):
mydb = mysql.connector.connect(
host=xxxx,
user=xxxx,
password=xxxx,
database=xxxx
)
mycursor = mydb.cursor()
mycursor.execute("WITH CS1 AS (SELECT cts.Name, cts.State, m.Frequently, m.Always FROM Masks m JOIN Counties cts ON (m.FIPS = cts.FIPS)) SELECT CS1.State, AVG((CS1.Frequently+CS1.Always)*100) AS Perc_High_Frequency FROM CS1 WHERE CS1.State<>'Puerto Rico' GROUP BY CS1.State ORDER BY Perc_High_Frequency DESC")
tempList = mycursor.fetchall()
statesMaskName = [item[0] for item in tempList]
statesMaskPerc = [item[1] for item in tempList]
context={'statesMaskName':statesMaskName, 'statesMaskPerc':statesMaskPerc}
return render(request,'index.html', context)
The relevant HTML/JS:
<html lang="en" dir="ltr">
<head>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div class="fixed-header">
<h1>COVID-19 Sentiment and Mask Practices</h1>
</div>
<div>
<div class="col-lg-3" style="float: left; max-height: 6500px;max-width:400px;overflow: scroll; overflow-x:hidden;">
<div style="background-color: #17202A;">
<span style="color: #F7F9F9; text-align: center;"><h4>% Population Who "Frequently" or "Always" Wear Masks When In Public Within 6" of Others (as of July 2-14, 2020)</h4></span>
</div>
<div class="col-lg-12">
<form method="post" enctype="multipart/form-data" action="selectState">
{% csrf_token %}
<div class="col-lg-4" style="float: left; max-height: 3000px;">
<br><br style="line-height: 15px"/>
{% for state in statesMaskName %}
<table style="border-width: 2px; border: #333;">
<tr>
<input type="submit" value="{{state}}" name="statesMaskName" style="width:130px;">
</tr>
</table>
{% endfor%}
</div>
<div style="float: left;">
<canvas id="myChart" height="1360" width="250"></canvas>
</div>
</form>
</div>
</div>
<div class="col-lg-6">
</div>
<div class="col-lg-3">
</div>
</div>
<br>
</body>
<!--my updated code for chartjs graph-->
<script>
const labels = {{statesMaskName|safe}};
const data = {
labels: labels,
datasets: [{
label: '% Population',
color: 'orange',
backgroundColor: 'orange',
borderColor: 'orange',
data: {{statesMaskPerc|safe}},
}]
};
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
color: 'white',
scales: {
y: {
grid: {
color: '#b3b1ad',
},
ticks: {
color: 'white',
},
display: false
},
x: {
grid: {
color: '#b3b1ad',
},
ticks: {
color: 'white',
// Include a % sign in the ticks
callback: function(value, index, values) {
return value + '%';
}
}
}
}
}
};
var myChart = new Chart(
document.getElementById('myChart'),
config
);
</script>
<!--stock code for highcharts map-->
<div id="usMap" style="height: 500px; min-width: 310px; max-width: 800px; margin: 0 auto"></div>
<script src="https://code.highcharts.com/maps/highmaps.js"></script>
<script src="https://code.highcharts.com/maps/modules/data.js"></script>
<script src="https://code.highcharts.com/maps/modules/drilldown.js"></script>
<script src="https://code.highcharts.com/maps/modules/exporting.js"></script>
<script src="https://code.highcharts.com/maps/modules/offline-exporting.js"></script>
<script src="https://code.highcharts.com/mapdata/countries/us/us-all.js"></script>
<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<script type="text/javascript">
/*
TODO:
- Check data labels after drilling. Label rank? New positions?
*/
let data = Highcharts.geojson(Highcharts.maps['countries/us/us-all']);
const separators = Highcharts.geojson(Highcharts.maps['countries/us/us-all'], 'mapline');
// Set drilldown pointers
data.forEach((d, i) => {
d.drilldown = d.properties['hc-key'];
d.value = i; // Non-random bogus data
});
function getScript(url, cb) {
const script = document.createElement('script');
script.src = url;
script.onload = cb;
document.head.appendChild(script);
}
// Instantiate the map
Highcharts.mapChart('usMap', {
chart: {
events: {
drilldown: function (e) {
if (!e.seriesOptions) {
const chart = this,
mapKey = 'countries/us/' + e.point.drilldown + '-all';
// Handle error, the timeout is cleared on success
let fail = setTimeout(() => {
if (!Highcharts.maps[mapKey]) {
chart.showLoading('<i class="icon-frown"></i> Failed loading ' + e.point.name);
fail = setTimeout(() => {
chart.hideLoading();
}, 1000);
}
}, 3000);
// Show the spinner
chart.showLoading('<i class="icon-spinner icon-spin icon-3x"></i>'); // Font Awesome spinner
// Load the drilldown map
getScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', () => {
data = Highcharts.geojson(Highcharts.maps[mapKey]);
// Set a non-random bogus value
data.forEach((d, i) => {
d.value = i;
});
// Hide loading and add series
chart.hideLoading();
clearTimeout(fail);
chart.addSeriesAsDrilldown(e.point, {
name: e.point.name,
data: data,
dataLabels: {
enabled: true,
format: '{point.name}'
}
});
});
}
this.setTitle(null, { text: e.point.name });
},
drillup: function () {
this.setTitle(null, { text: '' });
}
}
},
title: {
text: 'Highcharts Map Drilldown'
},
subtitle: {
text: '',
floating: true,
align: 'right',
y: 50,
style: {
fontSize: '16px'
}
},
colorAxis: {
min: 0,
minColor: '#E6E7E8',
maxColor: '#005645'
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
plotOptions: {
map: {
states: {
hover: {
color: '#EEDD66'
}
}
}
},
series: [{
data: data,
name: 'USA',
dataLabels: {
enabled: true,
format: '{point.properties.postal-code}'
}
}, {
type: 'mapline',
data: separators,
color: 'silver',
enableMouseTracking: false,
animation: {
duration: 500
}
}],
drilldown: {
activeDataLabelStyle: {
color: '#FFFFFF',
textDecoration: 'none',
textOutline: '1px #000000'
},
drillUpButton: {
relativeTo: 'spacingBox',
position: {
x: 0,
y: 60
}
}
}
});
</script>
</html>

Chart.js Chart does not start at

I want to that the Chart start at 0. But it takes always the lower value to start.
I already tried a few things but nothing works.
It never takes the settings done in de options Part of de javascript part. So i dont know what the issue is. It never starts at 0. But this is what i want to.
Please help. Thank you very much :)
Looks currently like this: https://school.luis-luescher.com/m242/moin/index.php
<!DOCTYPE html>
<html>
<head>
<title>Database</title>
<style type="text/css">
BODY {
width: 550PX;
}
#chart-container {
width: 100%;
height: auto;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.4/dist/Chart.min.js"></script>
</head>
<body>
<div id="chart-container">
<canvas id="graphCanvas"></canvas>
</div>
<script>
$(document).ready(function() {
showGraph();
});
function showGraph() {
{
$.post("https://school.luis-luescher.com/m242/moin/data.php",
function(data) {
console.log(data);
var trytime = [];
var count = [];
for (var i in data) {
trytime.push(data[i].trytime);
count.push(data[i].count);
}
var chartdata = {
labels: trytime,
datasets: [{
label: 'Erfolgreiche Authentifizerungen',
backgroundColor: '#8846f1',
borderColor: '#a446f1',
hoverBackgroundColor: '#CCCCCC',
hoverBorderColor: '#666666',
borderWidth: 1,
data: count,
}],
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
var graphTarget = $("#graphCanvas");
var barGraph = new Chart(graphTarget, {
type: 'bar',
data: chartdata
});
});
}
}
</script>
</body>
</html>
Your Options object must be outside chartData.
var barGraph = new Chart(graphTarget, {
type: 'bar',
data: chartdata,
options: options
});

Chart.js: width and height of a pie chart not respected

I'm using Chart.js to create pie charts. I need each chart to be 76x76px. Unfortunately, the rendered chart is always a bit smaller than the size if the wrapping div and the canvas itself.
If you inspect the chart in the FIDDLE, you'll see what I mean: the canvas element has a fixed size but the chart itself doesn't fill it fully.
It's almost as if there was a top margin reserved for something that isn't there.
The code:
HTML
<div class="wrapper">
<canvas id="myChart" width="76" height="76"></canvas>
</div>
JS
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
datasets: [{
data: [30, 70],
backgroundColor: [
'green',
'gray'
],
borderWidth: 0
}]
},
options: {
tooltips: {
enabled: false
},
events: []
}
});
CSS
.wrapper {
width: 76px;
height: 76px;
}
Any ideas what I should do to make the pie chart fill the 76x76px canvas?
The additional space is reserved for the legend, which is enabled by default. Simply disable it and you should have the whole space for the chart:
legend: {
display: false
}
A working example:
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
datasets: [{
data: [30, 70],
backgroundColor: [
'green',
'gray'
],
borderWidth: 0
}]
},
options: {
tooltips: {
enabled: false
},
legend: {
display: false // <- the important part
},
events: []
}
});
.wrapper {
width: 76px;
height: 76px;
border: 1px solid black; /* for demonstration purposes*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js" integrity="sha512-d9xgZrVZpmmQlfonhQUvTR7lMPtO7NkZMkA0ABN3PHCbKA5nqylQ/yWlFAyY6hYgdF1Qh6nYiuADWwKB4C2WSw==" crossorigin="anonymous"></script>
<div class="wrapper">
<canvas id="myChart" width="76" height="76"></canvas>
</div>

Categories