I understand that I need to set Chart.defaults.global.animation.duration = some value. I just don't know where I place this line. I've previously declared it everywhere and it doesn't seem to change anything. I thought that I could set it globally after importing Chart.
Here's the Chart Component.
<script>
import Chart from 'chart.js'
import config from '../config.js'
Chart.defaults.global.animation.duration = 3000
export default {
name: 'Chart',
props: ["positions"],
data() {
return {
}
},
created() {
this.loadData()
this.createChart('canvas', config)
},
methods: {
loadData() {
this.positions.forEach((position) => {
config.data.labels.push(position.symbol)
config.data.datasets[0].data.push(position.closePrice)
})
},
createChart(id, data) {
const ctx = document.getElementById(id)
new Chart(ctx, {
type: data.type,
data: data.data,
options: data.options,
});
}
}
}
</script>
The chart's configuration.
const config = {
type: 'pie',
data: {
labels: [],
datasets: [
{
label: '',
data: [],
backgroundColor: [
'#48beff',
'#3dfaff',
'#43c59e',
'#3d7068',
'#14453d',
],
borderWidth: 1
}
]
},
options: {
legend: {
display: false
},
},
}
export default config
I solved this. The problem was that the closing <style/> tag in my Component was missing. The styles were applied once it was added, and setting Chart.defaults.global.animation.duration now works as expected.
Related
I am using chartjs with the vue-chartjs wrapper and trying to create a Line Chart using data fetched from my api. The data prints to the console as expected and I do not get a error in the console. The resulting Line Chart does not display at all in the browser. There is, however a large amount of white space where the canvas tag is injected. I can create a doughnut chart fine, just not this line chart. Your help is greatly appreciated! I am using code from the Chart examples found at https://vue-chartjs.org/examples/ for the LineChart component
IndexView.vue
<script setup>
import axios from 'axios'
import { onMounted, reactive } from 'vue'
import LineChart from '#/components/LineChart.vue'
const data = reactive({
user: null,
totals: null,
checkins: null
})
const state = reactive({
loading: true
})
const charts = reactive({
doughnutConfig: null,
lineConfig: null
})
onMounted(async () => {
// load data from store and api
data.user = await userStore.fetchUser()
const user_resp = await axios.get(...)
data.totals = user_resp.data.totals
data.checkins = user_resp.data.check_ins
state.loading = false
// create line chart
var dates = []
var ratings = []
var length = data.checkins.length < 10 ? data.checkins.length : 10
for (var i = 0; i < length; i++) {
dates.push(data.checkins[i].date)
ratings.push(data.checkins[i].rating)
}
console.log(dates) // [ "2022-09-04T00:00:00", "2022-09-04T00:00:00", "2022-09-04T00:00:00", "2022-09-04T00:00:00", "2022-09-05T00:00:00" ]
console.log(ratings) // [ 5, 5, 3, 2, 4 ]
charts.lineConfig = {
data: {
labels: dates,
datasets: {
label: 'Ratings by date',
data: ratings,
backgroundColor: '#f87979'
}
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
}
}
}
})
</script>
<template>
<LineChart
v-if="charts.lineConfig"
:chart-options="charts.lineConfig.options"
:chart-data="charts.lineConfig.data"
:width="400"
:height="300"
/>
</template>
LineChart.vue
<script setup>
import { defineProps } from 'vue'
import { Line } from 'vue-chartjs'
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
LineElement,
LinearScale,
PointElement,
CategoryScale
} from 'chart.js'
ChartJS.register(
Title,
Tooltip,
Legend,
LineElement,
LinearScale,
PointElement,
CategoryScale
)
const props = defineProps({
chartData: {
type: Object,
required: true
},
chartOptions: {
type: Object,
required: true
},
chartId: {
type: String,
default: 'line-chart'
},
width: {
type: Number,
required: true
},
height: {
type: Number,
required: true
}
})
</script>
<template>
<Line
:chart-id="props.chartId"
:chart-data="props.chartData"
:chart-options="props.chartOptions"
:width="props.width"
:height="props.height"
/>
</template>
Usually when a chart is not shown, there is an issue on the data configuration.
In your data config, the datasets option seems to be defined as an object but instead should be an array.
data: {
labels: dates,
datasets: { // <--- should be an array.
label: 'Ratings by date',
data: ratings,
backgroundColor: '#f87979'
}
},
It should be:
data: {
labels: dates,
datasets: [{
label: 'Ratings by date',
data: ratings,
backgroundColor: '#f87979'
}]
},
I am trying to hide the legend of my chart created with Chart.js.
According to the official documentation (https://www.chartjs.org/docs/latest/configuration/legend.html), to hide the legend, the display property of the options.display object must be set to false.
I have tried to do it in the following way:
const options = {
legend: {
display: false,
}
};
But it doesn't work, my legend is still there. I even tried this other way, but unfortunately, without success.
const options = {
legend: {
display: false,
labels: {
display: false
}
}
}
};
This is my full code.
import React, { useEffect, useState } from 'react';
import { Line } from "react-chartjs-2";
import numeral from 'numeral';
const options = {
legend: {
display: false,
},
elements: {
point: {
radius: 1,
},
},
maintainAspectRatio: false,
tooltips: {
mode: "index",
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return numeral(tooltipItem.value).format("+0,000");
},
},
},
scales: {
xAxes: [
{
type: "time",
time: {
format: "DD/MM/YY",
tooltipFormat: "ll",
},
},
],
yAxes: [
{
gridLines: {
display: false,
},
ticks: {
callback: function(value, index, values) {
return numeral(value).format("0a");
},
},
},
],
},
};
const buildChartData = (data, casesType = "cases") => {
let chartData = [];
let lastDataPoint;
for(let date in data.cases) {
if (lastDataPoint) {
let newDataPoint = {
x: date,
y: data[casesType][date] - lastDataPoint
}
chartData.push(newDataPoint);
}
lastDataPoint = data[casesType][date];
}
return chartData;
};
function LineGraph({ casesType }) {
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async() => {
await fetch("https://disease.sh/v3/covid-19/historical/all?lastdays=120")
.then ((response) => {
return response.json();
})
.then((data) => {
let chartData = buildChartData(data, casesType);
setData(chartData);
});
};
fetchData();
}, [casesType]);
return (
<div>
{data?.length > 0 && (
<Line
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data
},
],
}}
options={options}
/>
)}
</div>
);
}
export default LineGraph;
Could someone help me? Thank you in advance!
PD: Maybe is useful to try to find a solution, but I get 'undefined' in the text of my legend and when I try to change the text like this, the text legend still appearing as 'Undefindex'.
const options = {
legend: {
display: true,
text: 'Hello!'
}
};
As described in the documentation you linked the namespace where the legend is configured is: options.plugins.legend, if you put it there it will work:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
}
]
},
options: {
plugins: {
legend: {
display: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>
On another note, a big part of your options object is wrong, its in V2 syntax while you are using v3, please take a look at the migration guide
Reason why you get undefined as text in your legend is, is because you dont supply any label argument in your dataset.
in the newest versions this code works fine
const options = {
plugins: {
legend: {
display: false,
},
},
};
return <Doughnut data={data} options={options} />;
Import your options value inside the charts component like so:
const options = {
legend: {
display: false
}
};
<Line data={data} options={options} />
I'm using Vue Chart JS v3.5.1 in my Nuxt JS/Vue project, and I've noticed that when trying to use options and pass them as a prop, nothing happens, the chart defaults back to the chart's default settings despite me overwriting settings.
I've got several files:
plugins/LineChart.js
components/LineChart.vue
plugins/LineChart.js
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
computed: {
localOptions: function() {
return this.chartOptions
},
localData: function() {
console.log(`data: ${this.chartData}`)
return this.chartData
}
},
mounted () {
this.renderLineChart()
},
methods: {
/*
** Render a line chart
*/
renderLineChart () {
// this.chartdata is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.localData, this.localOptions)
}
},
watch: {
chartData: {
handler: function (val, oldVal) {
this._data._chart.destroy()
this.renderLineChart()
},
deep: true
},
chartOptions: {
handler: function (val, oldVal) {
this.localOptions = val
},
deep: true
}
}
}
components/LineChart.vue
<template>
<div>
<line-chart :chart-data="customChartData" :chart-options="customChartOptions" class="data-chart"></line-chart>
</div>
</template>
<style>
.data-chart canvas {
width: 100% !important;
height: auto !important;
}
</style>
<script>
import LineChart from '~/plugins/LineChart.js'
export default {
components: {
LineChart
},
props: {
labels: {
type: Array,
default: null
},
datasets: {
type: Array,
default: null
},
options: {
type: Object,
default: () => ({})
}
},
data () {
return {
customChartData: {},
customChartOptions: {}
}
},
mounted () {
this.fillData()
},
methods: {
fillData () {
this.customChartData = {
labels: this.labels,
datasets: this.datasets
}
this.customChartOptions = {
options: this.options
}
}
}
}
</script>
My usage, is then reasonably simple, yet I'm not getting my options to show?
<LineChart
:options="{
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display: false
},
ticks: {
autoSkip: true,
maxTicksLimit: 3,
maxRotation: 0,
minRotation: 0
}
}],
yAxes: [{
display: true,
gridLines: {
display: true,
color: '#f3f5f6'
}
}]
},
elements: {
point: {
radius: 0,
hitRadius: 35
}
}
}"
:labels="['test']"
:datasets="[{
fill: false,
borderWidth: 2.5,
pointBackgroundColor: '#fff',
borderColor: '#5046e5',
data: [500,
}]"
/>
What am I doing wrong?
UPDATE
In addition, I seem to only have the first chart out of many charts on the page show data, why would only one chart in a series of charts show data, I've got a key on each one.
in your fillData it looks like you assign the options wrong. Vue Chartjs expects an object with the options in it and not an object with an field options with the options.
If you change: this.customChartOptions = {options: this.options} to: this.customChartOptions = this.options it should work
I am creating a cryptocurrency price tracker with React. I am using axios to make API requests and get information about the price history of different cryptocurrencies. This works fine, but when I am creating the chart with ChartJS, the chart only shows one value, even though I have thousands. Anyone know how to fix this? Big thanks in advance.
Here is my code for the chart component:
import Chartjs from "chart.js";
import axios from "axios";
import { historyOptions } from "../../chartConfigs/chartConfigs";
const HistoryChart = ({ coinId }) => {
const [timeLength, setTimeLength] = useState(30);
const chartRef = useRef();
const [timeSeriesData, setTimeSeriesData] = useState([]);
useEffect(() => {
const timeSeriesDataArray = [];
axios.get(`https://api.coingecko.com/api/v3/coins/${coinId}/market_chart?vs_currency=usd&days=${30}`)
.then(response => {
response.data.prices.forEach(element => {
timeSeriesDataArray.push(
{
t: element[0],
y: element[2].toFixed(2)
}
)
})
setTimeSeriesData(timeSeriesDataArray)
})
.catch(error => console.log(error))
}, [coinId, timeLength])
useEffect(() => {
if (chartRef && chartRef.current) {
const chartInstance = new Chartjs(chartRef.current,{
type: 'line',
data: {
datasets: [{
label: "Price",
data: timeSeriesData,
backgroundColor: "rgba(174, 374, 194, 0.5)",
borderColor: "rgba(174, 374, 194, 0.4)",
pointRadius: 0,
borderWidth: 1
}]
},
options: historyOptions
})
}
}, [timeSeriesData])
return (
<div className="history-chart-container">
<canvas ref={chartRef} id="history-chart" width={1200} height={500}></canvas>
</div>
)
}
export default HistoryChart
Here is my code for the chart options (historyOptions):
lineHeighAnnotation: {
always: true,
hover: false,
lineHeight: 1.5
},
animation: {
duration: 2000
},
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: {
type: "time",
distribution: "linear",
}
}
}```
[1]: https://i.stack.imgur.com/e7g4P.png
[2]: https://i.stack.imgur.com/t4YIa.png
This could be fixed by changing your line chart into a scatter chart.
const chartInstance = new Chartjs(chartRef.current,{
type: 'scatter',
...
To still get the lines drawn between the data points, you need to define the option showLine: true on the dataset.
datasets: [{
label: "Price",
showLine: true,
...
}]
UPDATE
You should also make sure to update the chart when new data is added and the chart already exists. Not knowing much about react.js, you could make chartInstance a global variable and proceed as follows:
if (chartRef && chartRef.current) {
chartInstance = new Chartjs(chartRef.current,{
type: 'line',
...
} else {
chartInstance.update();
}
I'm using vue-chartjs for chart
This is my BarChart.js
import {Bar} from 'vue-chartjs'
export default {
extends: Bar,
data () {
return {
gradient: null,
gradient2: null,
datacollection: {
labels: ['January', 'February','March'],
datasets: [
{
label: 'Data One',
backgroundColor: this.gradient,
data: [40,42,99]
},
]}
}
},
mounted () {
this.gradient =
this.$refs.canvas.getContext('2d').createLinearGradient(0, 0, 0, 400);
this.gradient.addColorStop(0, 'rgba(250,274,50,1)');
this.gradient.addColorStop(1, 'rgba(250,174,50,0)');
console.log(this.$refs.canvas.getContext('2d'));
this.renderChart(this.datacollection, {responsive: true,
maintainAspectRatio: false})
}
}
And this is my Vue for it
<template>
<v-flex sm6>
<bar-chart></bar-chart>
</v-flex>
</template>
<script>
import BarChart from './BarChart.js';
export default {
components: {
BarChart
},
data() {
return {
datacollection: null
}
},
}
</script>
<style>
</style>
But I can't see the gradient, so I did console.log for this.$refs.canvas.getContext('2d') and it is referencing the bar-chart correctly but the fillstyle is not canvasgradient it is showing
CanvasRenderingContext2D
canvas:canvas#bar-chart
fillStyle:"#000000"
Well you can not reference data properties inside data properties in vue.js
data: () => ({
data1: '1',
data2: this.data1
})
This will not work tho.
You can put your datacollection directly inside the renderChart() method and then add the gradient. Or try to use computed properties