如何触发包含三个重叠 div 元素的 :hover 过渡(维恩图)

How can I trigger a :hover transition that includes three overlapping div elements (Venn diagram)

我的问题是我有这个由三个 div 元素组成的维恩图,我想用 :hover 缩放它们,这样当我将鼠标悬停在一个交叉点上时,所有在交叉点缩放到我定义的值。目前我只得到一个圈来缩放。

.circles-container {
  position: relative;
  width: 45.625rem;
  height: 45.625rem;
}

.circle-blue {
  position: absolute;
  left: 0rem;
  top: 0rem;
  width: 28.4375rem;
  height: 28.4375rem;
  background-color: rgba(187, 231, 254, 0.6);
  border-radius: 50%;
}

.circle-purple {
  position: absolute;
  right: 0rem;
  top: 0rem;
  width: 28.4375rem;
  height: 28.4375rem;
  background-color: rgba(211, 181, 229, 0.6);
  border-radius: 50%;
}

.circle-pink {
  position: absolute;
  right: 8.59375rem;
  left: 8.59375rem;
  bottom: 0rem;
  width: 28.4375rem;
  height: 28.4375rem;
  background-color: rgba(255, 212, 219, 0.6);
  border-radius: 50%;
}

.second-section-circle {
  transition: all, 1s;
}

.second-section-circle:hover {
  transform: scale(1.1);
}
<div class="circles-container">
  <div class="circle-blue second-section-circle"></div>
  <div class="circle-purple second-section-circle"></div>
  <div class="circle-pink second-section-circle"></div>
</div>

你可以做到这一点,但你需要一点 JavaScript。别担心,没有什么太复杂的。你可以做的是使用 element.getBoundingClientRect() 方法获取每个圆的尺寸,就像这样...

let blue = document.querySelector(".circle-blue").getBoundingClientRect();
let purple = document.querySelector(".circle-purple").getBoundingClientRect();
let pink = document.querySelector(".circle-pink").getBoundingClientRect();

然后每次用户移动鼠标时,您可以测试鼠标是否在给定元素上,如果是,您可以缩放它,而不管哪个元素与另一个元素重叠,因此导致任何圆圈缩放,包括交叉点中包含的圆...

let blue = document.querySelector(".circle-blue").getBoundingClientRect();
let purple = document.querySelector(".circle-purple").getBoundingClientRect();
let pink = document.querySelector(".circle-pink").getBoundingClientRect();

window.addEventListener("mousemove", (e) => {
  let x = e.pageX,y = e.pageY;

  //test blue...
  if (x > blue.left && x < blue.right && y > blue.top && y < blue.bottom) {
    // if mouse is over element, scale it...
    document.querySelector(".circle-blue").style.transform = "scale(1.2)";
  } else {
    // otherwise, dont scale it...
    document.querySelector(".circle-blue").style.transform = "scale(1)";
  }

  //test purple...
  if (x > purple.left && x < purple.right && y > purple.top && y < purple.bottom) {
    // if mouse is over element, scale it...
    document.querySelector(".circle-purple").style.transform = "scale(1.2)";
  } else {
    // otherwise, dont scale it...
    document.querySelector(".circle-purple").style.transform = "scale(1)";
  }

  //test pink...
  if (x > pink.left && x < pink.right && y > pink.top && y < pink.bottom) {
    // if mouse is over element, scale it...
    document.querySelector(".circle-pink").style.transform = "scale(1.2)";
  } else {
    // otherwise, dont scale it...
    document.querySelector(".circle-pink").style.transform = "scale(1)";
  }
});
.circles-container {
  position: relative;
  width: 45.625rem;
  height: 45.625rem;
}

.circle-blue {
  position: absolute;
  left: 0rem;
  top: 0rem;
  width: 28.4375rem;
  height: 28.4375rem;
  background-color: rgba(187, 231, 254, 0.6);
  border-radius: 50%;
}

