Commit 841aaffb authored by hucy's avatar hucy

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

parent 96ed2a72
...@@ -2,10 +2,17 @@ ...@@ -2,10 +2,17 @@
* 轮播图 * 轮播图
--> -->
<script setup lang="ts"> <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 { isEmpty } from 'src/common/utils';
// import * as echarts from 'echarts'; import * as echarts from 'echarts';
// type EChartsOption = echarts.EChartsOption;
interface Props { interface Props {
itemKey: string; itemKey: string;
...@@ -21,10 +28,18 @@ const props = withDefaults(defineProps<Props>(), { ...@@ -21,10 +28,18 @@ const props = withDefaults(defineProps<Props>(), {
navigation: false, navigation: false,
}); });
const DOM_PIE_KEY = 'chart-pie-dom-';
const pointActive = ref<any>(1); const pointActive = ref<any>(1);
const lastIndex = ref(0); const lastIndex = ref(0);
const timer = ref<any>(null); const timer = ref<any>(null);
const state = reactive({
// vue3中使用proxy的方式监听响应式,chart会被在vue内部转换成响应式对象,从而在resize 的时候获取不到
// markRaw 标记一个对象,使其永远不会再成为响应式对象
domMap: markRaw(new Map()),
});
watch( watch(
() => props.list, () => props.list,
() => { () => {
...@@ -42,17 +57,88 @@ onBeforeUnmount(() => { ...@@ -42,17 +57,88 @@ onBeforeUnmount(() => {
// list改变 // list改变
function listChange() { function listChange() {
console.log('listChange', props.list); // console.log('listChange=', props.list);
offTimer(); // 清除定时器 offTimer(); // 清除定时器
if (isEmpty(props.list)) { if (isEmpty(props.list)) {
resetIndex(); resetIndex();
state.domMap.clear();
} else { } else {
// 如果当前下标 > list长度,则下标重新开始 // 如果当前下标 > list长度,则下标重新开始
if (pointActive.value > props.list.length) { if (pointActive.value > props.list.length) {
resetIndex(); resetIndex();
} }
onStartTimer(); 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() { ...@@ -66,22 +152,57 @@ function onStartTimer() {
pointActive.value++; pointActive.value++;
lastIndex.value++; lastIndex.value++;
} }
onStartTimer();
nextTick(() => {
renderChart();
onStartTimer();
});
}, props.times); }, props.times);
} }
function onClickPoint(val: any, index: number) { function onClickPoint(val: any, index: number) {
if (index === lastIndex.value) return;
offTimer(); offTimer();
if (index > lastIndex.value) { if (index > lastIndex.value) {
// 右 // 右
} else if (index < lastIndex.value) { } else if (index < lastIndex.value) {
// 左 // 左
} else {
return;
} }
pointActive.value = val[props.itemKey]; pointActive.value = val[props.itemKey];
lastIndex.value = index; lastIndex.value = index;
onStartTimer();
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() { function offTimer() {
...@@ -109,9 +230,10 @@ function resetIndex() { ...@@ -109,9 +230,10 @@ function resetIndex() {
> >
<!-- some item --> <!-- some item -->
<div class="my-item-box center"> <div class="my-item-box center">
<div class="fit" :id="`chart-pie-dom-${i[props.itemKey]}`"> <div
{{ i.label }} class="fit"
</div> :id="`${DOM_PIE_KEY}${i[props.itemKey]}`"
></div>
</div> </div>
</div> </div>
</template> </template>
...@@ -170,7 +292,7 @@ function resetIndex() { ...@@ -170,7 +292,7 @@ function resetIndex() {
height: 100%; height: 100%;
overflow: auto; overflow: auto;
position: absolute; position: absolute;
background-color: white; background-color: #fff;
top: 0; top: 0;
left: 0; left: 0;
} }
......
const COLORLIST = [
'#C0232C',
'#B6C335',
'#FBCE0F',
'#E87C24',
'#28727B',
'#FF8463',
'#9BCA62',
'#FAD75F',
'#F3A43B',
'#62BFE0',
'#D7504C',
];
// 图表轮播图测试数据 // 图表轮播图测试数据
export const WarpTestData = [ export const WarpTestData = [
{ {
...@@ -5,10 +18,9 @@ export const WarpTestData = [ ...@@ -5,10 +18,9 @@ export const WarpTestData = [
label: '1号', label: '1号',
url: require('./element/imgs/carousel-1.jpg'), url: require('./element/imgs/carousel-1.jpg'),
option: { option: {
color: COLORLIST,
title: { title: {
text: 'Referer of a Website', text: '1号',
subtext: 'Fake Data',
left: 'center',
}, },
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
...@@ -16,26 +28,18 @@ export const WarpTestData = [ ...@@ -16,26 +28,18 @@ export const WarpTestData = [
legend: { legend: {
orient: 'vertical', orient: 'vertical',
left: 'left', left: 'left',
top: 'bottom',
}, },
series: [ series: [
{ {
name: 'Access From',
type: 'pie', type: 'pie',
radius: '50%',
data: [ data: [
{ value: 1048, name: 'Search Engine' }, { value: 1048, name: '苹果' },
{ value: 735, name: 'Direct' }, { value: 735, name: '香蕉' },
{ value: 580, name: 'Email' }, { value: 580, name: '葡萄' },
{ value: 484, name: 'Union Ads' }, { value: 484, name: '' },
{ value: 300, name: 'Video Ads' }, { value: 300, name: '荔枝' },
], ],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
}, },
], ],
}, },
...@@ -44,31 +48,136 @@ export const WarpTestData = [ ...@@ -44,31 +48,136 @@ export const WarpTestData = [
id: 2, id: 2,
label: '2号', label: '2号',
url: require('./element/imgs/carousel-2.jpg'), 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, id: 3,
label: '3号', label: '3号',
url: require('./element/imgs/carousel-3.jpg'), 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, id: 4,
label: '4号', label: '4号',
url: require('./element/imgs/carousel-4.jpg'), url: require('./element/imgs/carousel-4.jpg'),
option: null, option: {
}, color: COLORLIST,
{ title: {
id: 5, text: '4号',
label: '5号', },
url: require('./element/imgs/carousel-5.jpg'), tooltip: {
option: null, trigger: 'item',
}, },
{ series: [
id: 6, {
label: '6号', type: 'pie',
url: require('./element/imgs/carousel-2.jpg'), radius: [20, 120],
option: null, 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 = [ ...@@ -76,13 +185,12 @@ export const WarpTestData = [
export const WarpTestData2 = [ export const WarpTestData2 = [
{ {
id: 1, id: 1,
label: '1号-变了1', label: '1号',
url: require('./element/imgs/carousel-1.jpg'), url: require('./element/imgs/carousel-1.jpg'),
option: { option: {
color: COLORLIST,
title: { title: {
text: '图表轮播图测试数据2', text: '1号-测试数据2',
subtext: '666',
left: 'center',
}, },
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
...@@ -90,58 +198,232 @@ export const WarpTestData2 = [ ...@@ -90,58 +198,232 @@ export const WarpTestData2 = [
legend: { legend: {
orient: 'vertical', orient: 'vertical',
left: 'left', left: 'left',
top: 'bottom',
}, },
series: [ series: [
{ {
name: 'Access From',
type: 'pie', type: 'pie',
radius: '50%',
data: [ data: [
{ value: 1000, name: 'Search Engine' }, { value: 1048, name: '苹果' },
{ value: 1000, name: 'Direct' }, { value: 735, name: '香蕉' },
{ value: 1000, name: 'Email' }, { value: 580, name: '葡萄' },
{ value: 1000, name: 'Union Ads' }, { value: 484, name: '梨' },
{ value: 1000, name: 'Video Ads' }, { value: 300, name: '荔枝' },
], ],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
},
}, },
], ],
}, },
}, },
{ {
id: 2, id: 2,
label: '2号-变了1', label: '2号',
url: require('./element/imgs/carousel-2.jpg'), 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, id: 3,
label: '3号-变了1', label: '3号-测试数据2',
url: require('./element/imgs/carousel-3.jpg'), 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, id: 4,
label: '4号-变了1', label: '4号',
url: require('./element/imgs/carousel-4.jpg'), url: require('./element/imgs/carousel-4.jpg'),
option: null, 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: {
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' },
],
},
],
},
}, },
// {
// 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,
// },
]; ];
...@@ -4,17 +4,18 @@ ...@@ -4,17 +4,18 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, onMounted, onBeforeUnmount } from 'vue'; import { reactive, onMounted, onBeforeUnmount } from 'vue';
import Com from 'src/components'; import Com from 'src/components';
import { WarpTestData, WarpTestData2 } from '../config'; import { WarpTestData, WarpTestData2, WarpTestData3 } from '../config';
import * as echarts from 'echarts';
const state = reactive({ const state = reactive({
list: [] as any, list: [] as any,
times: 5000, times: 5000,
testChart: null as any,
}); });
onMounted(() => { onMounted(() => {
setTimeout(() => { test111();
initData(); initData();
}, 3000);
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
...@@ -25,16 +26,72 @@ function initData() { ...@@ -25,16 +26,72 @@ function initData() {
state.list = WarpTestData; state.list = WarpTestData;
} }
function onDataChange1() {
state.list = WarpTestData;
}
function onDataChange2() { function onDataChange2() {
state.list = WarpTestData2; state.list = WarpTestData2;
} }
function onDataChange3() {
state.list = WarpTestData3;
}
function onSetToEnpty() { function onSetToEnpty() {
state.list = []; state.list = [];
} }
function onChangeTimers() { 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> </script>
<template> <template>
...@@ -49,18 +106,39 @@ function onChangeTimers() { ...@@ -49,18 +106,39 @@ function onChangeTimers() {
</Com.CarouselWarp> </Com.CarouselWarp>
</div> </div>
<div class="btns"> <div class="btns">
<q-btn
label="图表轮播图测试数据1"
@click="onDataChange1"
color="primary"
/>
<q-btn <q-btn
label="图表轮播图测试数据2" label="图表轮播图测试数据2"
@click="onDataChange2" @click="onDataChange2"
color="primary" color="primary"
/> />
<q-btn
label="图表轮播图测试数据3"
@click="onDataChange3"
color="primary"
/>
<q-btn label="将数据置为空" @click="onSetToEnpty" color="primary" /> <q-btn label="将数据置为空" @click="onSetToEnpty" color="primary" />
<q-btn label="改变轮播时间" @click="onChangeTimers" color="orange" /> <q-btn label="改变轮播时间" @click="onChangeTimers" color="orange" />
</div> </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> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.test111 {
width: 500px;
height: 500px;
border: 1px solid red;
}
.my-warp-box { .my-warp-box {
width: 500px; width: 500px;
height: 300px; 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