Commit 841aaffb authored by hucy's avatar hucy

feat:动态配置的echar图表轮播图

parent 96ed2a72
......@@ -2,10 +2,17 @@
* 轮播图
-->
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import {
ref,
reactive,
onMounted,
onBeforeUnmount,
watch,
nextTick,
markRaw,
} from 'vue';
import { isEmpty } from 'src/common/utils';
// import * as echarts from 'echarts';
// type EChartsOption = echarts.EChartsOption;
import * as echarts from 'echarts';
interface Props {
itemKey: string;
......@@ -21,10 +28,18 @@ const props = withDefaults(defineProps<Props>(), {
navigation: false,
});
const DOM_PIE_KEY = 'chart-pie-dom-';
const pointActive = ref<any>(1);
const lastIndex = ref(0);
const timer = ref<any>(null);
const state = reactive({
// vue3中使用proxy的方式监听响应式,chart会被在vue内部转换成响应式对象,从而在resize 的时候获取不到
// markRaw 标记一个对象,使其永远不会再成为响应式对象
domMap: markRaw(new Map()),
});
watch(
() => props.list,
() => {
......@@ -42,17 +57,88 @@ onBeforeUnmount(() => {
// list改变
function listChange() {
console.log('listChange', props.list);
// console.log('listChange=', props.list);
offTimer(); // 清除定时器
if (isEmpty(props.list)) {
resetIndex();
state.domMap.clear();
} else {
// 如果当前下标 > list长度,则下标重新开始
if (pointActive.value > props.list.length) {
resetIndex();
}
nextTick(() => {
const domMap = new Map();
props.list.map((item: any) => {
const id = `${DOM_PIE_KEY}${item[props.itemKey]}`;
const hasDom = state.domMap.has(id);
const dom: any = hasDom
? state.domMap.get(id).dom
: document.getElementById(id);
const option = item.option || null;
let myChart: any;
const condition = pointActive.value === item[props.itemKey];
if (hasDom) {
if (state.domMap.get(id).myChart) {
myChart = state.domMap.get(id).myChart;
} else {
if (condition) {
myChart = echarts.init(dom);
} else {
myChart = null;
}
}
} else {
if (condition) {
myChart = echarts.init(dom);
} else {
myChart = null;
}
}
if (condition && option) {
// console.log('设置了', myChart);
myChart.resize();
myChart.clear();
myChart.setOption(option);
}
const val = {
dom,
option,
id,
myChart,
};
if (state.domMap) domMap.set(id, val);
return val;
});
if (state.domMap.size < domMap.size) {
for (const [key, value] of domMap) {
if (state.domMap.has(key)) {
state.domMap.set(key, domMap.get(key));
} else {
state.domMap.set(key, value);
}
}
} else if (state.domMap.size > domMap.size) {
for (const key of state.domMap.keys()) {
if (domMap.has(key)) {
state.domMap.set(key, domMap.get(key));
} else {
state.domMap.delete(key);
}
}
} else {
for (const key of domMap.keys()) {
state.domMap.set(key, domMap.get(key));
}
}
// console.log('state.domMap =', state.domMap);
onStartTimer();
});
}
}
......@@ -66,22 +152,57 @@ function onStartTimer() {
pointActive.value++;
lastIndex.value++;
}
nextTick(() => {
renderChart();
onStartTimer();
});
}, props.times);
}
function onClickPoint(val: any, index: number) {
if (index === lastIndex.value) return;
offTimer();
if (index > lastIndex.value) {
// 右
} else if (index < lastIndex.value) {
// 左
} else {
return;
}
pointActive.value = val[props.itemKey];
lastIndex.value = index;
nextTick(() => {
renderChart();
onStartTimer();
});
}
function renderChart() {
const key = `${DOM_PIE_KEY}${pointActive.value}`;
const currentDom = state.domMap.get(key);
// console.log('currentDom =', currentDom);
if (currentDom.myChart) {
if (currentDom.option) {
currentDom.myChart.clear();
currentDom.myChart.setOption(currentDom.option);
}
} else {
const myChart = echarts.init(currentDom.dom);
if (currentDom.option) {
myChart.clear();
myChart.setOption(currentDom.option);
}
const val = {
dom: currentDom.dom,
option: currentDom.option,
id: currentDom.id,
myChart,
};
state.domMap.set(key, val);
}
// console.log('domMap =', state.domMap);
// console.log('pointActive =', pointActive.value);
}
function offTimer() {
......@@ -109,9 +230,10 @@ function resetIndex() {
>
<!-- some item -->
<div class="my-item-box center">
<div class="fit" :id="`chart-pie-dom-${i[props.itemKey]}`">
{{ i.label }}
</div>
<div
class="fit"
:id="`${DOM_PIE_KEY}${i[props.itemKey]}`"
></div>
</div>
</div>
</template>
......@@ -170,7 +292,7 @@ function resetIndex() {
height: 100%;
overflow: auto;
position: absolute;
background-color: white;
background-color: #fff;
top: 0;
left: 0;
}
......
const COLORLIST = [
'#C0232C',
'#B6C335',
'#FBCE0F',
'#E87C24',
'#28727B',
'#FF8463',
'#9BCA62',
'#FAD75F',
'#F3A43B',
'#62BFE0',
'#D7504C',
];
// 图表轮播图测试数据
export const WarpTestData = [
{
......@@ -5,10 +18,9 @@ export const WarpTestData = [
label: '1号',
url: require('./element/imgs/carousel-1.jpg'),
option: {
color: COLORLIST,
title: {
text: 'Referer of a Website',
subtext: 'Fake Data',
left: 'center',
text: '1号',
},
tooltip: {
trigger: 'item',
......@@ -16,26 +28,18 @@ export const WarpTestData = [
legend: {
orient: 'vertical',
left: 'left',
top: 'bottom',
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' },
{ value: 580, name: 'Email' },
{ value: 484, name: 'Union Ads' },
{ value: 300, name: 'Video Ads' },
{ value: 1048, name: '苹果' },
{ value: 735, name: '香蕉' },
{ value: 580, name: '葡萄' },
{ value: 484, name: '' },
{ value: 300, name: '荔枝' },
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
],
},
......@@ -44,31 +48,136 @@ export const WarpTestData = [
id: 2,
label: '2号',
url: require('./element/imgs/carousel-2.jpg'),
option: null,
option: {
color: COLORLIST,
title: {
text: '2号',
},
tooltip: {
trigger: 'axis',
},
legend: {
data: ['苹果', '香蕉', '葡萄', '梨', '荔枝'],
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
name: '苹果',
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210],
},
{
name: '香蕉',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310],
},
{
name: '葡萄',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410],
},
{
name: '梨',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320],
},
{
name: '荔枝',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320],
},
],
},
},
{
id: 3,
label: '3号',
url: require('./element/imgs/carousel-3.jpg'),
option: null,
option: {
color: COLORLIST,
title: {
text: '3号',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend: {},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: {
type: 'category',
data: ['Brazil', 'Indonesia', 'USA', 'India', 'China', 'World'],
},
yAxis: {
type: 'value',
},
series: [
{
name: '2011',
type: 'bar',
data: [18203, 23489, 29034, 104970, 131744, 630230],
},
{
name: '2012',
type: 'bar',
data: [19325, 23438, 31000, 121594, 134141, 681807],
},
],
},
},
{
id: 4,
label: '4号',
url: require('./element/imgs/carousel-4.jpg'),
option: null,
option: {
color: COLORLIST,
title: {
text: '4号',
},
{
id: 5,
label: '5号',
url: require('./element/imgs/carousel-5.jpg'),
option: null,
tooltip: {
trigger: 'item',
},
series: [
{
id: 6,
label: '6号',
url: require('./element/imgs/carousel-2.jpg'),
option: null,
type: 'pie',
radius: [20, 120],
center: ['50%', '50%'],
roseType: 'area',
itemStyle: {
borderRadius: 8,
},
data: [
{ value: 40, name: 'rose 1' },
{ value: 38, name: 'rose 2' },
{ value: 32, name: 'rose 3' },
{ value: 30, name: 'rose 4' },
{ value: 28, name: 'rose 5' },
{ value: 26, name: 'rose 6' },
{ value: 22, name: 'rose 7' },
{ value: 18, name: 'rose 8' },
],
},
],
},
},
];
......@@ -76,13 +185,12 @@ export const WarpTestData = [
export const WarpTestData2 = [
{
id: 1,
label: '1号-变了1',
label: '1号',
url: require('./element/imgs/carousel-1.jpg'),
option: {
color: COLORLIST,
title: {
text: '图表轮播图测试数据2',
subtext: '666',
left: 'center',
text: '1号-测试数据2',
},
tooltip: {
trigger: 'item',
......@@ -90,58 +198,232 @@ export const WarpTestData2 = [
legend: {
orient: 'vertical',
left: 'left',
top: 'bottom',
},
series: [
{
name: 'Access From',
type: 'pie',
radius: '50%',
data: [
{ value: 1000, name: 'Search Engine' },
{ value: 1000, name: 'Direct' },
{ value: 1000, name: 'Email' },
{ value: 1000, name: 'Union Ads' },
{ value: 1000, name: 'Video Ads' },
{ value: 1048, name: '苹果' },
{ value: 735, name: '香蕉' },
{ value: 580, name: '葡萄' },
{ value: 484, name: '梨' },
{ value: 300, name: '荔枝' },
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
},
],
},
},
{
id: 2,
label: '2号-变了1',
label: '2号',
url: require('./element/imgs/carousel-2.jpg'),
option: null,
option: {
color: COLORLIST,
title: {
text: '2号-测试数据2',
},
tooltip: {
trigger: 'axis',
},
legend: {
data: ['苹果', '香蕉', '葡萄', '梨', '荔枝'],
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
name: '苹果',
type: 'line',
stack: 'Total',
data: [990, 1000, 1200, 800, 90, 230, 210],
},
{
name: '香蕉',
type: 'line',
stack: 'Total',
data: [500, 200, 100, 700, 290, 330, 310],
},
{
name: '葡萄',
type: 'line',
stack: 'Total',
data: [400, 300, 90, 750, 190, 330, 410],
},
{
name: '梨',
type: 'line',
stack: 'Total',
data: [450, 220, 88, 680, 390, 330, 320],
},
{
name: '荔枝',
type: 'line',
stack: 'Total',
data: [550, 250, 120, 600, 1290, 1330, 1320],
},
],
},
},
{
id: 3,
label: '3号-变了1',
label: '3号-测试数据2',
url: require('./element/imgs/carousel-3.jpg'),
option: null,
option: {
color: COLORLIST,
title: {
text: '3号-测试数据2',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend: {},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: {
type: 'category',
data: ['一月', '二月', '三月', '四月', '五月', '六月'],
},
yAxis: {
type: 'value',
},
series: [
{
name: '降水',
type: 'bar',
data: [6000, 7000, 6500, 5800, 7000, 10000],
},
{
name: '光照',
type: 'bar',
data: [10000, 9000, 8000, 7000, 10000, 12000],
},
],
},
},
{
id: 4,
label: '4号-变了1',
label: '4号',
url: require('./element/imgs/carousel-4.jpg'),
option: {
color: COLORLIST,
title: {
text: '4号-测试数据2',
},
tooltip: {
trigger: 'item',
},
series: [
{
type: 'pie',
radius: [20, 120],
center: ['50%', '50%'],
roseType: 'area',
itemStyle: {
borderRadius: 8,
},
data: [
{ value: 50, name: '周一' },
{ value: 60, name: '周二' },
{ value: 65, name: '周三' },
{ value: 75, name: '周四' },
{ value: 100, name: '周五' },
{ value: 120, name: '周六' },
{ value: 80, name: '周日' },
],
},
],
},
},
{
id: 5,
label: '5号',
url: require('./element/imgs/carousel-4.jpg'),
option: null,
},
// {
// id: 5,
// label: '5号-变了1',
// url: require('./element/imgs/carousel-5.jpg'),
// option: null,
// },
// {
// id: 6,
// label: '6号-变了1',
// url: require('./element/imgs/carousel-2.jpg'),
// option: null,
// },
option: {
color: COLORLIST,
title: {
text: '5号-测试数据2',
},
xAxis: {},
yAxis: {},
series: [
{
symbolSize: 20,
data: [
[10.0, 8.04],
[8.07, 6.95],
[13.0, 7.58],
[9.05, 8.81],
[11.0, 8.33],
[14.0, 7.66],
[13.4, 6.81],
[10.0, 6.33],
[14.0, 8.96],
[12.5, 6.82],
[9.15, 7.2],
[11.5, 7.2],
[3.03, 4.23],
[12.2, 7.83],
[2.02, 4.47],
[1.05, 3.33],
[4.05, 4.96],
[6.03, 7.24],
[12.0, 6.26],
[12.0, 8.84],
[7.08, 5.82],
[5.02, 5.68],
],
type: 'scatter',
},
],
},
},
];
// 图表轮播图测试数据3
export const WarpTestData3 = [
{
id: 1,
label: '1号',
url: require('./element/imgs/carousel-1.jpg'),
option: {
color: COLORLIST,
title: {
text: '1号-测试数据3',
},
tooltip: {
trigger: 'item',
},
legend: {
orient: 'vertical',
left: 'left',
top: 'bottom',
},
series: [
{
type: 'pie',
data: [
{ value: 100, name: 'A' },
{ value: 200, name: 'B' },
{ value: 300, name: 'C' },
{ value: 400, name: 'D' },
{ value: 500, name: 'E' },
],
},
],
},
},
];
......@@ -4,17 +4,18 @@
<script setup lang="ts">
import { reactive, onMounted, onBeforeUnmount } from 'vue';
import Com from 'src/components';
import { WarpTestData, WarpTestData2 } from '../config';
import { WarpTestData, WarpTestData2, WarpTestData3 } from '../config';
import * as echarts from 'echarts';
const state = reactive({
list: [] as any,
times: 5000,
testChart: null as any,
});
onMounted(() => {
setTimeout(() => {
test111();
initData();
}, 3000);
});
onBeforeUnmount(() => {
......@@ -25,16 +26,72 @@ function initData() {
state.list = WarpTestData;
}
function onDataChange1() {
state.list = WarpTestData;
}
function onDataChange2() {
state.list = WarpTestData2;
}
function onDataChange3() {
state.list = WarpTestData3;
}
function onSetToEnpty() {
state.list = [];
}
function onChangeTimers() {
state.times = 1000;
state.times = 2000;
}
function test111() {
let chartDom: any = document.getElementById('test111');
state.testChart = echarts.init(chartDom);
const option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line',
},
],
};
state.testChart.setOption(option);
}
function onDestructionChart() {
state.testChart.dispose();
}
function onResetChart() {
test111();
}
function onResetData() {
const option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [300, 300, 300, 300, 300, 300, 300],
type: 'line',
},
],
};
state.testChart.setOption(option);
}
function onView() {
console.log('查看 =', state.testChart);
}
</script>
<template>
......@@ -49,18 +106,39 @@ function onChangeTimers() {
</Com.CarouselWarp>
</div>
<div class="btns">
<q-btn
label="图表轮播图测试数据1"
@click="onDataChange1"
color="primary"
/>
<q-btn
label="图表轮播图测试数据2"
@click="onDataChange2"
color="primary"
/>
<q-btn
label="图表轮播图测试数据3"
@click="onDataChange3"
color="primary"
/>
<q-btn label="将数据置为空" @click="onSetToEnpty" color="primary" />
<q-btn label="改变轮播时间" @click="onChangeTimers" color="orange" />
</div>
<q-btn label="销毁图表" @click="onDestructionChart" color="orange" />
<q-btn label="重绘图表" @click="onResetChart" color="orange" />
<q-btn label="重新设置数据" @click="onResetData" color="orange" />
<q-btn label="查看" @click="onView" color="orange" />
<div class="test111" id="test111"></div>
</div>
</template>
<style lang="scss" scoped>
.test111 {
width: 500px;
height: 500px;
border: 1px solid red;
}
.my-warp-box {
width: 500px;
height: 300px;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment