Angular2 ng2-chart customizations? - javascript

I have started to use angular2 ng2-chart. I have few questions regarding the below image which I created using angular2 ng2-chart but still want to do more customization:
Questions:
1) How can I draw a dotted-line between two points when there are no values like in above image Nov-7 has value 0 (zero)?
2) How can I make a shadow effect, opacity or a combination of more than one colors?
3) How can I get the value of y-axis when I hover on any of the defined point and also if I want to change the y-axis grid color on mouse hover. What is the best way to do it using ng2-chart hover function?
Current sample code and config file:
index.html
<div class="container">
<div class="row">
<div class="overview-page">
<div class="overview-page-title">
<h2>Overview</h2>
</div>
<div class="chart-view">
<canvas baseChart
class="chart"
[datasets]="charts.datasets"
[labels]="charts.labels"
[colors]="charts.chartColors"
[options]="charts.options"
[legend]="false"
[chartType]="charts.type"
(chartHover)="chartHovered($event)">
</canvas>
</div>
</div>
</div>
</div>
index.component.ts
import {Component, Output, EventEmitter, OnInit} from '#angular/core';
import {Router} from '#angular/router';
import {Config} from '../../../config/config';
#Component({
templateUrl: 'index.html',
styleUrls: ['../../../../common/stylesheets/pages/index.scss']
})
export class IndexComponent implements OnInit {
protected charts: any;
ngOnInit() {
this.charts = (<any>Config.get('test')).charts;
console.log(this.charts);
}
chartHovered(e:any):void {
console.log(e);
}
}
Config.ts:
import * as Immutable from 'immutable';
export const Config = Immutable.Map({
test: {
charts: {
datasets: [{
data: [40, 48.2, 0, 52.6, 51.1, 57.6, 74.8]
}],
labels: ['Nov 5', 'Nov 6', 'Nov 7', 'Nov 8', 'Nov 9', 'Nov 10', 'Nov 11'],
type: 'line',
options: {
scales: {
xAxes: [{
gridLines: {
color: 'rgba(171,171,171,1)',
lineWidth: 1
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
max: 100,
min: 0,
stepSize: 25
},
gridLines: {
color: 'rgba(171,171,171,1)',
lineWidth: 0.5
}
}]
},
responsive: true
},
chartColors: [{
backgroundColor: 'rgba(25,10,24,0.2)',
borderColor: 'rgba(225,10,24,0.2)',
pointBackgroundColor: 'rgba(225,10,24,0.2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(225,10,24,0.2)'
}]
}
}
});

