基于vue3 和 F2 3.5.0
<template><div :style="{minHeight: `${height}px`,width: '100%' }" ref="container"><canvas v-show="showChart" :id="chartId" class="chart-canval"></canvas><empty-box v-show="!showChart"></empty-box></div>
</template><script setup lang="ts">
import {ref, onMounted} from 'vue'
import F2 from '@antv/f2/lib/index-all.js';const props = defineProps({height: {type: Number,default: 300,required: false},chartId: {type: String,default: 'barChart'},group: {type: Boolean,default: true},color: {type: String,default: 'itemName'},colorArray: {type: Array,default: ['l(90) 0:#BFDCFDFF 1:#458BFFFF','l(90) 0:#CFF4F3FF 1:#73E3CBFF','#7357F6FF', '#459EF5FF', '#78D86CFF', '#97DFD8FF', '#F0BD58FF', '#7DBBF8FF', '#A1E498FF', '#B6E9E4FF', '#F5D18AFF', '#B5D8FBFF', '#C9EFC4FF', '#D5F2EFFF', '#F9E5BCFF'],// default: ['#459EF5FF','#97DFD8FF','#84BBF0FF','#F0BD58FF','#7357F6FF'],},legendPosition: {type: String,default: 'bottom'},unit: {type: String,default: ''},intervalPositionX: {type: String,default: 'xValue'},intervalPositionY: {type: String,default: 'yValue'},isScrollBar: {type: Boolean,default: false},adjustType: {type: String,default: 'dodge'},intervalSize: {type: Number,default: 15},transposed: {type: Boolean,default: false},isShowText: {type: Boolean,default: false},showToolTotal: {type: Boolean,default: false}
})const chart = ref()
const container = ref()
const showChart = ref(true)onMounted(() => {setTimeout(() => {newChartBox()}, 100);
})
const newChartBox = () => {const clientWidth = document.documentElement.clientWidthconst domWidth = container.value.clientWidthchart.value = new F2.Chart({id: props.chartId,width: domWidth || clientWidth,height: props.height,// padding: [10, 20, 20, 10],appendPadding: [10, 25, 10, 10],pixelRatio: window.devicePixelRatio,});
}/*** @description: 柱状图* @param {*} data 数据* @return {*}*/
const initChartTimeout = (data: any) => {if (data.length > 0) {showChart.value = truelet ipX: any = {}// let nameList: any = {}if (chart.value) {chart.value.clear(); // 清理所有}chart.value.tooltip(false);chart.value.legend({position: props.legendPosition,align: 'center',})if (props.isScrollBar) {const originDates = data.map((item: any) => item[props.intervalPositionX]).slice(0, 4);ipX[props.intervalPositionX] = {tickCount: 4,values: originDates,}ipX[props.intervalPositionY] = {tickCount: 4}chart.value.source(data, ipX);chart.value.interval().position(`${props.intervalPositionX}*${props.intervalPositionY}`).color(props.colorArray)//分组时改变color属性.size(props.intervalSize); // 柱状宽度chart.value.interaction('pan');chart.value.scrollBar({mode: "x",xStyle: {offsetY: -5}});chart.value.axis(props.intervalPositionX, {//y轴配置label: (label: any) => {return {text: label}}})} else {ipX[props.intervalPositionX] = {tickCount: 5,}let colorItem: anyif ( props.group ) {colorItem = [props.color,props.colorArray]} else {colorItem = [props.colorArray]}chart.value.source(data,ipX);chart.value.interval().position(`${props.intervalPositionX}*${props.intervalPositionY}`).color(...colorItem)//分组时改变color属性.adjust({type: props.adjustType, // 分组 stack 堆叠marginRatio: 0.5 // 设置分组间柱子的间距}).size(props.intervalSize); // 柱状宽度}if ( props.isShowText) {data.forEach((obj: any) => {chart.value.guide().text({position: [obj[props.intervalPositionX], obj[props.intervalPositionY]],content: obj[props.intervalPositionY],style: {textAlign: 'center',fontSize: '10',},offsetY: -10,limitInPlot: true,});});}if (props.transposed) {chart.value.coord({transposed: true});chart.value.guide().text({top: true, // 是否绘制在 canvas 最上层,默认为 falseposition: [0, 0], // ['min', 'max']、文本的起始位置,值为原始数据值,支持 callbackcontent: props.unit || '',style: {// fill: '#000', // 文本颜色fontSize: '8', // 文本大小},offsetX: -25, // x 方向的偏移量 -15offsetY: 26, // y 方向偏移量 -20});} else {chart.value.guide().text({top: true, // 是否绘制在 canvas 最上层,默认为 falseposition: ['min', 'max'], // 文本的起始位置,值为原始数据值,支持 callbackcontent: props.unit || '',style: {// fill: '#000', // 文本颜色fontSize: '10', // 文本大小},offsetX: -15, // x 方向的偏移量 -15offsetY: -10, // y 方向偏移量 -20});}chart.value.tooltip({layout: 'vertical',offsetY: props.transposed ? 0 : 110,background: {radius: 6,fill: '#1890FF',},nameStyle: {fontSize: 10,},valueStyle: {fontSize: 10,},onShow: function onShow(ev: any) {const items = ev.items;items.unshift({name: items[0].title,x: items[0].x,y: items[0].y,})},// onChange(obj: any) {// obj.items// if ( props.showToolTotal ) {// obj.items.unshift({// name: '',// value: '222'// });// } else {// obj.items// }// }})render()} else {showChart.value = false}}const initChart = (data: any) => {setTimeout(() => {initChartTimeout(data)}, 100);
}const render = () => {chart.value.render();
}defineExpose({initChart, chart, render})</script>
引用
滚动
<InitBarChart ref="financingWayChart" chartId="financingWayChart" intervalPositionX="name"intervalPositionY="value" :colorArray="['#459EF5FF']" :group="false" :height="260" unit="万元" :isShowText="true":isScrollBar="true" />
const queryChart = (originalData: any) => {let chartData: any = []originalData.forEach((item: any) => {chartData.push({value: Number(item.indexValue),name: item.itemName,const: 'const',})})debtChart.value.initChart(chartData, labelNumber.value)
}
对比
<InitBarChart ref="otherChart" chartId="otherChart"intervalPositionX="sdate"intervalPositionY="payAmt"unit="分"color="itemName":colorArray="['l(90) 0:#BFDCFDFF 1:#458BFFFF','l(90) 0:#CFF4F3FF 1:#73E3CBFF']":intervalSize="8":height="260"/>
堆叠对比
<InitBarChartref="jdzfChart" chartId="jdzfChart"intervalPositionX="payType"intervalPositionY="payAmt":height="150"unit="单位:万元"legendPosition="top"color="itemName"adjustType="stack":transposed="true":colorArray="['#7357F6FF', '#459EF5FF', '#78D86CFF', '#97DFD8FF', '#F0BD58FF',]"/>
if (res.data) {res.data.forEach((item: any) => {chartData.push({itemName: item.itemName.includes('完成投资') ? item.date : '计划支付',payAmt: item.payAmt,payType: item.itemName.includes('完成投资') ? '实际支付' : '计划支付',、})})}