一、条纹:美化柱状图的绝佳方式
在Vue柱状图的设计中,条纹(stripes)是一种美化效果的绝佳方式。可以通过设置CSS样式,在柱状图上添加竖条纹或水平条纹。竖条纹(vertical)可以通过background-image和linear-gradient实现,水平条纹(horizontal)可以通过background-image和repeating-linear-gradient实现。
<template>
<div class="chart-container">
<canvas id="bar-chart"></canvas>
</div>
</template>
<style>
.chart-container {
position: relative;
margin-top: 30px;
height: 300px;
width: 100%;
background: #F7F7F7;
border-radius: 5px;
}
#bar-chart {
background-size: 30px 100%;
background-repeat: repeat-x;
background-image: linear-gradient(to right, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 0%);
box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.1);
}
</style>
二、怎么写:从数据到真正实现柱状图
Vue柱状图的实现需要先准备好数据,在数据中为每一个条形提供一个值。之后,需要定义一些变量和参数来配置柱状图的样式,在mounted()生命周期方法中创建新的Chart对象并传递数据和选项。数据配置完成后,需要按照canvas元素的高度和宽度计算每个柱形的宽度。
<template>
<div class="chart-container">
<canvas id="bar-chart"></canvas>
</div>
</template>
<script>
import Chart from 'chart.js';
export default {
data () {
return {
datacollection: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August'],
datasets: [
{
label: 'Data One',
backgroundColor: ['#F26202', '#F7981C', '#FFE32C', '#60B8E8', '#02A4D3', '#0D3C55', '#021E34', '#19D3DA'],
data: [40, 20, 12, 39, 10, 20, 30, 29],
borderWidth: 1
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
},
files: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August'],
labels: ['Data One']
}
},
mounted () {
this.renderChart()
},
methods: {
renderChart () {
const ctx = document.getElementById('bar-chart').getContext('2d')
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
gradientStroke.addColorStop(1, 'rgba(29,140,248,0.2)');
gradientStroke.addColorStop(0.4, 'rgba(29,140,248,0.0)');
gradientStroke.addColorStop(0, 'rgba(29,140,248,0)');
let myChart = new Chart(ctx, {
type: 'bar',
data: this.datacollection,
options: this.options
})
let dataset = myChart.data.datasets[0];
let bars = [];
let width = (myChart.chart.width * 0.9) / dataset.data.length;
for (let i = 0; i < dataset.data.length; i++) {
let x = myChart.chart.width * 0.05 + width * i;
let y = myChart.chart.height - (myChart.chart.height * dataset.data[i] / 100);
bars.push(new this.Bar(x, y, width, myChart.chart.height * dataset.data[i] / 100, dataset.backgroundColor[i]));
}
this.draw(bars, ctx);
},
Bar (x, y, w, h, c) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.c = c;
},
draw (bars, ctx) {
ctx.save();
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
bars.forEach(function (bar) {
ctx.fillStyle = bar.c;
ctx.fillRect(bar.x, bar.y, bar.w, bar.h);
});
ctx.restore();
}
}
}
</script>
三、组件:在Vue项目中引入柱状图组件
为了提高可重用性并且使柱状图更加易用,可以将其封装成Vue组件。在组件中,可以传入data属性作为柱状图的数据源,以及其他一些自定义选项来自定义柱状图。另外,也可以定义一些生命周期方法来完善组件的功能。
<template>
<div>
<canvas ref="chart"></canvas>
</div>
</template>
<script>
import Chart from 'chart.js';
export default {
props: {
data: {
type: Object,
default: null
},
options: {
type: Object,
default: null
},
type: {
type: String,
default: 'bar'
},
height: {
type: Number,
default: 400
},
width: {
type: Number,
default: 600
}
},
mounted () {
this.renderChart()
},
methods: {
renderChart () {
let ctx = this.$refs.chart.getContext('2d')
this.chart = new Chart(ctx, {
type: this.type,
data: this.data,
options: this.options
})
},
updateChart () {
this.chart.data = this.data
this.chart.update()
}
},
watch: {
data () {
this.updateChart()
}
}
}
</script>
四、点击显示明细选取:实现交互性Vue柱状图
在Vue柱状图的实际应用中,为了增加交互性和可操作性,很多时候需要点击某个柱状图来显示更多详细信息。这个功能可以通过Vue的事件监听器来实现。在监听到click事件后,调用自定义方法来显示具体的信息,例如本例中的showDetails()方法。
<template>
<div class="chart-container">
<canvas id="bar-chart" @click="showDetails"></canvas>
</div>
</template>
<script>
import Chart from 'chart.js';
export default {
data () {
return {
datacollection: {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August'],
datasets: [
{
label: 'Data One',
backgroundColor: ['#F26202', '#F7981C', '#FFE32C', '#60B8E8', '#02A4D3', '#0D3C55', '#021E34', '#19D3DA'],
data: [40, 20, 12, 39, 10, 20, 30, 29],
borderWidth: 1
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
},
files: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August'],
labels: ['Data One']
}
},
mounted () {
this.renderChart()
},
methods: {
renderChart () {
const ctx = document.getElementById('bar-chart').getContext('2d')
let gradientStroke = ctx.createLinearGradient(0, 230, 0, 50);
gradientStroke.addColorStop(1, 'rgba(29,140,248,0.2)');
gradientStroke.addColorStop(0.4, 'rgba(29,140,248,0.0)');
gradientStroke.addColorStop(0, 'rgba(29,140,248,0)');
let myChart = new Chart(ctx, {
type: 'bar',
data: this.datacollection,
options: this.options
})
let dataset = myChart.data.datasets[0];
let bars = [];
let width = (myChart.chart.width * 0.9) / dataset.data.length;
for (let i = 0; i < dataset.data.length; i++) {
let x = myChart.chart.width * 0.05 + width * i;
let y = myChart.chart.height - (myChart.chart.height * dataset.data[i] / 100);
bars.push(new this.Bar(x, y, width, myChart.chart.height * dataset.data[i] / 100, dataset.backgroundColor[i]));
}
this.draw(bars, ctx);
},
Bar (x, y, w, h, c) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.c = c;
},
draw (bars, ctx) {
ctx.save();
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
bars.forEach(function (bar) {
ctx.fillStyle = bar.c;
ctx.fillRect(bar.x, bar.y, bar.w, bar.h);
});
ctx.restore();
},
showDetails () {
// 这里可以实现点击某个柱状图,展示更多详情
alert('Show details')
}
}
}
</script>