I couldn't find the best answer to your first question. However you can define multiple datasets with no intersection and use different colours (see the point 2) for that one.
http://valor-software.com/ng2-charts/
For the second one when you define colours, as you are already doing it in your code:
chartColors: [{
backgroundColor: 'rgba(25,10,24,0.2)',
borderColor: 'rgba(225,10,24,0.2)',
pointBackgroundColor: 'rgba(225,10,24,0.2)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(225,10,24,0.2)'
}
The last number in rgba is the opacity. For having different colours the option is to define multiple datasets, otherwise it randomises the colours and you won't get mixed ones. A plunker here:
http://plnkr.co/edit/9PckMZiDYZjRz1PA0Suq
For the last question regarding getting the value of x-axis, look at the event which is logged to console on bounded events.

Related

ChartJS: single bar of bar chart. I want a border around entire bar, including the max Y-value

I want to create a single bar using a bar chart. The setup is that the user can select different choices (representing the colors). In this example (codesandbox link below) I have a bar that has a max value of 90.000. The three chosen values are 20.000, 30.000 and 15.000, totaling 65.000.
Now, my goal is to have a border around this entire bar, not just the colors. In the image below this is represented with the red border. Currently I do this by putting a container element around my canvas element, but I would like to do this in the canvas itself, without using a container element. Someone has an idea on how to do this?
Codesandbox link
You need to define different dataset properties such as borderSkipped, borderRadius, borderWidth to achieve what you're looking for.
Don't know why but I also had to define the data of the dataset at the bottom as a floating bar in order to see the rounded border.
data: [[0, 20000]]
Please take a look at the runnable code below and see how it could work.
new Chart('chart', {
type: 'bar',
data: {
labels: [''],
datasets: [{
label: "currentAmount",
data: [[0, 20000]],
backgroundColor: "#bbb",
borderColor: "#f00",
borderWidth: 2,
borderSkipped: 'top',
borderRadius: 30,
barPercentage: 0.5
},
{
label: "amount 1",
data: [30000],
backgroundColor: "orange",
borderColor: "#f00",
borderWidth: { left: 2, right: 2 },
barPercentage: 0.5
},
{
label: "amount 2",
data: [15000],
backgroundColor: "green",
borderColor: "#f00",
borderWidth: { left: 2, right: 2 },
barPercentage: 0.5
},
{
label: "remaining",
data: [25000],
backgroundColor: "#fff",
borderColor: "#f00",
borderWidth: 2,
borderSkipped: 'bottom',
borderRadius: 30,
barPercentage: 0.5
},
]
},
options: {
plugins: {
legend: {
display: false
},
tooltip: {
displayColors: false
}
},
scales: {
y: {
display: false,
stacked: true,
beginsAtZero: true
},
x: {
display: false,
stacked: true
}
}
}
});
canvas {
max-width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<canvas id="chart"></canvas>

make horizontal graph with percentage :react js

I trying to make a horizontal chart with react-chartjs i want each data to show the percentage
import React, { Component } from "react";
import { HorizontalBar } from "react-chartjs-2";
export default class Button extends Component {
render() {
const dataHorBar = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
backgroundColor: "#EC932F",
borderColor: "rgba(255,99,132,1)",
borderWidth: 1,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [65, 59, 80, 81, 56, 55, 40]
}
]
};
return (
<div>
<HorizontalBar data={dataHorBar} />
</div>
);
}
}
Here is the code of what I have tried
https://codesandbox.io/s/react-chartjs-bar-horizontal-bar-forked-be9wil
I also want to remove the background lines and make the graph more rounded edge
In order to use the feature for having rounded rectangles, you need to update to the v3 of chartjs, therefore, the following code will be working only on this version. But you can adapt it to a previous version, you will just not be able to change the border radius of the rectangle.
You can use the datalabels plugin, in order to display custom text in your chart, and format the label like this:
options: {
plugins: {
datalabels: {
formatter: value => value + " %", // Add the percentage after the value
align: "end",
anchor: "end",
clip: true,
}
}
}
For the shapes, you can use the option borderRadius, to have rounded edges. You can find more information here, but in the end, you just have to specify a value for the borderRadius, in each dataset:
datasets: [
{
label: "My First dataset",
backgroundColor: "#EC932F",
borderColor: "rgba(255,99,132,1)",
borderWidth: 1,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [65, 59, 80, 81, 56, 55, 40],
borderRadius: 50, // Give a number
}
]
Finally, for removing the grid lines, you can use this snippet, and pass those options to your chart
options: {
scales: {
x: {
grid: {
display: false // Hide x grid
}
},
y: {
grid: {
display: false // Hide y grid
}
}
}
};
That's it for the ground principle. Here is a live working example, if you really wants to see how to implement it.

Chartjs custom colors not displaying when dataset is changed

I am trying to create 2 distinct line charts which display 2 different datasets. With this, I want to display 2 different colors for each chart.
<div style="display: block" *ngIf='signalRService.data'>
<canvas baseChart id="data1"
[datasets]="signalRService.data1"
[labels]="chartLabels"
[options]="chartOptions"
[legend]="chartLegend"
[chartType]="chartType"
[colors]="colors"
(chartClick)="chartClicked($event)"></canvas>
</div>
<div style="display: block" *ngIf='signalRService.data'>
<canvas baseChart id="data2"
[datasets]="signalRService.data2"
[labels]="chartLabels"
[options]="chartOptions"
[legend]="chartLegend"
[chartType]="chartType"
[colors]="colors"
(chartClick)="chartClicked($event)"></canvas>
</div>
At the moment, I have signalRService.dataX which is containing specific data from the larger signalRService.data. When I separate the data into 2 variables to assign them to different charts, the colors and color settings stop working and revert to their defaults (Light gray with a fill). I also have them both on the same componenent.
Fixes I have tried:
I have tried to use the [data] property instead of [datasets] which hasn't worked, as I can't read signalRService.data[0] because it's undefined.
I tried to create 2 separate arrays for colors, which hasn't worked either.
I have looked into, but haven't really figured out how I can use [datasets]="signalRService.data" and then hide a different dataset for each chart.
The best solution would be if I was able to adjust colors and maintain the rest of the code or to be able to hide a dataset on each graph (I will have 3, so I'd want to hide 2 of 3 datasets). However, I'm open to any ideas, even what I might have "tried" but done incorrectly.
Below is my app.component.ts file in case it's necessary.
import { Component, OnInit } from '#angular/core';
import { SignalRService } from './services/signal-r.service';
import { HttpClient } from '#angular/common/http';
import { ChartOptions } from 'chart.js';
import { Label } from 'ng2-charts';
import * as pluginCrosshair from 'chartjs-plugin-crosshair';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
public chartOptions: (ChartOptions) = {
responsive: true,
spanGaps: false,
animation: {
duration: 0
},
scales: {
// We use this empty structure as a placeholder for dynamic theming.
xAxes: [{}],
yAxes: [
{
id: 'y-axis-0',
position: 'left',
ticks: {
max : 30,
min: -30
}
},
]
},
plugins: {
tooltips: {
mode: "interpolate",
intersect: false,
},
crosshair: {
line: {
color: '#F66', // crosshair line color
width: 2, // crosshair line width
value: '0'
},
sync: {
enabled: false, // enable trace line syncing with other charts
//group: 1, // chart group
suppressTooltips: false // suppress tooltips when showing a synced tracer
},
},
zoom: {
enabled: false,
},
}
};
public chartType: string = 'line';
public chartLegend: boolean = true;
public chartLabels: Label[] = ['0', '1', '2', '3', '4', '5','6','7','8','9','10','11','12','13','14','15','16','17',
'18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40',
'41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59'];
public chartPlugins = [pluginCrosshair];
public colors: any[] = [{ // grey
backgroundColor: 'rgba(148,159,177,0.2)',
borderColor: 'rgba(148,159,177,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)',
fill: false
},
{
backgroundColor: 'rgba(0,100,0,0.2)',
borderColor: 'rgba(0,0,100,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)',
fill: false
}];
constructor(public signalRService: SignalRService, private http: HttpClient) { }
ngOnInit() {
this.signalRService.startConnection();
this.signalRService.addTransferChartDataListener();
this.signalRService.addBroadcastChartDataListener();
this.startHttpRequest();
}
private startHttpRequest = () => {
this.http.get('https://localhost:5001/api/chart')
.subscribe(res => {
console.log(res);
})
}
public chartClicked = (event) => {
console.log(event);
this.signalRService.broadcastChartData();
}
}
I actually figured this out. If I replace the reference in the html to the colors array with just the information itself like this
[colors]="
[{
backgroundColor: 'rgba(0,100,0,0.2)',
borderColor: 'rgba(0,0,100,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)',
fill: false
}]"
and I also change the data1 and data2 variables to slices (using Arrays.slice) of the original super dataset, it works.

