vw vh 大屏可视化适配方案

看了网上的各种方案,目前大家采用的大概有 3 种👇

方案实现方式优点缺点
vw vh1.按照设计稿的尺寸,将px按比例计算转为vwvh1.可以动态计算图表的宽高,字体等,灵活性较高
2.当屏幕比例跟 ui 稿不一致时,不会出现两边留白情况
1.每个图表都需要单独做字体、间距、位移的适配,比较麻烦
scale1.通过 scale 属性,根据屏幕大小,对图表进行整体的等比缩放1.代码量少,适配简单
2.一次处理后不需要在各个图表中再去单独适配
1.因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况
2.当缩放比例过大时候,字体会有一点点模糊,就一点点
3.当缩放比例过大时候,事件热区会偏移。
rem + vw vh1.获得 rem 的基准值
2.动态的计算html根元素的font-size
3.图表中通过 vw vh 动态计算字体、间距、位移等
1.布局的自适应代码量少,适配简单1.因为是根据 ui 稿等比缩放,当大屏跟 ui 稿的比例不一样时,会出现周边留白情况
2.图表需要单个做字体、间距、位移的适配

以上 3 种方案在实际应用中该怎么选择视具体情况而定。

  • 如果想简单,客户能同意留白,选用 scale 即可
  • 如果需要兼容不同比例的大屏,并且想在不同比例中都有比较好的效果,图表占满屏幕,类似于移动端的响应式,可以采用 vw vh 的方案
  • 至于 rem,个人觉得就是 scale 和 vw vh 的综合,最终的效果跟 scale 差不多

接下来展示的是vw vh方案实现步骤:

实现思路

按照设计稿的尺寸,将px按比例计算转为vwvh,转换公式如下

假设设计稿尺寸为 1920*1080(做之前一定问清楚 ui 设计稿的尺寸)

即:
网页宽度=1920px
网页高度=1080px

我们都知道
网页宽度=100vw
网页宽度=100vh

所以,在 1920px*1080px 的屏幕分辨率下

1920px = 100vw

1080px = 100vh

这样一来,以一个宽 300px 和 200px 的 div 来说,其所占的宽高,以 vw 和 vh 为单位,计算方式如下:

vwDiv = (300px / 1920px ) * 100vw
vhDiv = (200px / 1080px ) * 100vh

所以,就在 1920*1080 的屏幕分辨率下,计算出了单个 div 的宽高

当屏幕放大或者缩小时,div 还是以 vw 和 vh 作为宽高的,就会自动适应不同分辨率的屏幕

css 方案 - sass

util.scss

// 使用 scss 的 math 函数,https://sass-lang.com/documentation/breaking-changes/slash-div
@use "sass:math";

// 默认设计稿的宽度
$designWidth: 1920;
// 默认设计稿的高度
$designHeight: 1080;

// px 转为 vw 的函数
@function vw($px) {
  @return math.div($px, $designWidth) * 100vw;
}

// px 转为 vh 的函数
@function vh($px) {
  @return math.div($px, $designHeight) * 100vh;
}

路径配置
只需在vue.config.js里配置一下utils.scss的路径,就可以全局使用了

vue.config.js

const path = require("path");

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = {
  publicPath: "",
  configureWebpack: {
    name: "app name",
    resolve: {
      alias: {
        "@": resolve("src"),
      },
    },
  },
  css: {
    // 全局配置 utils.scs,详细配置参考 vue-cli 官网
    loaderOptions: {
      sass: {
        prependData: `@import "@/styles/utils.scss";`,
      },
    },
  },
};








vite:
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: `@import "@/styles/util.scss";`,
        },
      },
    },

在 .vue 中使用

<template>
    <div class="box">			
    </div>
</template>

<script>
export default{
    name: "Box",
}
</script>

<style lang="scss" scoped="scoped">
/* 
 直接使用 vw 和 vh 函数,将像素值传进去,得到的就是具体的 vw vh 单位		 
 */
.box{
    width: vw(300);
    height: vh(100);
    font-size: vh(16);
    background-color: black;
    margin-left: vw(10);
    margin-top: vh(10);
    border: vh(2) solid red;
}
</style>
css 方案 - less

utils.less

@charset "utf-8";

// 默认设计稿的宽度
@designWidth: 1920;

// 默认设计稿的高度
@designHeight: 1080;

.px2vw(@name, @px) {
  @{name}: (@px / @designWidth) * 100vw;
}

.px2vh(@name, @px) {
  @{name}: (@px / @designHeight) * 100vh;
}

.px2font(@px) {
  font-size: (@px / @designWidth) * 100vw;
}

路径配置
vue.config.js里配置一下utils.less

const path = require("path");

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = {
  publicPath: "",
  configureWebpack: {
    name: "app name",
    resolve: {
      alias: {
        "@": resolve("src"),
      },
    },
  },
  css: {
    // 全局配置utils.scss
    loaderOptions: {
      less: {
        additionalData: `@import "@/styles/utils.less";`,
      },
    },
  },
};

在 .vue 文件中使用

<template>
    <div class="box">			
    </div>
</template>

<script>
export default{
    name: "Box",
}
</script>

<style lang="less" scoped="scoped">
/* 
 直接使用 vw 和 vh 函数,将像素值传进去,得到的就是具体的 vw vh单位		 
 */
.box{
    .px2vw(width, 300);
    .px2vh(height, 100);
    .px2font(16);
    .px2vw(margin-left, 300);
    .px2vh(margin-top, 100);
    background-color: black;
}
</style>
定义 js 样式处理函数
// 定义设计稿的宽高
const designWidth = 1920;
const designHeight = 1080;

// px转vw
export const px2vw = (_px) => {
  return (_px * 100.0) / designWidth + 'vw';
};

export const px2vh = (_px) => {
  return (_px * 100.0) / designHeight + 'vh';
};

export const px2font = (_px) => {
  return (_px * 100.0) / designWidth + 'vw';
};
屏幕变化后,图表自动调整

这种使用方式有个弊端,就是屏幕尺寸发生变化后,需要手动刷新一下才能完成自适应调整

为了解决这个问题,你需要在各个图表中监听页面尺寸变化,重新调整图表,在 vue 项目中,也可以借助element-resize-detector,最好封装个 resize 的指令,在各图表中就只要使用该指令就可以了,毕竟作为程序员,能偷懒就偷懒

1.安装 element-resize-detector

npm install element-resize-detector --save

 2.引入工具包在组件中使用或者在单独的 js 中使用

import resizeDetector from 'element-resize-detector'

3.封装 directive

// directive.js
import * as ECharts from "echarts";
import elementResizeDetectorMaker from "element-resize-detector";
import Vue from "vue";
const HANDLER = "_vue_resize_handler";
function bind(el, binding) {
  el[HANDLER] = binding.value
    ? binding.value
    : () => {
        let chart = ECharts.getInstanceByDom(el);
        if (!chart) {
          return;
        }
        chart.resize();
      };
  // 监听绑定的div大小变化,更新 echarts 大小
  elementResizeDetectorMaker().listenTo(el, el[HANDLER]);
}
function unbind(el) {
  // window.removeEventListener("resize", el[HANDLER]);
  elementResizeDetectorMaker().removeListener(el, el[HANDLER]);
  delete el[HANDLER];
}
// 自定义指令:v-chart-resize 示例:v-chart-resize="fn"
Vue.directive("chart-resize", { bind, unbind });

 4.main.js 中引入

import '@/directive/directive';

5.html 代码

<template>
  <div class="linechart">
    <div ref="chart" v-chart-resize class="chart"></div>
  </div>
</template>

这里要注意的是,图表中如果需要 tab 切换动态更新图表数据,在更新数据时一定不要用 echarts 的 dispose 方法先将图表移除,再重新绘制,因为 resize 指令中挂载到的图表实例还是旧的,就监听不到新的 chart 元素的 resize 了,更新数据只需要用 chart 的 setOption 方法重新设置配置项即可。

图表字体、间距、位移等尺寸自适应

echarts 的字体大小只支持具体数值(像素),不能用百分比或者 vw 等尺寸,一般字体不会去做自适应,当宽高比跟 ui 稿比例出入太大时,会出现文字跟图表重叠的情况

这里我们就需要封装一个工具函数,来处理图表中文字自适应了👇

  • 默认情况下,这里以你的设计稿是 1920*1080 为例,即网页宽度是 1920px (做之前一定问清楚 ui 设计稿的尺寸)

  • 把这个函数写在一个单独的工具文件dataUtil.js里面,在需要的时候调用

  • 其原理是计算出当前屏幕宽度和默认设计宽度的比值,将原始的尺寸乘以该值

  • 另外,其它 echarts 的配置项,比如间距、定位、边距也可以用该函数

1.编写 dataUtil.js 工具函数

// Echarts图表字体、间距自适应
export const fitChartSize = (size,defalteWidth = 1920) => {
  let clientWidth = window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
  if (!clientWidth) return size;
  let scale = (clientWidth / defalteWidth);
  return Number((size*scale).toFixed(3));
}




/********如果你有带鱼屏的适配,需要改为以vh高度计算的********/
// 1080高度计算
export const fitChartSize = (size, defaultHeight = 1080) => {
    let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    if (!clientHeight) return size;
    let scale = (clientHeight / defaultHeight);
    return Number((size * scale).toFixed(3));
}

2.将函数挂载到原型上

import {fitChartSize} from '@src/utils/dataUtil.js'
Vue.prototype.fitChartFont = fitChartSize;



/********vue3写法********/
import { fitChartSize } from '@/utils/dataUtil.js'  
// 添加全局方法
app.config.globalProperties.$fitChartSize = fitChartSize;

const { proxy } = getCurrentInstance();
proxy.$fitChartSize(2)

示例代码:

// 装卸能耗分析
<template>
    <div class="all">
        <div class="all_title">
            <span class="all_title_txt">装卸能耗分析</span>
            <img class="dateBg" src="../../assets/images/dateBg.png" alt="" oncontextmenu="return false"
                draggable="false">
        </div>
        <div class="all_bod" id="echarts2"></div>
    </div>
</template>

<script setup name="box8">
const { proxy } = getCurrentInstance();
import { ref, reactive, watch, onMounted, onUnmounted, nextTick } from "vue";
// const { fitChartSize } = proxy.$fitChartSize(); 
// let currentIndex = ref(0)
// let chart = ref(null);
let timeTicket = ref(null);
let timer = ref(null);

const props = defineProps({
    allData: {
        type: Object,
        required: true
    }
});

// 监听 allData 的变化
watch(() => props.allData, (newVal) => {
    // console.log("echarts8接收到值", newVal)
    let myData8 = [];
    let tss = [];
    let dcl = [];
    // let myData8 = ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"];
    // let tss = [60, 80, 20, 40, 60, 40, 50, 50, 60, 32, 52, 55, 60];
    // let dcl = [40, 55, 50, 60, 30, 20, 60, 30, 20, 10, 30, 20];
    newVal.forEach(item => {
        myData8.push(item.time)
        tss.push(item.energyConsumption)
        dcl.push(item.thruput)
    })
    setTimeout(() => {
        initChart(myData8, tss, dcl)
    }, 500)
});

// window.addEventListener('resize', function () {
//     // const innerWidth = window.innerWidth
//     // const innerHeight = window.innerHeight
//     // console.log("resize", proxy.$fitChartSize(14))
//     chart.resize();
// });

onUnmounted(() => {
    if (timer.value) clearInterval(timer.value);
})

// onMounted(() => {
//     setTimeout(() => {
//         console.log(6666, proxy.$fitChartSize(14))
//     }, 500)
// })

// 计算样式
// const computedSize = computed(() => {
//     let clientWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
//     let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
//     let objFun = {};

