基于vue3 和 F2 3.5.0
<template><div :style="{minHeight: `${height}px`,width: '100%' }" ref="container"><canvas v-show="showChart" ref="canvas" :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: 'barAndLineChart'},color: {type: String,default: 'itemName'},colorArray: {type: Array,default: ['#7357F6FF', '#459EF5FF', '#78D86CFF', 'red'],//, 'l(90) 0:#BFDCFD 1:#458BFF', 'l(90) 0:#CFF4F3 1:#73E3CB'},legendPosition: {type: String,default: 'bottom'},unit: {type: String,default: ''},unit2: {type: String,default: ''},intervalPositionX: {type: String,default: 'xValue'},intervalPositionY: {type: String,default: 'yValue'},intervalPositionY2: {type: String,default: 'yValue'},mask: {type: String,default: ''},type: {type: String,default: 'type'},type2: {type: String,default: 'type2'},legendItems: {type: Array,default: []},isScrollBar: {type: Boolean,default: false},intervalSize: {type: Number,default: 8},
})const chart = ref()
const canvas = 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: ['auto', 'auto', 'auto', 'auto'],pixelRatio: window.devicePixelRatio,});
}/*** @description: 柱状图* @param {*} data 数据* @return {*}*/
const initChartTimeout = (data: any) => {if (data.length > 0) {data.sort((a: any,b: any) => {return Number(new Date(a[props.intervalPositionX])) - Number(new Date(b[props.intervalPositionX]));})data.forEach((item: any) => {if (item[props.intervalPositionY]) {item[props.intervalPositionY] = parseFloat(item[props.intervalPositionY])}})showChart.value = trueif (chart.value) {chart.value.clear(); // 清理所有}chart.value.tooltip({layout: 'vertical',offsetY: 60,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) {// console.log("onChange ~ obj:", obj)}});let ipX: any = {}if (props.isScrollBar) {const originDates = data.map((item: any) => item[props.intervalPositionX]).slice(-4);ipX[props.intervalPositionX] = {tickCount: 4,values: originDates,}ipX[props.intervalPositionY] = {tickCount: 4,// formatter: function formatter(val) {// return val + props.unit// }}chart.value.source(data, ipX);chart.value.interval().position(`${props.intervalPositionX}*${props.intervalPositionY}`)//柱.adjust({type: 'dodge', // 分组marginRatio: 0.2 // 设置分组间柱子的间距}).color(props.type, props.colorArray).size(props.intervalSize);chart.value.interaction('pan');chart.value.scrollBar({mode: "x",xStyle: {offsetY: -5}});chart.value.axis(props.intervalPositionX, {label: (label: any) => {return {text: label}}})} else {ipX[props.intervalPositionX] = {tickCount: 6,label: {textAlign: 'center',}}chart.value.source(data, ipX);chart.value.interval().position(`${props.intervalPositionX}*${props.intervalPositionY}`)//柱.adjust({type: 'dodge', // 分组marginRatio: 0.2 // 设置分组间柱子的间距}).color(props.type, props.colorArray).size(props.intervalSize);chart.value.axis(props.intervalPositionX);}chart.value.line().position(`${props.intervalPositionX}*${props.intervalPositionY2}`)//线.color(props.type2, ['#FDAD15FF', '#2AC670', '#ff7957FF'])chart.value.legend({position: 'top',// align: "left",marker: 'square',custom: props.legendItems?.length > 0 ,items: props.legendItems})chart.value.guide().text({top: true, // 是否绘制在 canvas 最上层,默认为 falseposition: ['min', 'max'], // 文本的起始位置content: props.unit,style: {// fill: '#000', // 文本颜色fontSize: '10', // 文本大小},offsetX: -15, // x 方向的偏移量offsetY: -20, // y 方向偏移量});chart.value.guide().text({top: true, // 是否绘制在 canvas 最上层,默认为 falseposition: ['max', 'max'], // 文本的起始位置content: props.unit2,style: {fontSize: '10', // 文本大小},offsetX: 15, // x 方向的偏移量offsetY: -18, // y 方向偏移量});render()} else {showChart.value = false}}const initChart = (data: any) => {setTimeout(() => {initChartTimeout(data)}, 100);
}const render = () => {chart.value.render();
}defineExpose({initChart, chart, render})</script>
引用
<InitBarAndLineChart ref="chartRef":chartId="uuidv4()"intervalPositionX="statTime"intervalPositionY="accu"intervalPositionY2="yoy"color="itemName":colorArray="['l(90) 0:#BFDCFDFF 1:#458BFFFF','l(90) 0:#CFF4F3FF 1:#73E3CBFF','l(90) 0:#846BF9FF 1:#DCD4FFFF','l(90) 0:#D6FAF8FF 1:#E7FFFEFF',]"adjustType="stack":showToolTotal="true":height="260"unit2="%"/>
数据格式
{type: `${indexName}企业产值`,type2: `${indexName}企业产值累计同比`,accu: item.outp,yoy: item.outpYoy,statTime: item.statTime},