Can't reuse a template in Vue.js

Trying to reuse a custom template from my Graph.vue file, but this attempt fails(without any errors in the console). I only get one chart rendered(the red one). Any ideas how to fix this code?
My current code looks like this:
main.js
import Vue from 'vue';
import Graph from './components/Graph.vue';
new Vue({
el: 'graph',
components: { Graph }
});
Graph.vue
<template>
<canvas height="400" width="600"></canvas>
</template>
<script>
import Chart from 'chart.js';
export default {
props: ['labels', 'values', 'color'],
props: {
labels: {},
values: {},
color: {
default: 'rgba(220,220,220,0.2)'
}
},
mounted(){
var data = {
labels: this.labels,
datasets: [
{
label: "My First dataset",
fill: true,
lineTension: 0.1,
backgroundColor: this.color,
borderColor: "rgba(75,192,192,1)",
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: "rgba(75,192,192,1)",
pointBackgroundColor: "#fff",
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(75,192,192,1)",
pointHoverBorderColor: "rgba(220,220,220,1)",
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: this.values,
spanGaps: false
},
]
};
new Chart(this.$el, {type: 'line', data: data});
}
}
</script>
example.html
<div style="width:600px" class="container">
<graph :labels="['January', 'February', 'March']"
:values="[10, 42, 4]"
color="red"
></graph>
</div>
<div style="width:600px" class="container">
<graph :labels="['May', 'June', 'July']"
:values="[100, 420, 99]"
color="blue"
></graph>
</div>
<script src="{{asset('/js/main.js')}}"></script>
The intended result should be two bars - red and blue one.
I think your mountpoint is wrong. el: 'graph' behavior is probably not predictable in this context (will it target the first graph element?).
Use something like that instead:
JS:
new Vue({
el: '#graphContainer',
components: { Graph }
});
HTML:
<div id="graphContainer">
<div style="width:600px" class="container>
<graph :labels="['January', 'February', 'March']"
:values="[10, 42, 4]"
color="red"></graph>
</div>
<div style="width:600px" class="container">
<graph :labels="['May', 'June', 'July']"
:values="[100, 420, 99]"
color="blue"></graph>
</div>
</div>
I like #Cobaltway answer better, but this also solves the problem.
JS:
import Vue from 'vue';
import Graph from './components/Graph.vue';
const graphs = document.querySelectorAll('graph');
for (let i = 0; i < graphs.length; ++i) {
new Vue({
el: graphs[i],
components: { Graph }
});
}

chart js 2 how to set bar width