.circle-purple {
  position: absolute;
  right: 0rem;
  top: 0rem;
  width: 28.4375rem;
  height: 28.4375rem;
  background-color: rgba(211, 181, 229, 0.6);
  border-radius: 50%;
}

.circle-pink {
  position: absolute;
  right: 8.59375rem;
  left: 8.59375rem;
  bottom: 0rem;
  width: 28.4375rem;
  height: 28.4375rem;
  background-color: rgba(255, 212, 219, 0.6);
  border-radius: 50%;
}

.second-section-circle {
  transition: all, 1s;
}
<div class="circles-container">
  <div class="circle-blue second-section-circle"></div>
  <div class="circle-purple second-section-circle"></div>
  <div class="circle-pink second-section-circle"></div>
</div>

我完成了 ,这样圆圈就会对越过它们的边界做出反应,而不是它们周围描述的正方形的边界。

并且还添加了辅助函数和循环,以免手动列出图中的所有圆圈。现在脚本代码不依赖于图中的圆圈数。

https://codepen.io/glebkema/pen/OJjNwzd

let circlesElements = document.getElementsByClassName("second-section-circle");
let circlesInfo = [];

for (let elem of circlesElements) {
    circlesInfo.push(getCircleInfo(elem));
}

// console.log(circlesInfo);

window.addEventListener("mousemove", (e) => {
    for (let info of circlesInfo) {
        let deltaX = e.pageX - info.centerX;
        let deltaY = e.pageY - info.centerY;
        if (deltaX * deltaX + deltaY * deltaY <= info.radius2) {
            // if mouse is over element, scale it...
            info.elem.style.transform = "scale(1.2)";
        } else {
            // otherwise, dont scale it...
            info.elem.style.transform = "scale(1)";
        }
    }
});

function getCircleInfo(elem) {
    let rect = elem.getBoundingClientRect();
    let radius = (rect.right - rect.left) / 2;
    return {
        elem: elem,
        centerX: (rect.right + rect.left) / 2,
        centerY: (rect.bottom + rect.top) / 2,
        radius2: radius * radius
    };
}
.circles-container {
    position: relative;
    width: 45.625rem;
    height: 45.625rem;
}

.second-section-circle {
    position: absolute;
    width: 28.4375rem;
    height: 28.4375rem;
    border-radius: 50%;
    transition: all, 1s;
}

.circle-blue {
    left: 0rem;
    top: 0rem;
    background-color: rgba(187, 231, 254, 0.6);
}

.circle-pink {
    right: 8.59375rem;
    left: 8.59375rem;
    bottom: 0rem;
    background-color: rgba(255, 212, 219, 0.6);
}

.circle-purple {
    right: 0rem;
    top: 0rem;
    background-color: rgba(211, 181, 229, 0.6);
}
<div class="circles-container">
    <div class="second-section-circle circle-blue"></div>
    <div class="second-section-circle circle-purple"></div>
    <div class="second-section-circle circle-pink"></div>
</div>

一个 CSS 唯一的解决方案,它需要更多元素和一个 CSS 变量来控制大小:

