【组件设计】漏斗图

624 阅读1分钟

漏斗图

为了解决还原设计稿上的漏斗图,并两边附带数据对比,尽可能地用Echarts实现,且不支持自动排序。

代码配置

<template>
  <div 
    ref="customerStageFunnel" 
    id="customerStageFunnel" 
    style="height: 280px; width: 100%" 
  />
</template>

<script>
// 调用echarts
import echarts from "echarts";
export default {
  props: {
    funnelData: {
      type: Object,
      default: () => ({})
    }
  },
  watch: {
    funnelData: {
      handler(val) {
        if (val && val.left && val.center && val.right) {
          this.$nextTick(() => {
            this.initChart();
          });
        }
      },
      deep: true,
      immediate: true
    }
  },
  data() {
    return {
      img: require("@/assets/qwH5/home/dash.png")
    };
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$refs.customerStageFunnel);
      const option = {
        title: [
          {
            show: true,
            text: "阶段名称(经过此阶段客户数量)",
            left: "center",
            bottom: 0,
            padding: [24, 0, 0, 0],
            textStyle: {
              fontFamily: "PingFangSC-Regular, PingFang SC",
              fontSize: 10,
              fontWeight: 400,
              color: "#999999"
            }
          },
          {
            show: true,
            text: "无意向客户(转化率)",
            left: "left",
            bottom: 0,
            padding: [24, 0, 0, 0],
            textStyle: {
              fontFamily: "PingFangSC-Regular, PingFang SC",
              fontSize: 10,
              fontWeight: 400,
              color: "#999999"
            }
          },
          {
            show: true,
            text: "阶段转化率",
            left: "right",
            bottom: 0,
            padding: [24, 0, 0, 0],
            textStyle: {
              fontFamily: "PingFangSC-Regular, PingFang SC",
              fontSize: 10,
              fontWeight: 400,
              color: "#999999"
            }
          }
        ],
        aria: {
          enabled: true,
          decal: {
            show: true
          }
        },
        tooltip: {
          show: false
        },
        toolbox: {
          show: false
        },
        legend: {
          show: false
        },
        color: [
          "rgba(78, 112, 240, 1)",
          "rgba(78, 112, 240, 0.95)",
          "rgba(78, 112, 240, 0.9)",
          "rgba(78, 112, 240, 0.85)",
          "rgba(78, 112, 240, 0.8)",
          "rgba(78, 112, 240, 0.75)",
          "rgba(78, 112, 240, 0.7)",
          "rgba(78, 112, 240, 0.65)",
          "rgba(78, 112, 240, 0.6)",
          "rgba(78, 112, 240, 0.55)",
          "rgba(78, 112, 240, 0.5)",
          "rgba(78, 112, 240, 0.45)"
        ],
        series: [
          // 版图
          {
            type: "funnel",
            minSize: "30%",
            maxSize: "60%",
            // height:500,
            top: 16,
            bottom: 20,
            // gap: 1,
            z: 3,
            legendHoverLink: false,
            label: {
              position: "inside",
              fontFamily: "PingFangSC-Medium, PingFang SC",
              fontSize: 9,
              fontWeight: "500",
              color: "#fff",
              formatter: function(params) {
                const name =
                  params.name.length > 5
                    ? params.name.slice(0, 4) + "..."
                    : params.name;
                return `${name}(${params.value})`;
              }
              // width: 10,
              // overflow: 'truncate',
              // formatter: '{b}{xx|}({c})',
              // rich: { xx: { padding: [0, 2] } }
            },
            data: this.funnelData.center || [],
            sort: "none"
          },
          // 左边信息
          {
            type: "funnel",
            minSize: "30%",
            maxSize: "30%",
            top: 16,
            bottom: 20,
            left: "-60%",
            // funnelAlign: 'left',
            gap: 2,
            z: 1,
            legendHoverLink: false,
            label: {
              show: true,
              position: "inside",
              color: "#5B5E7B",
              fontSize: 10,
              fontWeight: "400",
              formatter: function(params) {
                const dashed = "{x|}{y|}{x|}{y|}{x|}{y|}{x|}{y|}{x|}{y|}{x|}"; // 手动画虚线
                // const  dataIndex
                const rate = params.data.rate;
                const value = params.data.count;
                return `${value}(${rate})\n${dashed}`;
              },
              rich: {
                x: {
                  width: 5,
                  height: 0.5,
                  backgroundColor: "#E6E6E6",
                  lineHeight: 8
                },
                y: {
                  width: 5,
                  height: 0.5,
                  backgroundColor: "transparent",
                  lineHeight: 8
                }
              }
            },
            labelLine: {
              show: false
            },
            itemStyle: {
              color: "transparent"
            },
            data: this.funnelData.left || [],
            sort: "none"
          },
          {
            type: "funnel",
            minSize: "30%",
            maxSize: "30%",
            top: 16,
            bottom: 20,
            right: "-60%",
            // funnelAlign: 'left',
            gap: 2,
            z: 1,
            legendHoverLink: false,
            label: {
              show: true,
              position: "inside",
              color: "#5B5E7B",
              fontSize: 10,
              fontWeight: "400",
              padding: [0, 8, 0, 0],
              width: 36,
              height: 23,
              lineHeight: 23,
              formatter: function(params) {
                // console.log(params);
                const rate = params.data.rate;
                // const value = params.value;
                return `${rate}`;
              },
              backgroundColor: {
                image: this.img,
                width: 36,
                height: 23
              }
            },
            labelLine: {
              show: false
            },
            itemStyle: {
              color: "transparent"
            },
            data: this.funnelData.right || [],
            sort: "none"
          }
        ]
      };

      this.chart.setOption(option);

      // resize
      if (window.addEventListener) {
        // 所有主流浏览器,除了 IE 8 及更早版本
        window.addEventListener("resize", this.chart.resize);
      } else if (window.attachEvent) {
        // IE 8 及更早版本
        window.attachEvent("onresize", this.chart.resize);
      }
    }
  },
};
</script>

实际效果

ldt.png