目录
一、下载echarts 、vue-awesome(icon图标)、@jiaminghi/data-view(DataV组件)、lib-flexible(屏幕适配)
一、下载echarts 、vue-awesome(icon图标)、@jiaminghi/data-view(DataV组件)、lib-flexible(屏幕适配)
cnpm i -S echart@4.9.0 vue-awesome @jiaminghi/data-view lib-flexible
二、在main.js中引入
import dataV from '@jiaminghi/data-view';
Vue.use(dataV);
// 按需引入vue-awesome图标
import Icon from 'vue-awesome/components/Icon';
import 'vue-awesome/icons/chart-bar.js';
import 'vue-awesome/icons/chart-area.js';
import 'vue-awesome/icons/chart-pie.js';
import 'vue-awesome/icons/chart-line.js';
import 'vue-awesome/icons/align-left.js';
// 全局注册图标
Vue.component('icon', Icon);
// 适配flex
import 'flexible.js';
//引入echart
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
修改flexible.js:
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
// 最小1366px,最大适配2560px
if (width / dpr < 1366) {
width = 1366 * dpr;
} else if (width / dpr > 2560) {
width = 2560 * dpr;
}
// 设置成24等份,设计稿时1920px的,这样1rem就是80px
var rem = width / 24;
docEl.style.fontSize = rem + "px";
flexible.rem = win.rem = rem;
}
三、封装echarts
echarts/index.vue:
<template>
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import tdTheme from './theme.json' // 引入默认主题
import resizeMixins from "@/utils/resizeMixins";
export default {
name: 'echart',
mixins: [resizeMixins],
props: {
className: {
type: String,
default: 'chart'
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '2.5rem'
},
options: {
type: Object,
default: ()=>({})
}
},
data () {
return {
chart: null
}
},
watch: {
options: {
handler (options) {
// 设置true清空echart缓存
this.chart.setOption(options, true)
},
deep: true
}
},
mounted () {
this.$echarts.registerTheme('tdTheme', tdTheme); // 覆盖默认主题
this.initChart();
},
methods: {
initChart () {
// 初始化echart
this.chart = this.$echarts.init(this.$el, 'tdTheme')
this.chart.setOption(this.options, true)
}
}
}
</script>
<style>
</style>
其中的theme.json自己去echarts官网下载。
utils / resizeMixins.js:
// 混入代码 resize-mixins.js
import { debounce } from '@/utils/index.js';
const resizeChartMethod = '$__resizeChartMethod';
export default {
data() {
// 在组件内部将图表 init 的引用映射到 chart 属性上
return {
chart: null,
};
},
created() {
window.addEventListener('resize', this[resizeChartMethod], false);
},
activated() {
// 防止 keep-alive 之后图表变形
if (this.chart) {
this.chart.resize()
}
},
beforeDestroy() {
window.removeEventListener('resize', this[resizeChartMethod]);
},
methods: {
// 防抖函数来控制 resize 的频率
[resizeChartMethod]: debounce(function() {
if (this.chart) {
this.chart.resize();
}
}, 300)
},
};
utils/index.js:(防抖函数)
/**
* @param {Function} fn 防抖函数
* @param {Number} delay 延迟时间
*/
export function debounce(fn, delay) {
var timer;
return function() {
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}
四、父子组件传值
components/bottomLeftChart/chart.vue:
<template>
<!-- 每一个图表都要设置height高度,如下 -->
<Echart
:options="options"
height="4.7rem"
></Echart>
</template>
<script>
import Echart from '@/common/echart'
export default {
data () {
return {
options: {},
};
},
components: {
Echart,
},
props: {
cdata: {
type: Object,
default: () => ({})
},
},
watch: {
cdata: {
handler (newData) {
this.options = {
//这里写options的配置。动态变化的数据从newData中获取
title:{},
legend:{},
xAxis:{
data:newData.xxx,
axisLine:{}
},
yAxis:{},
series:[]
}
},
immediate: true,
deep: true
},
},
}
</script>
components/bottomLeftChart/index.js:
<template>
<Chart :cdata="cdata" />
</template>
<script>
import Chart from "./chart.vue";
export default {
data() {
return {
//这里只需要把动态变化的数据传过去就行了。其他不变的option配置不用写。因为option是整合的关
//系,而不是替换的关系。
cdata: {
lineData:[xxx],
barData:[xxx]
}
};
},
components: {
Chart,
},
mounted() {
this.setData();
},
methods: {
// 根据自己的业务情况修改
setData() {
//这里动态注入数据。
this.cdata={xxx}
},
},
};
</script>
五、div包装
card.vue:
<template>
<div class="card">
<div class="background">
<div class="d-flex mb-2 pt-2 pl-2">
<span class="icon-color">
<slot name="icon">
<icon name="chart-pie"></icon>
</slot>
</span>
<span class="fs-md colorText mx-2">{{title}}</span>
<div style="width:1.25rem;height:.25rem; position:relative;top:-.0375rem;">
<slot name="decoration">
</slot>
</div>
</div>
<div>
<slot name="content">
内容区域
</slot>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {};
},
props:{
title:{
type:String,
default:"title"
}
},
components: {
},
mounted() {},
methods: {}
};
</script>
<style lang="scss">
.card {
padding: 0.15rem ;
height: 100%;
min-width: 3.75rem;
border-radius: 0.0625rem;
.background {
border-radius: 0.125rem;
background-color: rgba(19, 25, 47, 0.6);
height: 100%;
}
}
</style>
六、引用模板
<template>
<card id="bottomLeft" title="数据统计图">
<icon name="chart-bar" slot="icon"></icon>
<dv-decoration-1 slot="decoration" />
<div slot="content">
<BottomLeftChart />
</div>
</card>
</template>
<script>
import card from "@/components/card";
import BottomLeftChart from "@/components/bottomLeftChart";
export default {
data() {
return {};
},
components: {
BottomLeftChart,
card,
},
mounted() {},
methods: {},
};
</script>
七、使用
注意:这里一定要设置父亲的宽和高,因为封装的组件里面的宽高全是100%,所以全由外层的父亲决定宽高。
下面的 <dv-border-box-13>可以更换,见:http://datav.jiaminghi.com/guide/borderBox.html#dv-border-box-1
<div style="height: 5rem;width:10rem">
<!-- 每一个板块的宽高由父亲决定 -->
<dv-border-box-13>
<bottomLeft />
</dv-border-box-13>
</div>
八、示例
效果图:
代码参考:https://blog.csdn.net/qq_40323256/article/details/114890628
components/bottomRightChart/chart.vue:
<template>
<!-- 每一个图表都要设置height高度,如下 -->
<Echart :options="options" height="4.7rem"></Echart>
</template>
<script>
import Echart from "@/common/echart";
export default {
data() {
return {
options: {},
};
},
components: {
Echart,
},
props: {
cdata: {
type: Object,
default: () => ({}),
},
},
watch: {
cdata: {
handler(newData) {
this.options = {
tooltip: {
show: true,
},
xAxis: {
type: "category",
data: newData.provinceInfo,
},
yAxis: {
value: "value",
},
dataZoom: {
// 区域缩放组件
show: false,
startValue: newData.startValue,
endValue: newData.endValue,
},
series: [
{
type: "bar",
label: {
show: true,
position: "top",
color: "white",
rotate: 30,
},
barWidth: 30,
data: newData.valueArr,
itemStyle: {
barBorderRadius: [15, 15, 0, 0], //[左上角,右上角,左小角,右下角]
color: (arg) => {
let targetColorArr = null;
if (arg.value > 300) {
targetColorArr = newData.colorArr[0];
} else if (arg.value > 200) {
targetColorArr = newData.colorArr[1];
} else {
targetColorArr = newData.colorArr[2];
}
return new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
// 0%
{ offset: 0, color: targetColorArr[0] },
// 100%
{ offset: 1, color: targetColorArr[1] },
]);
},
},
},
],
};
},
immediate: true,
deep: true,
},
},
};
</script>
components/bottomRightChart/index.vue:
<template>
<Chart
:cdata="cdata"
@mouseover.native="handlerMouseOver()"
@mouseout.native="handlerMouseOut()"
/>
</template>
<script>
import Chart from "./chart.vue";
export default {
data() {
return {
cdata: {
colorArr: [],
provinceInfo: [],
valueArr: [],
// 柱形图 区域缩放起点值
startValue: 0,
// 柱形图结 区域缩放终点值
endValue: 9,
},
// 定时器
timerId: null,
};
},
components: {
Chart,
},
mounted() {
this.updateChart();
this.startInterval();
},
destroyed() {
clearInterval(this.timerId);
},
methods: {
// 鼠标经过关闭 动画效果
handlerMouseOver() {
clearInterval(this.timerId);
},
// 鼠标离开 开启动画效果
handlerMouseOut() {
this.startInterval();
},
// 根据自己的业务情况修改
updateChart() {
this.cdata.colorArr = [
["#b8e994", "#079992"],
["#82ccdd", "#0a3d62"],
["#f8c291", "#b71540"],
];
this.cdata.provinceInfo = [
"上海",
"北京",
"广州",
"深圳",
"四川",
"重庆",
"河北",
"河南",
"山东",
"山西",
"云南",
"海南",
"甘肃",
"湖北",
"湖南",
];
this.cdata.valueArr = [
100,
200,
300,
400,
123,
234,
345,
456,
124,
241,
134,
241,
123,
111,
245,
];
},
// 改变柱形图 区域缩放起始与终点值的函数
startInterval() {
// 如果存在则关闭
this.timerId && clearInterval(this.timerId);
this.timerId = setInterval(() => {
this.cdata.startValue++;
this.cdata.endValue++;
if (this.cdata.endValue > this.cdata.provinceInfo.length - 1) {
this.cdata.startValue = 0;
this.cdata.endValue = 9;
}
this.updateChart();
}, 2000);
},
},
};
</script>
views/bottomRight.vue:
<template>
<card id="bottomRight" title="数据统计图">
<icon name="chart-bar" slot="icon"></icon>
<dv-decoration-1 slot="decoration" />
<div slot="content">
<BottomRightChart />
</div>
</card>
</template>
<script>
import card from "@/components/card";
import BottomRightChart from "@/components/bottomRightChart";
export default {
data() {
return {};
},
components: {
BottomRightChart,
card,
},
mounted() {},
methods: {},
};
</script>
views/menu2/index.vue:
<!--menu2-->
<template>
<div>
<div style="height: 5rem; width: 10rem">
<!-- 每一个板块的宽高由父亲决定 -->
<dv-border-box-13>
<bottomRight />
</dv-border-box-13>
</div>
</div>
</template>
<script>
import bottomRight from "../bottomRight";
export default {
name: "",
components: { bottomRight },
data() {
return {};
},
props: {},
created() {},
mounted() {},
computed: {},
methods: {},
watch: {},
};
</script>
<style lang="scss" scoped>
</style>