您的位置:

Vue柱状图的详细阐述

一、条纹:美化柱状图的绝佳方式

在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>