//     // 14寸笔记本
//     if (clientWidth <= 1366) {
//         console.log("14寸笔记本")
//         // objFun.fontSize = 12; //文字大小
//         // objFun.symbolSize = 3; //节点大小
//         // objFun.borderWidth = 1; //线条宽度
//         // objFun.itemWidth = 12; //legend方块宽度
//         // objFun.itemHeight = 5; //legend方块高度
//         // objFun.padding = [0, 50, 0, 0]; //右侧单位距离右侧距离
//         // objFun.nameGap = 10;
//         objFun.grid = {
//             containLabel: true,
//             bottom: "6%",
//             top: "25%",
//             left: "2%",
//             right: "2%",
//         };
//     } // 全高清屏幕
//     else if (clientWidth <= 1920) {
//         console.log("全高清屏幕")
//         // objFun.fontSize = 14; //文字大小
//         // objFun.symbolSize = 5; //节点大小
//         // objFun.borderWidth = 2; //线条宽度
//         // objFun.itemWidth = 20; //legend方块宽度
//         // objFun.itemHeight = 8; //legend方块高度
//         // objFun.padding = [0, 55, 0, 0]; //右侧单位距离右侧距离
//         // objFun.nameGap = 15;
//         objFun.grid = {
//             containLabel: true,
//             bottom: "6%",
//             top: "25%",
//             left: "2%",
//             right: "2%",
//         };
//     }// 2K
//     else if (clientWidth <= 2560) {
//         console.log("2K")
//         // objFun.fontSize = 22; //文字大小
//         // objFun.symbolSize = 8; //节点大小
//         // objFun.borderWidth = 3; //线条宽度
//         // objFun.itemWidth = 25; //legend方块宽度
//         // objFun.itemHeight = 10; //legend方块高度
//         // objFun.padding = [0, 85, 0, 0]; //右侧单位距离右侧距离
//         // objFun.nameGap = 16;
//         objFun.grid = {
//             containLabel: true,
//             bottom: "6%",
//             top: "24%",
//             left: "2%",
//             right: "2%",
//         };
//     }// 4K 带鱼屏
//     else if (clientWidth <= 3840 && clientHeight <= 1080) {
//         console.log("4K 带鱼屏")
//         // objFun.fontSize = 20; //文字大小
//         // objFun.symbolSize = 9; //节点大小
//         // objFun.borderWidth = 2.5; //线条宽度
//         // objFun.itemWidth = proxy.$fitChartSize(22); //legend方块宽度
//         // objFun.itemHeight = proxy.$fitChartSize(12); //legend方块高度
//         // objFun.padding = [0, 60, 0, 0]; //右侧单位距离右侧距离
//         // objFun.nameGap = proxy.$fitChartSize(15);
//         objFun.grid = {
//             containLabel: true,
//             bottom: "6%",
//             top: proxy.$fitChartSize(60),
//             left: "2%",
//             right: "2%",
//         };
//     }// 4K
//     else if (clientWidth <= 3840 && clientHeight >= 1080) {
//         console.log("4K尺寸")
//         // objFun.fontSize = 35; //文字大小
//         // objFun.symbolSize = 20; //节点大小
//         // objFun.borderWidth = 5; //线条宽度
//         // objFun.itemWidth = 40; //legend方块宽度
//         // objFun.itemHeight = 20; //legend方块高度
//         // objFun.padding = [0, 100, 0, 0]; //右侧单位距离右侧距离
//         // objFun.nameGap = 30;
//         objFun.grid = {
//             containLabel: true,
//             bottom: "6%",
//             top: "21%",
//             left: "2%",
//             right: "2%",
//         };
//     }
//     return objFun;
// });

