I would like to render a chart width a 100%
width, but a fixed height (e.g. 500px
). I would also like the chart to resize according to those constraints (without maintaining aspect ratio).
Currently, I'm having trouble working with the responsive
/maintainAspectRatio
options. Regardless of my styling & options, the height seems to grow beyond it's containing elements (I believe it's using a 1:1
aspect ratio).
I can easily get something working when I feed the chart numeric width/height as a landscape ratio w:h
(e.g. <line-chart :chart-data="chartData" :width="5" :height="1" />
). Since the prop validation expects a number, I'm wondering if my desired behavior is possible with the current api.
2.4.2
2.8.2
5.3.0
With responsive: true
the canvas will ignore the width and height parameters and grow always 100% of the outer container.
With the @2.8
release you can pass two additional props.
One is the css-classes
for the outer div and the other is a styles
object which gets applied as inline styles to the outer div.
https://github.com/apertureless/vue-chartjs/releases/tag/v2.8.0
So I would not go over the width
and height
props, because they are applied directly to the cnavas. You can try to either pass a style object with
{
height: '500px',
width: '100%',
position: 'relative'
}
Or you can make a css class with that properties and pass it.
Using the styles as follow
<sale-chart :styles="{height: '250px', position: 'relative'}"></sale-chart>
the chart does not respect the given size of 250px
Do you have maintainAspectRatio
set to true or false?
Can you maybe post a minimal codepen for reproduction?
Here's a fiddle: https://jsfiddle.net/alexsasharegan/v6dj7qr3/
It appears to be working in here. I'll double back on my setup and see what I spot that's off.
The difference I can see is that somehow the height setting is not propagating down to the canvas styles. I have everything set up as identically as possible. I'm reinstalling the lib and inspecting my webpack config for any possible hangups.
Interesting... in your Line Chart render function, I don't see the code that would propagate the style object down on the canvas like I'm seeing in the fiddle repro:
export default Vue.extend({
render: function (createElement) {
return createElement(
'div', {
style: this.styles,
class: this.cssClasses
},
[
createElement(
'canvas', {
attrs: {
id: this.chartId,
width: this.width,
height: this.height
},
// Wouldn't there be a copy of the style obj here?
ref: 'canvas'
}
)
]
)
},
}
Any idea how the fiddle has the identical style settings as the wrapper?
Switching my component definition to the following solved my problem. This makes me think that somewhere in the chain, my maintainAspectRatio
setting was getting merged with the default true
in a way that merged the truthy value. Maybe, maybe not. But this works nicely now, so feel free to close this or keep it open for @wannymiarelli .
<script>
import { Line, mixins } from "vue-chartjs"
import { plainObj } from "@/core/object"
export default Line.extend({
mixins: [mixins.reactiveProp],
props: {
options: {
type: Object,
default: plainObj
}
},
mounted() {
this.renderChart(this.chartData, this.options)
},
data() {
return {
defaultOptions: {
responsive: true, // my new default options
maintainAspectRatio: false, // my new default options
scales: {
yAxes: [{
ticks: {
beginAtZero: true
},
gridLines: {
display: true // my new default options
}
}],
xAxes: [{
gridLines: {
display: false
}
}]
}
},
plugins: []
}
},
})
</script>
Perhaps having : maintainAspectRatio: true
as default would be a good way to go.
@DespertaWeb
As this issue is quite old (nearly 2 years), there are no default options anymore.
With vue-chartjs
v3 all stylings and options made by me were removed. The reason is that you now have a clean chart component, as you would use chart.js directly.
The height rerenders with promises.
<script>
import { Bar, mixins } from 'vue-chartjs';
const { reactiveProp } = mixins;
export default {
extends: Bar,
mixins: [reactiveProp],
props: ['chartOptions'],
mounted() {
this.renderChart(this.chartData, this.chartOptions);
},
watch: {
chartData() {
this.renderChart(this.chartData, this.chartOptions);
},
},
};
</script>
The watcher rerenders the chart with changes in the chartData. Use together with dynamic styles ->
<template>
<div style="height:300px;">
<bar-chart :styles="myStyles" :chart-data="dataCollection"
:chart-options="chartOptions"></bar-chart>
</div>
</template>
<script>
import BarChart from './ChartBar.vue';
export default {
components: {
BarChart,
},
props: ['dataCollection'],
data() {
return {
myStyles: {
height: '300px',
width: '100%',
position: 'relative',
},
chartOptions: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
},
gridLines: {
display: true,
},
}],
xAxes: [{
ticks: {
beginAtZero: true,
},
gridLines: {
display: false,
},
}],
},
legend: {
display: true,
},
tooltips: {
enabled: true,
mode: 'single',
callbacks: {
label(tooltipItems, data) {
const { datasetIndex, index } = tooltipItems;
const value = data.datasets[datasetIndex].data[index];
if (parseInt(value, 10) > 999) {
return `\u20AC ${value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`;
}
return `\u20AC ${value}`;
},
},
},
responsive: true,
maintainAspectRatio: false,
height: 300,
},
};
},
};
</script>
<style lang="scss" scoped>
</style>
I had the same problem and fixed it by adding the renderChart call in a chartData watcher... However, isn't it kinda weird having to use this solution while using the reactiveProp mixin? Shouldn't the mixin already do all the work by itself?
Most helpful comment
Fixed
Switching my component definition to the following solved my problem. This makes me think that somewhere in the chain, my
maintainAspectRatio
setting was getting merged with the defaulttrue
in a way that merged the truthy value. Maybe, maybe not. But this works nicely now, so feel free to close this or keep it open for @wannymiarelli .