I'm using Chart js version: 2.1.4 and I'm not able to limit the bar width. I found two options on stackoverflow
barPercentage: 0.5
or
categorySpacing: 0
but neither of one works with the mentioned version. Is there a way to solve this issue without manually modifying the chart.js core library?
thanks
You were right : The attribute you have to edit is barPercentage.
But maybe the error comes from where you edited the value.
As you can see in the bar chart options :
Name : barPercentage
- Type : Number
- Default : 0.9
- Description : Percent (0-1) of the available width each bar should be within the category percentage. 1.0 will take the whole category width and put the bars right next to each other. Read More
The attribute is actually stored in scales.xAxes ("Options for xAxes" table).
So you just have to edit your chart this way :
var options = {
scales: {
xAxes: [{
barPercentage: 0.4
}]
}
}
Here is a fully working example with a custom width (0.2) for the bar :
var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
backgroundColor: "rgba(75,192,192,0.4)",
borderColor: "rgba(75,192,192,1)",
data: [65, 59, 75, 81, 56, 55, 40],
}]
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
// Change here
barPercentage: 0.2
}]
}
}
});
console.log(myChart);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.js"></script>
<canvas id="myChart"></canvas>
Update (Chart.js Version 2.2.0+)
As stated in the Release Version 2.2.0 - Candidate 2 :
Enhancements
Can now manually configure the thickness of a bar in a bar chart. Use a new barThickness option on the correct axis to set the thickness of a bar.
And so on ...
For version 2.8+ (and apparently as far back as 2.2), there are now some excellent controls over the bar thickness, max thickness, etc.
Per the Chart.js documentation, you would set them like so:
{
type: 'bar', // or 'horizontalBar'
data: ...,
options: {
scales: {
xAxes: [{
barThickness: 6, // number (pixels) or 'flex'
maxBarThickness: 8 // number (pixels)
}]
}
}
}
As of v2.7.2 it can be done by:
scales: {
xAxes: [{
maxBarThickness: 100,
}],
}
In case if you are using ng2-chart in an angular project then the bar chart configuration looks Alike this:
npm install ng2-charts chart.js --save
import 'ng2-charts' in your module.
import { ChartsModule } from 'ng2-charts';
Now the bar chart configurations:
barChartOptions: ChartOptions = {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
};
barChartLabels: Label[] = ['2006', '2007', '2008', '2009', '2010', '2011', '2012'];
barChartType: ChartType = 'bar';
barChartLegend = true;
barChartPlugins = [];
barChartData: ChartDataSets[] = [
{
barThickness: 16,
barPercentage: 0.5,
data: [65, 59, 80],
label: 'Growth'
},
{
barThickness: 16,
barPercentage: 0.5,
data: [28, 48, 40],
label: 'Net'
}
];
barChartColors: Color[] = [
{ backgroundColor: '#24d2b5' },
{ backgroundColor: '#20aee3' },
];
Now the HTML part:
<div class="bar-chart-wrapper">
<canvas baseChart [datasets]="barChartData" [colors]="barChartColors"
[labels]="barChartLabels"
[options]="barChartOptions" [plugins]="barChartPlugins" [legend]="barChartLegend"
[chartType]="barChartType">
</canvas>
</div>
You can control the height of your chart container
.bar-chart-wrapper {
height: 310px;
}
barThickness and maxBarThickness (previously in ChartOptions[]) are now a part of ChartDataSets[].
As per above answer
Here is complete Bar chart graph using react chartjs2.
import React from 'react';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
} from 'chart.js';
import { Bar } from 'react-chartjs-2';
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
export const options = {
responsive: true,
plugins: {
legend: {
position: 'top', // lable position left/right/top/bottom
labels: {
boxWidth: 0, // lable box size
}
},
},
elements: {
point: {
radius: 1
}
},
scales: {
x: {
display: false, // show/ hide x-axis
grid: {
display: false // show/hide grid line in x-axis
},
},
y: {
display: false, // same as x-axis
grid: {
display: false
}
}
}
};
const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
export const data = {
labels,
datasets: [
{
label: 'datasets', // label text
data: [100, 300, 500, 700],
backgroundColor: '#7b62ff', // bar / column color
barThickness: 6, // <<<<<<<<<<<< bar / column size
},
],
};
export default function ResumesGraph() {
return (
<div>
<Bar
data={data}
options={options}
width={'500px'}
height={'180px'}
/>
</div>
);
}
Try this
import {Chart} from "chart.js"
Chart.defaults.datasets.bar.maxBarThickness = 73;
//also try barPercentage
For those who are interested, i made a quick fork based on 3.9 branch to manage dynamic width :
https://github.com/stephanebouget/Chart.js/tree/3.9
For example :
Live demo
https://codepen.io/stephanebouget/pen/PoerxPP
var data = {
datasets: [{
label: 'Dataset #1',
backgroundColor: 'rgba(255,99,132,0.2)',
borderColor: 'rgba(255,99,132,1)',
borderWidth: 1,
hoverBackgroundColor: 'rgba(255,99,132,0.4)',
hoverBorderColor: 'rgba(255,99,132,1)',
data: [65, 59, 20, 81, 56, 55, 40],
setPercentage: [10, 2, 20, 40, 4, 6, 18], // Here is the magic !!!
}],
};

Categories