CSS — Как изменить фон пересечения двух объектов?

#html #css #css-shapes

#HTML #css #css-фигуры

Вопрос:

Я пытаюсь воспроизвести стиль этой анимации, но я не знаю, как «заполнить» цвет фона пересечения этих двух фигур. В анимации пересечение удобно пошаговое и останавливается там, где край квадрата пересекается с началом круга; Я могу представить, как использовать обтравочную маску для заполнения этого квадранта круга. Однако возможно ли сделать то же самое более динамично? Можете ли вы заполнить фон двух пересекающихся фигур (при этом сохраняя прозрачный фон в другом месте)?

 .shape-interconnected {
     width: 400px;
     height: 300px;
     position: relative;
     background-color: black;
     color: white;
     margin: 1rem;
     border-radius: 4px;
}
 .shape-interconnected > .square, .shape-interconnected > .circle {
     width: 50px;
     height: 50px;
     position: absolute;
     border: 5px solid white;
     transform: translate(-50%, -50%);
}
 .shape-interconnected > .square {
     border-radius: 4px;
     top: 45%;
     left: 55%;
}
 .shape-interconnected > .circle {
     border-radius: 50%;
     top: 55%;
     left: 45%;
}
  
 <div class="shape-interconnected">
  <div class="square"></div>
  <div class="circle"></div>
</div> 

Ответ №1:

Вы можете воссоздать дриблинг, используя html с небольшим псевдо css и анимационной магией.

Приведенный ниже пример работает с любым набором переменных css size border , определенным в корневых переменных css.

 :root {
  --size: 250px;
  --border: 5px;
}
 

Хитрость в моем примере заключается в использовании позиционирования в процентах, что означает, что родительский .shape-interconnected элемент, контролируемый переменной css size , определяет положение всех дочерних и дочерних псевдоэлементов.

Здесь нужно много объяснений по css, я добавил комментарии в css, посмотрите, вдохновит ли это вас, чтобы вы попали туда, куда вам нужно…

Вот скрипка… https://jsfiddle.net/joshmoto/378Lcgp0 /

 /* our root css vars */
:root {
  --size: 250px;
  --border: 5px;
}

BODY {
  background: black;
  min-height: 100%;
}

/* reset our box sizing on psuedo elems */
*, ::after, ::before {
    box-sizing: border-box;
}

/* our shape intersect container positioned center of window */
/* this can be positioned where ever you want */
.shape-interconnected {
  background: black;
  width: var(--size);
  height: var(--size);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  animation: shape-interconnected 2s infinite;
}

/* animate height and width equally  */
@keyframes shape-interconnected {
  0% {
    width: var(--size);
    height: var(--size);
  }
  50% {
    width: calc(var(--size) * 0.6);
    height: calc(var(--size) * 0.6);
  }
  100% {
    width: var(--size);
    height: var(--size);
  }
}

/* our square calculated at 40% of parent */
/* position and overflow hidden are key, hiding pseudo child elems */
.shape-interconnected > .square {
  width: calc(var(--size) * 0.4);
  height: calc(var(--size) * 0.4);
  background: transparent;
  position: absolute;
  overflow: hidden;
  right: 0;
  top: 0;
}

/* our square before pseudo elem emulating inner white filled circle */
/* position absolute with animation keyframes */
.shape-interconnected > .square::before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: #fff;
  border-radius: 50%;
  position: absolute;
  animation: circle-interconnected 2s infinite;
}

/* start top/right 150% away, overflowing out of view */
/* 50% keyframe top/right 50% away, in view */
@keyframes circle-interconnected {
  0% {
    top: 150%;
    right: 150%;
  }
  50% {
    top: 50%;
    right: 50%;
  }
  100% {
    top: 150%;
    right: 150%;
  }
}

/* our square after pseudo elem emulating white border */
.shape-interconnected > .square::after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  border: var(--border) solid white;
  position: relative;
}

/* our circle calculated at 40% of parent */
.shape-interconnected > .circle {
  width: calc(var(--size) * 0.4);
  height: calc(var(--size) * 0.4);
  position: absolute;
  bottom: 0;
  left: 0;
}

/* our circle after pseudo elem emulating white border */
.shape-interconnected > .circle::after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  border: var(--border) solid white;
  border-radius: 50%;
  position: relative;
} 
 <div class="shape-interconnected">
  <div class="square"></div>
  <div class="circle"></div>
</div> 

Вот еще один пример, использующий тот же код, что и выше, но с этими настройками корневой переменной css…

 :root {
  --size: 500px;
  --border: 2px;
}
 

