Обрезка по фигуру

Рейтинг: 1Ответов: 2Опубликовано: 01.02.2023

Описание

Есть такая конструкция:

body {
  background-color: lightgrey;
}

div {
  display: flex;
  box-sizing: border-box;
  margin: 0;
  background-color: white;
  border: 2px solid grey;
}
<div style="position: relative; width: 100px; height: 100px; align-items: center;">
  <div style="width: 75px; height: 75px; position: absolute; right: -37.5px; padding: 8px; border-radius: 50%; background-color: orange;">
    <div style="width: 100%; height: 100%; border-radius: inherit;"></div>
  </div>
</div>

Вопрос

Каким способом можно вырезать оранжевую часть так, чтобы остались только белые части?
Примерно вот так:

Дополнение

Попробовал с background-clip, clip-path. Оранжевая часть вырезается, но белый квадрат сзади остается. Получается вот так:

И ещё одно уточнение

Сверху — упрощенный пример этого сайта. Пример может не включать себе некоторые детали, которые рассмотрены в сайте, ведь это минимальный запускаемый пример. Просьба, предложить такие решения которые можно реализовать в сайте.

Ответы

▲ 4Принят

// for demo

[...document.querySelectorAll('#control input')].map(el => {
  ['change', 'mousemove'].map(event_name => {
    el.addEventListener(event_name, ({target}) => {
      document.querySelector('.block').style.setProperty('--'+target.id, target.value+'%');
      document.querySelector(`label[for="${target.id}"]`).dataset.val = target.value;
    });
  });
});
/* for demo */
#control {color: #fff; font-family: monospace; position: fixed; left: 0; top: 0; z-index: 1;}
label {display: flex; align-items: center;}
label:not(:last-child) {margin-bottom: 20px;}
label::after {content: attr(data-val)'%'; display: inline;}
input {width: 100px; margin: 0 5px;}
body {display: flex; justify-content: center; align-items: center; min-height: 100vh; background: url(https://i.imgur.com/HYAdZOO.png) no-repeat center center / cover; margin: 0; overflow: hidden;}
/* /for demo */

.block {
  --x: 0;
  --y: 0;
  --stroke: 10px;
  --size: 60px;

  display: block;
  width: 200px;
  height: 200px;
  position: relative;
}

.block .mask {
  display: block;
  width: 100%;
  height: 100%;
  -webkit-border-radius: 10px;
          border-radius: 10px;
  background-color: #fff;
  -webkit-mask-image:
    -webkit-radial-gradient(var(--x) var(--y),
      circle,
      transparent -webkit-calc(var(--size) / 2 + var(--stroke)),
      white -webkit-calc(var(--size) / 2 + var(--stroke) + 1px)
    );
  mask-image:
    radial-gradient(circle at var(--x) var(--y),
      transparent -moz-calc(var(--size) / 2 + var(--stroke)),
      white -moz-calc(var(--size) / 2 + var(--stroke) + 1px)
    );
  mask-image:
    radial-gradient(circle at var(--x) var(--y),
      transparent calc(var(--size) / 2 + var(--stroke)),
      white calc(var(--size) / 2 + var(--stroke) + 1px)
    );
  position: absolute;
  left: 0;
  top: 0;
}

.block .image {
  display: block;
  width: var(--size);
  height: var(--size);
  -webkit-border-radius: 50%;
          border-radius: 50%;
  background-color: red;
  padding: 5px;
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
  position: absolute;
  left: var(--x);
  top: var(--y);
  -webkit-transform: translate(-50%, -50%);
     -moz-transform: translate(-50%, -50%);
      -ms-transform: translate(-50%, -50%);
       -o-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}
<!-- for demo -->
<div id="control">
  <label for="x" data-val="0">X <input id="x" type="range" min="0" max="100%" value="0"></label>
  <label for="y" data-val="0">Y <input id="y" type="range" min="0" max="100%" value="0"></label>
</div>
<!-- /for demo -->

<div class="block">
  <div class="mask"></div>
  <div class="image">
    <img src="https://i.imgur.com/LjYw4LU.gif" width="50">
  </div>
</div>

Использую mask'у, фигуру задаю такую же, как .image, в нашем случае это круг - для этого использую radial-gradient, размер этого круга такой же как размер .image + область "под вырез" (переменная --stroke).

Позиционирую как mask'у, так и .image относительно .block (переменные --x и --y), так же .image смещён через transform.

.mask и .image лежат на одном уровне, т.к. если вложить .image в .mask, то .image будет обрезаться mask'ой.

▲ 0

Ну я так смог только решить эту проблему
В --bs-color я вписал цвет заднего фона и вывожу потом задний фон и outer-round через переменную

--bs-color: white;

body {
  background-color: lightgrey;
}

div {
  display: flex;
  box-sizing: border-box;
  margin: 0;
  background-color: white;
  border: 2px solid grey;
}
.outer-round {
  width: 75px;
  height: 75px;
  position: absolute;
  right: -37.5px;
  padding: 10px;
  border-radius: 50%;
  background-color: --bs-color;
  border-bottom: 2px solid grey;
  border-right: 2px solid transparent;
  border-left: 2px solid grey;
  border-top: 2px solid transparent;
  transform:rotate(45deg);
}
<div style="position: relative; width: 100px; height: 100px; align-items: center;">
  <div class="outer-round">
    <div class="inner-round" style="width: 100%; height: 100%; border-radius: inherit;"></div>
  </div>
</div>