// 初始化echarts
function initChart(myData8, tss, dcl) {
    const chartDom = document.getElementById('echarts2');
    let chart = proxy.$echarts.init(chartDom);
    // let ycl = [20, 60, 65, 20, 10, 60, 80, 25, 40, 60, 20, 40];
    let option = {
        title: {
            text: '能耗设备',
            textStyle: {
                fontSize: proxy.$fitChartSize(14),  // 设置文字大小
                color: '#fff'   // 设置文字颜色
            },
        },
        // backgroundColor: "#041D3F",
        tooltip: {
            trigger: "axis",
            axisPointer: {
                lineStyle: {
                    color: {
                        type: "linear",
                        x: 0,
                        y: 0,
                        x2: 0,
                        y2: 1,
                        colorStops: [
                            {
                                offset: 0,
                                color: "rgba(0, 255, 233,0)",
                            },
                            {
                                offset: 0.5,
                                color: "rgba(255, 255, 255,1)",
                            },
                            {
                                offset: 1,
                                color: "rgba(0, 255, 233,0)",
                            },
                        ],
                        global: false,
                    },
                },
            },
            textStyle: {
                color: "#fff",
                fontSize: proxy.$fitChartSize(14), // 设置字体大小
            },
            confine: true, // 限制溢出屏幕外
            backgroundColor: "rgba(0,0,0,0.5)", // 设置背景颜色
            padding: [10, 10, 10, 10], // 设置方框的内边距
        },
        // grid: computedSize.value.grid,
        grid: {
            containLabel: true,
            bottom: proxy.$fitChartSize(0),
            top: proxy.$fitChartSize(55),
            left: proxy.$fitChartSize(5),
            right: proxy.$fitChartSize(5),
        },
        legend: {
            show: true,
            right: 0,
            top: 0,
            // itemWidth: computedSize.value.itemWidth,
            itemWidth: proxy.$fitChartSize(22),
            // itemHeight: computedSize.value.itemHeight,
            itemHeight: proxy.$fitChartSize(12),
            icon: 'rect',
            // itemGap: 20, // 调整图例项之间的水平间距
            textStyle: {
                color: '#fff',
                fontSize: proxy.$fitChartSize(14),
                // 设置上下居中对齐
                align: 'center',
                // verticalAlign: 'middle',
                // color: "#B6DCF5",
                // padding: [0, 0, 0, 4],
            },
        },
        xAxis: {
            data: myData8,
            axisLabel: {
                interval: 0,
                show: true,
                fontSize: proxy.$fitChartSize(14),
                color: "#B6DCF5",
            },
            axisLine: {
                show: true,
                lineStyle: {
                    show: true,
                    color: "rgba(54, 153, 255, .4)",
                },
            },
            axisTick: {
                show: false,
            },
        },
        yAxis: [
            {
                name: "单位:KJ",
                type: "value",
                // nameGap: computedSize.value.nameGap,
                nameGap: proxy.$fitChartSize(15),
                nameTextStyle: {
                    color: "#B6DCF5",
                    fontSize: proxy.$fitChartSize(14),
                    align: "center",
                    padding: [0, 0, 0, 0],
                    // padding: [0, 0, 0, proxy.$fitChartSize(50)],
                },
                // splitNumber: 5,
                axisLabel: {
                    show: true,
                    fontSize: proxy.$fitChartSize(14),
                    color: "#B6DCF5",
                },
                axisLine: {
                    show: false,
                    lineStyle: {
                        color: "#7FD6FF",
                    },
                },
                axisTick: {
                    show: false,
                },
                splitLine: {
                    lineStyle: {
                        color: "rgba(54, 153, 255, .4)",
                        type: "dashed",
                    },
                },
            }, {
                name: "单位:吨",
                // offset: -25,
                type: "value",
                // nameGap: computedSize.value.nameGap, // 控制名称和轴之间的距离
                nameGap: proxy.$fitChartSize(15), // 控制名称和轴之间的距离
                nameLocation: "end",
                nameTextStyle: {
                    color: "#B6DCF5",
                    fontSize: proxy.$fitChartSize(14),
                    align: "center",
                    // padding: [0, 0, 0, 0],
                    // padding: computedSize.value.padding,
                    padding: [0, proxy.$fitChartSize(50), 0, 0],
                    // padding: computedSize.value.padding,
                },
                // splitNumber: 5,
                axisLabel: {
                    show: true,
                    fontSize: proxy.$fitChartSize(14),
                    color: "#B6DCF5",
                },
                axisLine: {
                    show: false,
                    lineStyle: {
                        color: "#7FD6FF",
                    },
                },
                axisTick: {
                    show: false,
                },
                splitLine: {
                    lineStyle: {
                        color: "rgba(54, 153, 255, .4)",
                        type: "dashed",
                    },
                },
            }
        ],
        series: [
            {
                name: "能耗",
                type: "line",
                showSymbol: true,
                symbolSize: proxy.$fitChartSize(6),  //节点圆点大小
                symbol: "circle",
                lineStyle: {
                    normal: {
                        color: "#FF8E3C",
                        // width: computedSize.value.borderWidth, //线条宽度
                        width: proxy.$fitChartSize(2), //线条宽度
                    },
                },
                itemStyle: {
                    color: "#FF8E3C",
                    // borderColor: "#fff",
                    borderWidth: 2,
                },
                data: tss, // 折线图的数据
            },
            {
                name: "吞吐量",
                type: "line",
                showSymbol: true,
                symbol: "circle",
                symbolSize: proxy.$fitChartSize(6), //节点圆点大小
                lineStyle: {
                    normal: {
                        color: "#00A0E9",
                        // width: computedSize.value.borderWidth, //线条宽度
                        width: proxy.$fitChartSize(2), //线条宽度
                    },
                },
                itemStyle: {
                    color: "#00A0E9",
                    // borderColor: "#fff",
                    // borderWidth: 2,
                    borderWidth: proxy.$fitChartSize(3),
                },
                data: dcl, // 折线图的数据
            },
            // {
            //     name: "已处理",
            //     type: "line",
            //     showSymbol: true,
            //     symbolSize: 8,
            //     symbol: "circle",
            //     lineStyle: {
            //         normal: {
            //             color: "#02D6B0",
            //         },
            //     },
            //     itemStyle: {
            //         color: "#02D6B0",
            //         borderColor: "#fff",
            //         borderWidth: 2,
            //     },
            //     data: ycl, // 折线图的数据
            // },
        ],
    };
    // 使用刚指定的配置项和数据显示图表。
    chart.setOption(option);

    // 轮播核心
    handleChartLoop(option, chart);

    // let index = 0; // 初始化索引 

    // // 使用定时器定时更新 tooltip 数据
    // if (timer.value) clearInterval(timer.value);

    // timer.value = setInterval(() => {
    //     chart.dispatchAction({
    //         type: "showTip", // 触发 tooltip 显示
    //         seriesIndex: 0, // 触发 tooltip 的系列索引
    //         dataIndex: index, // 触发 tooltip 的数据索引
    //     });
    //     index = (index + 1) % myData8.length; // 更新索引,循环显示数据
    // }, 2000); // 每隔 2 秒更新一次 

    // // 鼠标移入暂停轮播
    // chart.on("mousemove", () => {
    //     console.log("清空")
    //     if (timer.value) clearInterval(timer.value);
    //     timer.value = null;
    // });

    // // 鼠标移出继续轮播
    // chart.on("globalout", () => {
    //     if (timer.value) clearInterval(timer.value);
    //     timer.value = setInterval(() => {
    //         chart.dispatchAction({
    //             type: "showTip", // 触发 tooltip 显示
    //             seriesIndex: 0, // 触发 tooltip 的系列索引
    //             dataIndex: index, // 触发 tooltip 的数据索引
    //         });
    //         index = (index + 1) % myData8.length; // 更新索引,循环显示数据
    //     }, 2000); // 每隔 2 秒更新一次
    // });

    window.addEventListener('resize', function () {
        chart.resize();
    });

}