Живой пример ниже…

 /* our root css vars */
:root {
  --size: 500px;
  --border: 2px;
}

BODY {
  background: black;
  min-height: 100%;
}

/* reset our box sizing on psuedo elems */
*, ::after, ::before {
    box-sizing: border-box;
}

/* our shape intersect container positioned center of window */
/* this can be positioned where ever you want */
.shape-interconnected {
  background: black;
  width: var(--size);
  height: var(--size);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  animation: shape-interconnected 2s infinite;
}

/* animate height and width equally  */
@keyframes shape-interconnected {
  0% {
    width: var(--size);
    height: var(--size);
  }
  50% {
    width: calc(var(--size) * 0.6);
    height: calc(var(--size) * 0.6);
  }
  100% {
    width: var(--size);
    height: var(--size);
  }
}

/* our square calculated at 40% of parent */
/* position and overflow hidden are key, hiding pseudo child elems */
.shape-interconnected > .square {
  width: calc(var(--size) * 0.4);
  height: calc(var(--size) * 0.4);
  background: transparent;
  position: absolute;
  overflow: hidden;
  right: 0;
  top: 0;
}

/* our square before pseudo elem emulating inner white filled circle */
/* position absolute with animation keyframes */
.shape-interconnected > .square::before {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: #fff;
  border-radius: 50%;
  position: absolute;
  animation: circle-interconnected 2s infinite;
}

/* start top/right 150% away, overflowing out of view */
/* 50% keyframe top/right 50% away, in view */
@keyframes circle-interconnected {
  0% {
    top: 150%;
    right: 150%;
  }
  50% {
    top: 50%;
    right: 50%;
  }
  100% {
    top: 150%;
    right: 150%;
  }
}

/* our square after pseudo elem emulating white border */
.shape-interconnected > .square::after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  border: var(--border) solid white;
  position: relative;
}

/* our circle calculated at 40% of parent */
.shape-interconnected > .circle {
  width: calc(var(--size) * 0.4);
  height: calc(var(--size) * 0.4);
  position: absolute;
  bottom: 0;
  left: 0;
}

/* our circle after pseudo elem emulating white border */
.shape-interconnected > .circle::after {
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  border: var(--border) solid white;
  border-radius: 50%;
  position: relative;
} 
 <div class="shape-interconnected">
  <div class="square"></div>
  <div class="circle"></div>
</div> 

Комментарии:

1. Приятно, спасибо @joshmoto! Просто чтобы перевести в открытый текст мое понимание, мы настраиваем .square::before как круг на белом фоне с идентичной позицией и анимацией as .circle . Эффект «пересечения» возникает из overflow:hidden свойства on .square .

2. @PhilGresham в ореховой скорлупе да. Используя проценты для позиций и shape-interconnected div в качестве контейнера, который изменяет размер. Оба cicle и square divs расположены абсолютно в противоположных углах внутри shape-interconnected .

Ответ №2:

Вы можете добавить белый круг внутри квадрата и расположить его в тех же координатах, что и прозрачный.
Установите overflow: hidden квадрат, чтобы скрыть внешнюю часть белого круга:

 .shape-interconnected {
  width: 400px;
  height: 300px;
  position: relative;
  background-color: black;
  color: white;
  margin: 1rem;
  border-radius: 4px;
  --animation-props: 1s alternate linear infinite;
}

.shape-interconnected>.square,
.shape-interconnected>.square:before,
.shape-interconnected>.circle {
  width: 50px;
  height: 50px;
  position: absolute;
  border: 5px solid white;
  transform: translate(-50%, -50%)
}

.shape-interconnected>.square {
  top: 35%;
  left: 65%;
  border-radius: 4px;
  overflow: hidden;
  animation: for_square var(--animation-props);
}

.shape-interconnected>.circle {
  top: 65%;
  left: 35%;
  border-radius: 50%;
  animation: for_transparent_circle var(--animation-props);
}

.shape-interconnected>.square:before {
  content: '';
  border-radius: 50%;
  background: #fff;
  top: 230%;
  left: -190%;
  animation: for_white_circle var(--animation-props);
}

@keyframes for_square {
  to {
    top: 50%;
    left: 55%;
  }
}

@keyframes for_transparent_circle {
  to {
    top: 55%;
    left: 50%;
  }
}

@keyframes for_white_circle {
  to {
    top: 80%;
    left: 10%;
  }
} 
 <div class="shape-interconnected">
  <div class="square"></div>
  <div class="circle"></div>
</div>