blob: c0f83a2366053aebc139d676619e6df88586f3a0 [file] [log] [blame]
<template>
<div>
<div slot="header" class="clearfix text-base">
{{$t('preview')}}
<a href="javascript:;" @click="run()">
<i class="el-icon-refresh"></i>
</a>
</div>
<div
id="bar-race-preview"
ref="chart"
class="absolute bottom-4 top-14 left-5 right-5 border"
:class="isHidden ? 'hidden' : ''"
>
</div>
<div id="chart-hint" v-if="isHidden">
视频生成中无法预览
</div>
</div>
</template>
<script lang="ts">
import {defineComponent} from 'vue';
import * as echarts from 'echarts';
import canvasRecord from 'canvas-record';
const colorAll = [
'#5470c6',
'#91cc75',
'#fac858',
'#ee6666',
'#73c0de',
'#3ba272',
'#fc8452',
'#9a60b4',
'#ea7ccc'
];
const headerLength = 2;
let chart: echarts.ECharts;
let time: number;
export default defineComponent({
name: 'BChart',
props: {
title: String,
chartData: Array,
maxDataCnt: Number,
animationDuration: Number
},
data() {
return {
timeoutHandlers: [],
isHidden: false
};
},
watch: {
chartData() {
this.run();
}
},
mounted() {
},
methods: {
run() {
this.doResetChart();
time = Date.now();
this.doRun();
},
clearTimeoutHandlers() {
for (let i = 0; i < this.timeoutHandlers.length; ++i) {
clearTimeout(this.timeoutHandlers[i]);
}
this.timeoutHandlers = [];
},
removeTimeoutHandlers(handler: number) {
for (let i = 0; i < this.timeoutHandlers.length; ++i) {
if (this.timeoutHandlers[i] === handler) {
this.timeoutHandlers.splice(i, 1);
}
}
},
captureVideo(width?: number, height?: number): Promise<boolean> {
return new Promise(resolve => {
try {
this.isHidden = true;
this.doResetChart(width, height);
const canvas = chart.getDom().children[0].children[0] as HTMLCanvasElement;
const recorder = canvasRecord(canvas);
time = Date.now();
recorder.start();
this.doRun(() => {
let hasError = false;
try {
recorder.stop();
}
catch (e) {
console.error(e);
hasError = true;
}
this.isHidden = false;
setTimeout(() => {
this.run();
});
resolve(hasError);
});
}
catch (e) {
console.error(e);
this.isHidden = false;
resolve(false);
}
});
},
doResetChart(width?: number, height?: number) {
this.clearTimeoutHandlers();
if (chart) {
chart.dispose();
chart = null;
}
if (!this.chartData.length) {
return;
}
chart = echarts.init(this.$refs.chart as HTMLElement, null, {
width: width || undefined,
height: height || undefined
});
const animationDuration = this.animationDuration;
const option = {
backgroundColor: '#fff',
xAxis: {
type: 'value',
max: 'dataMax'
},
yAxis: {
type: 'category',
data: (this.chartData[0] as string[]).slice(1),
inverse: true,
animationDuration: 300,
animationDurationUpdate: 300,
max: this.maxDataCnt ? this.maxDataCnt - 1 : null
},
series: [{
id: 'bar',
type: 'bar',
data: (this.chartData[headerLength] as string[]).slice(1).map(str => parseInt(str, 10)),
seriesLayoutBy: 'row',
realtimeSort: true,
label: {
show: true,
position: 'right'
},
itemStyle: {
color: (param: any) => {
return (this.chartData[1] as string[])[param.dataIndex + 1] || colorAll[param.dataIndex % colorAll.length];
}
}
}],
grid: {
right: 60,
bottom: 30
},
title: [{
text: (this.chartData as any)[headerLength][0],
right: 20,
bottom: 15,
textStyle: {
color: '#ccc',
opacity: 0.3,
fontSize: 70
}
}, {
text: this.title,
left: 10,
top: 10
}],
animationDuration: 0,
animationDurationUpdate: animationDuration,
animationEasing: 'linear',
animationEasingUpdate: 'linear'
};
chart.setOption(option as echarts.EChartsOption, true);
},
doRun(onCompleted?: Function) {
const dataCnt = this.chartData.length - headerLength - 1;
const that = this;
for (let i = 0; i < dataCnt; ++i) {
(function (i: number) {
let timeout: number;
const timeoutCb = function () {
const row = that.chartData[headerLength + i + 1] as string[];
chart.setOption({
series: [{
type: 'bar',
id: 'bar',
data: row.slice(1).map(str => parseInt(str, 10)),
label: {
valueAnimation: true
}
}],
title: [{
text: row[0]
}]
});
that.removeTimeoutHandlers(timeout);
if (i === dataCnt - 1 && typeof onCompleted === 'function') {
setTimeout(onCompleted, that.animationDuration);
}
};
timeout = window.setTimeout(timeoutCb, i * that.animationDuration);
that.timeoutHandlers.push(timeout);
})(i);
}
}
}
})
</script>
<style>
.hidden {
visibility: hidden;
}
#chart-hint {
position: absolute;
top: 55px;
left: 20px;
color: #999;
}
</style>