function handleChartLoop(option, myChart) {
    if (!myChart) {
        return;
    }
    let currentIndex = -1; // 当前高亮图形在饼图数据中的下标
    timeTicket.value = setInterval(selectPie, 2000); // 设置自动切换高亮图形的定时器

    // 取消所有高亮并高亮当前图形
    function highlightPie() {
        // 遍历饼图数据,取消所有图形的高亮效果
        for (var idx in option.series[0].data) {
            myChart.dispatchAction({
                type: "downplay",
                seriesIndex: 0,
                dataIndex: idx,
            });
        }
        // 高亮当前图形
        myChart.dispatchAction({
            type: "highlight",
            seriesIndex: 0,
            dataIndex: currentIndex,
        });
        // 显示 tooltip
        myChart.dispatchAction({
            type: "showTip",
            seriesIndex: 0,
            dataIndex: currentIndex
        })
    }

    // 用户鼠标悬浮到某一图形时,停止自动切换并高亮鼠标悬浮的图形
    myChart.on("mouseover", (params) => {
        clearInterval(timeTicket.value);
        currentIndex = params.dataIndex;
        highlightPie();
    });

    // 用户鼠标移出时,重新开始自动切换
    myChart.on("mouseout", (params) => {
        if (timeTicket.value) {
            clearInterval(timeTicket.value);
        }
        timeTicket.value = setInterval(selectPie, 2000);
    });

    // 高亮效果切换到下一个图形
    function selectPie() {
        var dataLen = option.series[0].data.length;
        currentIndex = (currentIndex + 1) % dataLen;
        highlightPie();
    }
}
</script>

