当前位置: 首页 > news >正文

带Label的韦恩图(vue)

韦恩图

效果:
在这里插入图片描述

实现:
图形使用venn.jsd3.js绘制
label使用元素定位绘制(可根据数据动态计算)

代码:

  1. tempalte
  <div class="venn mgt-4 center-flex" v-else ref="vennBox" style="height: 140px;">
              <div class="venn-right" :style="{ left: lengedPos.rightX + 'px' }" ref="vennRight">
                <p class="color-666 fs-12 ellipsis lh-17">XXXX</p>
                <p class="lh-20">720人</p>
              </div>


              <div class="venn-left" :style="{ right: lengedPos.leftX + 'px' }" ref="vennRight">
                <p class="color-666 fs-12 ellipsis lh-17">XXX</p>
                <p class="lh-20">720人</p>
              </div>


              <div class="venn-bottom flex-align" ref="vennBottom">
                <div class="venn-text">
                  <p class="color-666 fs-12 lh-17">XXXX</p>
                  <p class="lh-20">720人</p>
                </div>
                <img src="@/assets/img/dataApplication/bottom.png" />

              </div>
              <div ref="vennContainer" class="venn-container" style="width: 325px;height: 120px;"></div>
            </div>
  1. script
import * as d3 from 'd3';
import { VennDiagram } from 'venn.js';

  data() {
    return {

      intersectionNum: 20,
      lengedPos: {
        rightX: 0,
        leftX: 0
      },

    };
  },
 mounted() {
        this.$nextTick(() => {
          setTimeout(() => {
            this.renderVennDiagram()
          }, 100);
        })
  },

  methods: {
    renderVennDiagram() {
      const container = this.$refs.vennContainer;
      // 数据
      const sets = [
        { sets: ['A'], size: 100, label: 'A' },
        { sets: ['B'], size: 100, label: 'B' },
        { sets: ['A', 'B'], size: this.intersectionNum, label: 'A ∩ B' }
      ];
      // 绘制韦恩图
      const chart = VennDiagram().styled(false).width(325).height(120);
      const svg = d3.select(container).append('svg')
        .attr('width', 325)
        .attr('height', 120);

      svg.datum(sets).call(chart);

      this.$nextTick(() => {
        const gElement = document.querySelector('g.venn-area.venn-circle[data-venn-sets="B"]');
        const gRect = gElement.getBoundingClientRect();
        const parentRect = this.$refs.vennBox.getBoundingClientRect();
        this.lengedPos.rightX = gRect.left - parentRect.left + gRect.width + 2;
        const gAElement = document.querySelector('g.venn-area.venn-circle[data-venn-sets="A"]');
        const gARect = gAElement.getBoundingClientRect();
        this.lengedPos.leftX = parentRect.right - gARect.left + 0
      })
    },
  1. style

::v-deep .venn-container {
  >svg {
    transform: scaleY(0.95);
  }

  g {
    position: relative;
  }

  svg {
    text {
      fill: transparent;
      display: none;
    }
  }

  [data-venn-sets="A"] {
    fill: #1083FB;
  }

  [data-venn-sets="B"] {
    fill: #6CD3FF;
  }

  [data-venn-sets="A_B"] {
    fill: #FFC300;

    path {
      stroke: white;
      stroke-width: 2px;
    }
  }

}

.venn {
  position: relative;

  &-left {
    position: absolute;
    top: 15px;

    &::after {
      content: '';
      position: absolute;
      right: -17.23px;
      background: url(~@/assets/img/dataApplication/left.png) center/100% 100% no-repeat;
      top: 50%;
      transform: translateY(-50%);
      width: 17.23px;
      height: 4.8px;
    }
  }


  &-right {
    position: absolute;
    top: 15px;

    &::before {
      content: '';
      position: absolute;
      left: -21.06px;
      background: url(~@/assets/img/dataApplication/right.png) center/100% 100% no-repeat;
      top: 50%;
      transform: translateY(-50%);
      width: 21.06px;
      height: 4.8px;
    }
  }

  &-bottom {
    position: absolute;
    left: 50%;
    transform: translateX(-100%) translateY(100%);
    bottom: 37px;

    .venn-text {
      position: absolute;
      left: 0;
      top: -3px;
    }

    img {
      width: 84px;
      height: 20px;
    }

    &::after {
      width: 84px;
      height: 20px;
      display: inline-block;
      background: url(~@/assets/img/dataApplication/bottom.png) center/100% 100% no-repeat;
      content: '';
      position: absolute;
      right: 0;
    }

    .venn-text {
      position: absolute;
      left: 0;
      transform: translateX(-100%);
    }
  }
}

相关文章:

  • 【Java】Maven
  • 【软件测试】自动化测试结合 CI/CD有哪些方案
  • Oracle 数据库查询表广播
  • 青蛙吃虫--dp
  • 【蓝桥杯】动态规划:线性动态规划
  • PhotoShop学习07
  • PostIn V1.0.8版本发布,IDEA 插件支持一键扫描上报,让接口定义不再繁琐
  • leetcode刷题记录44-208. 实现 Trie (前缀树)
  • 指针本质传递偏移动态申请空间 c语言(day05)
  • excel常见错误包括(#N/A、#VALUE!、#REF!、#DIV/0!、#NUM!、#NAME?、#NULL! )
  • 【蓝桥杯】动态规划:背包问题
  • 23种设计模式-行为型模式-模板方法
  • AtCoder 第400场初级竞赛 A~E题解
  • Redis客户端命令到服务器底层对象机制的完整流程?什么是Redis对象机制?为什么要有Redis对象机制?
  • 子串分值和(蓝桥杯)
  • 【MySQL 数据库】数据类型
  • Everything 安装教程与使用教程(附安装包)
  • java+postgresql+swagger-多表关联insert操作(七)
  • 流体力学笔记
  • 体验为王:云化园区网络如何重塑用户业务零卡顿时代
  • “GoFun出行”订单时隔7年扣费后续:平台将退费,双方已和解
  • 中方是否计划解除或调整稀土出口管制?外交部回应
  • 美官方将使用华为芯片视作违反美出口管制行为,外交部回应
  • “9+2”复式票,浦东购彩者拿下体彩大乐透1153万头奖
  • 讲座|消逝之钟:《红楼梦》与《布登勃洛克一家》中的时间观
  • 会谈时间迟迟未定、核心议题存在分歧,俄乌“土耳其谈判”一波三折