.circles-container {
  --s:150px; /* adjust this to control the size*/
  width:  var(--s);
  height: var(--s);
  margin:calc(var(--s)/3) auto;
  display:grid;
}
.circles-container > * {
  grid-area: 1/1;
  transition: all 1s;
  border-radius:50%;
  position:relative;
}
.circle-blue {
  background: rgba(187, 231, 254, 0.6);
  top:calc(var(--s)/3);
}
.circle-purple {
  background: rgba(211, 181, 229, 0.6);
  left:calc(0.866*calc(var(--s)/3));
  top: calc(-0.5 *calc(var(--s)/3));
}
.circle-pink {
  background: rgba(255, 212, 219, 0.6);
  right:calc(0.866*calc(var(--s)/3));
  top:  calc(-0.5 *calc(var(--s)/3));
}
.circles-container > *:nth-child(1) {
   top:calc(var(--s)/3);
   clip-path:circle(calc(var(--s)/2) at 21% 0%);
}
.circles-container > *:nth-child(2) {
   right:calc(0.866*calc(var(--s)/3));
   top:  calc(-0.5 *calc(var(--s)/3));
   clip-path:circle(calc(var(--s)/2) at 108% 50%);
}
.circles-container > *:nth-child(3) {
   left:calc(0.866*calc(var(--s)/3));
   top: calc(-0.5 *calc(var(--s)/3));
   clip-path:circle(calc(var(--s)/2) at 21% 100%);
}
.circles-container > *:nth-child(4) {
  clip-path: polygon(29% 38%, 50% 34%, 71% 38%, 64% 60%, 50% 74%, 36% 60%);
}
.circles-container > *:nth-child(-n + 4) {
  z-index:1;
}
.circles-container > *:nth-child(1):hover ~ .circle-pink,
.circles-container > *:nth-child(1):hover ~ .circle-blue,
.circles-container > *:nth-child(2):hover ~ .circle-pink,
.circles-container > *:nth-child(2):hover ~ .circle-purple,
.circles-container > *:nth-child(3):hover ~ .circle-blue,
.circles-container > *:nth-child(3):hover ~ .circle-purple,
.circles-container > *:nth-child(4):hover ~ *,
.circles-container > *:nth-child(n + 5):hover {
  transform: scale(1.15);
}
<div class="circles-container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  
  <div class="circle-blue"></div>
  <div class="circle-purple"></div>
  <div class="circle-pink"></div>
</div>

为额外的 div 添加背景颜色以理解拼图:

.circles-container {
  --s:150px; /* adjust this to control the size*/
  width:  var(--s);
  height: var(--s);
  margin:calc(var(--s)/3) auto;
  display:grid;
}
.circles-container > * {
  grid-area: 1/1;
  transition: all 1s;
  border-radius:50%;
  position:relative;
}
.circle-blue {
  background: rgba(187, 231, 254, 0.6);
  top:calc(var(--s)/3);
}
.circle-purple {
  background: rgba(211, 181, 229, 0.6);
  left:calc(0.866*calc(var(--s)/3));
  top: calc(-0.5 *calc(var(--s)/3));
}
.circle-pink {
  background: rgba(255, 212, 219, 0.6);
  right:calc(0.866*calc(var(--s)/3));
  top:  calc(-0.5 *calc(var(--s)/3));
}
.circles-container > *:nth-child(1) {
   top:calc(var(--s)/3);
   clip-path:circle(calc(var(--s)/2) at 21% 0%);
}
.circles-container > *:nth-child(2) {
   right:calc(0.866*calc(var(--s)/3));
   top:  calc(-0.5 *calc(var(--s)/3));
   clip-path:circle(calc(var(--s)/2) at 108% 50%);
}
.circles-container > *:nth-child(3) {
   left:calc(0.866*calc(var(--s)/3));
   top: calc(-0.5 *calc(var(--s)/3));
   clip-path:circle(calc(var(--s)/2) at 21% 100%);
}
.circles-container > *:nth-child(4) {
  clip-path: polygon(29% 38%, 50% 34%, 71% 38%, 64% 60%, 50% 74%, 36% 60%);
}
.circles-container > *:nth-child(-n + 4) {
  z-index:1;
}
.circles-container > *:nth-child(1):hover ~ .circle-pink,
.circles-container > *:nth-child(1):hover ~ .circle-blue,
.circles-container > *:nth-child(2):hover ~ .circle-pink,
.circles-container > *:nth-child(2):hover ~ .circle-purple,
.circles-container > *:nth-child(3):hover ~ .circle-blue,
.circles-container > *:nth-child(3):hover ~ .circle-purple,
.circles-container > *:nth-child(4):hover ~ *,
.circles-container > *:nth-child(n + 5):hover {
  transform: scale(1.15);
}
<div class="circles-container">
  <div style="background:red;"></div>
  <div style="background:green;"></div>
  <div style="background:purple;"></div>
  <div style="background:black;"></div>
  
  <div class="circle-blue"></div>
  <div class="circle-purple"></div>
  <div class="circle-pink"></div>
</div>