<style lang="scss" scoped>
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

img {
    -webkit-user-drag: none;
    user-drag: none;
    user-select: none;
    -ms-user-select: none;
}

.all {
    display: flex;
    flex-flow: column;
    justify-content: space-between;
    width: 100%;
    height: 100%;
    // border: 1px solid red;

    // background-color: pink;
    .all_title {
        display: flex;
        align-items: center;
        justify-content: space-between;
        // padding: 0 40px;
        padding-right: 20px;
        width: 100%;
        // height: 44px;
        color: #A5D8FC;
        font-size: 16px;
        background: url("../../assets/images/smallTitBg.png") no-repeat;
        background-size: 100% 100%;
        height: vh(80);

        .all_title_txt {
            font-size: vh(25);
            transform: translate(vh(40), vh(-20));
        }

        .dateBg {
            width: vh(30);
            height: vh(30);
            transform: translateY(vh(-10));
        }

        // span {
        //     transform: translateY(-8px);
        // }

        .dateBg {
            // width: 25px;
            // height: 25px;
            cursor: pointer;

            &:hover {
                opacity: .8;
            }
        }
    }

    .all_bod {
        display: flex;
        flex-flow: column;
        width: 100%;
        // height: calc(100% - 44px);
        height: calc(100% - vh(80));
    }
}

// 4K 带鱼屏
// @media screen and (max-width: 3840px) and (max-height: 1080px) {
//     .all_title_txt {
//         font-size: 28px;
//         transform: translate(50px, -20px);
//     }

//     .today_tit {
//         font-size: 30px;
//     }

//     .all_title {
//         height: 80px;
//     }

//     .all_bod {
//         height: calc(100% - 80px) !important;
//     }

//     .dateBg {
//         width: 35px;
//         height: 35px;
//         transform: translateY(-10px);
//     }
// }

// // 4K
// @media screen and (max-width: 3840px) and (min-height: 1081px) {
//     .all_title_txt {
//         font-size: 50px;
//         transform: translate(80px, -20px);
//     }

//     .today_tit {
//         font-size: 50px;
//     }

//     .all_title {
//         height: 100px;
//     }

//     .all_bod {
//         height: calc(100% - 100px) !important;
//     }

//     .dateBg {
//         width: 55px;
//         height: 55px;
//         transform: translateY(-15px);
//     }
// }

// // 2K
// @media screen and (max-width: 2560px) {
//     .all_title_txt {
//         font-size: 35px;
//         transform: translate(70px, -20px);
//     }

//     .today_tit {
//         font-size: 32px;
//     }

//     .all_title {
//         height: 100px;
//     }

//     .all_bod {
//         height: calc(100% - 100px) !important;
//     }


//     .dateBg {
//         width: 40px;
//         height: 40px;
//         transform: translateY(-15px);
//     }
// }

// // 全高清屏幕
// @media screen and (max-width: 1920px) {
//     .all_title_txt {
//         font-size: 16px;
//         transform: translate(30px, -10px);
//     }

//     .today_tit {
//         font-size: 16px;
//     }

//     .all_title {
//         height: 50px;
//     }

//     .all_bod {
//         height: calc(100% - 50px) !important;
//     }

//     .dateBg {
//         width: 25px;
//         height: 25px;
//         transform: translateY(-5px);
//     }
// }

// // 14寸笔记本
// @media screen and (max-width: 1366px) {
//     .all_title_txt {
//         font-size: 14px;
//         transform: translate(30px, -10px);
//     }

//     .today_tit {
//         font-size: 16px;
//     }

//     .all_title {
//         height: 50px;
//     }

//     .all_bod {
//         height: calc(100% - 50px) !important;
//     }

//     .dateBg {
//         width: 20px;
//         height: 20px;
//         transform: translateY(-5px);
//     }
// }</style>

 

3.这样你可以在.vue文件中直接使用this.fitChartSize()调用

<template>
  <div class="chartsdom" ref="chart" v-chart-resize></div>
</template>

<script>
export default {
  name: "dashboardChart",
  data() {
    return {
      option: null,
    };
  },
  mounted() {
    this.getEchart();
  },
  methods: {
    getEchart() {
      let myChart = this.$echarts.init(this.$refs.chart);
      const option = {
        backgroundColor: "transparent",
        tooltip: {
          trigger: "item",
          formatter: "{a} <br/>{b} : {c}%",
        },
        grid: {
          left: this.fitChartSize(10),
          right: this.fitChartSize(20),
          top: this.fitChartSize(20),
          bottom: this.fitChartSize(10),
          containLabel: true,
        },
        calculable: true,
        series: [
          {
            color: ["#0db1cdcc"],
            name: "计划投入",
            type: "funnel",
            width: "45%",
            height: "70%",
            x: "5%",

            minSize: "10%",
            funnelAlign: "right",

            center: ["50%", "50%"], // for pie

            data: [
              {
                value: 30,
                name: "下单30%",
              },
              {
                value: 55,
                name: "咨询55%",
              },
              {
                value: 65,
                name: "点击65%",
              },
              {
                value: 60,
                name: "访问62%",
              },
              {
                value: 80,
                name: "展现80%",
              },
            ].sort(function (a, b) {
              return a.value - b.value;
            }),
            roseType: true,
            label: {
              normal: {
                formatter: function () {},
                position: "inside",
              },
            },
            itemStyle: {
              normal: {
                borderWidth: 0,
                shadowBlur: this.fitChartSize(20),
                shadowOffsetX: 0,
                shadowOffsetY: this.fitChartSize(5),
                shadowColor: "rgba(0, 0, 0, 0.3)",
              },
            },
          },

          {
            color: ["#0C66FF"],
            name: "实际投入",
            type: "funnel",
            width: "45%",
            height: "70%",
            x: "50%",

            minSize: "10%",
            funnelAlign: "left",

            center: ["50%", "50%"], // for pie

            data: [
              {
                value: 35,
                name: "下单35%",
              },
              {
                value: 40,
                name: "咨询40%",
              },
              {
                value: 70,
                name: "访问70%",
              },
              {
                value: 90,
                name: "点击90%",
              },
              {
                value: 95,
                name: "展现95%",
              },
            ].sort(function (a, b) {
              return a.value - b.value;
            }),
            roseType: true,
            label: {
              normal: {
                position: "inside",
              },
            },
            itemStyle: {
              normal: {
                borderWidth: 0,
                shadowBlur: this.fitChartSize(20),
                shadowOffsetX: 0,
                shadowOffsetY: this.fitChartSize(5),
                shadowColor: "rgba(0, 0, 0, 0.3)",
              },
            },
          },
        ],
      };
      myChart.setOption(option, true);
    },
  },
  beforeDestroy() {},
};
</script>

<style lang="scss" scoped>
.chartsdom {
  width: 100%;
  height: 100%;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web网页精选

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值