clip-path svg работает с изображением, но не с div


person Rob Monhemius    schedule 24.11.2019    source источник
comment
Раздел Совместимость браузера ниже на этой странице. перечисляет элементы HTML как работающие в нескольких браузерах, отличных от MS, но также помечает его как экспериментальный. Ожидайте изменения поведения в будущем. // caniuse.com/#feat=css-clip-path содержит дополнительные примечания на каком уровне поддержки существует в различных браузерах.   -  person 04FS    schedule 24.11.2019
comment
@ 04FS Firefox 70 должен иметь полную поддержку в соответствии с таблицей caniuse. Там тоже не работает пример. Справедливое замечание об экспериментальной фазе. Я сообщу MDN, если все согласны с тем, что это (частично) нереализованная/недокументированная функция.   -  person Rob Monhemius    schedule 24.11.2019
comment
Firefox поддерживает обрезку div с помощью clipPath SVG.   -  person Robert Longson    schedule 24.11.2019
comment
Пожалуйста, измените размер div на width: 300px; height: 300px;   -  person enxaneta    schedule 24.11.2019
comment
@enxaneta Хороший улов. Кажется, что размер пикселя соответствует единице внутри svg :). Если вы опубликуете ответ, я могу принять его и закрыть вопрос;).   -  person Rob Monhemius    schedule 24.11.2019


Ответы (3)


Решением вашей проблемы будет использование clipPathUnits="objectBoundingBox" и построение пути отсечения с размерами от 0 до 1 следующим образом:

#clipped {
  margin:1em;
  width: 100px;
  height: 100px;
  background: black;
  display:inline-block;
  clip-path: url(#cross);
}
#clipped.big{
  width: 200px;
  height: 200px;
}
<div id="clipped"></div>
<div id="clipped" class="big"></div>
<svg viewBox="0 0 1 1">
  
    <clipPath id="cross" clipPathUnits="objectBoundingBox">
       <rect y="0" x="0" width=".4" height=".4"/>
       <rect y="0.6" x="0" width=".4" height=".4"/>
       <rect y="0" x="0.6" width=".4" height=".4"/>
       <rect y="0.6" x="0.6" width=".4" height=".4"/>
    </clipPath>
  
</svg>

person enxaneta    schedule 24.11.2019
comment
а как насчет обратного эффекта? любой способ применить атрибут magic, чтобы скрыть крест и показать другую часть, сохраняя путь клипа таким же простым, как этот? - person Temani Afif; 24.11.2019
comment
Я думаю, нам нужно определить 4 прямоугольника: jsfiddle.net/umd5vLn2? - person Temani Afif; 24.11.2019
comment
ну, вы можете оставить оба. Мне просто интересно, есть ли способ сохранить то же самое и иметь возможность иметь противоположное (например, с маской, где мы можем инвертировать белый и прозрачный) - person Temani Afif; 24.11.2019
comment
И этот ответ, и ответ Темани Афифа кажутся правильными. Решение objectBoundingBox отлично подходит, если вы работаете с изображениями с одинаковым соотношением высоты и ширины. В противном случае существует риск искажения траектории отсечения. В ответе Темани Афиф указано, что размер изображения имеет значение, когда вы не используете objectBoundingBox. Единицы в svg соотносятся с пикселями в div/изображении в этом сценарии. - person Rob Monhemius; 24.11.2019

Как указывает @enxaneta, все дело в размере. Если вы увеличите размер div, вы увидите эффект:

#clipped {
  width: 300px;
  height: 200px;
  background: black;
  clip-path: url(#cross);
}
<div id="clipped"></div>
<svg height="0" width="0">
  <defs>
    <clipPath id="cross">
      <rect y="110" x="137" width="90" height="90"/>
      <rect x="0" y="110" width="90" height="90"/>
      <rect x="137" y="0" width="90" height="90"/>
      <rect x="0" y="0" width="90" height="90"/>
    </clipPath>
  </defs>
</svg>

Или вы можете использовать mask, чтобы получить что-то динамичное. Фокус в том, чтобы иметь 4 белых прямоугольника в каждом углу, а белый цвет означает сделать его видимым

.box {
  width: 100px;
  height: 100px;
  margin:5px;
  background: linear-gradient(red,blue);
  -webkit-mask:
    linear-gradient(white,white) top left,
    linear-gradient(white,white) top right,
    linear-gradient(white,white) bottom left,
    linear-gradient(white,white) bottom right;
  -webkit-mask-size:40% 40%;
  -webkit-mask-repeat:no-repeat;
  -mask:
    linear-gradient(white,white) top left,
    linear-gradient(white,white) top right,
    linear-gradient(white,white) bottom left,
    linear-gradient(white,white) bottom right;
  mask-size:40% 40%;
  mask-repeat:no-repeat;
}
<div class="box"></div>

<div class="box" style="width:200px;height:200px;"></div>

person Temani Afif    schedule 24.11.2019

Clip-path не наследуется. Установление нового пути отсечения: элемент clipPath W3C

Следовательно, мы не получим вырезание дочернего элемента, применив clip-path к родительскому блоку.

Возможно, лучше использовать тег svg <image> вместо <img> и применить к нему clip-path

Используйте div как адаптивный контейнер

.wrapped {
width:25%;
height:25%;
}
#img1 {
clip-path:url(#cross);
}
<div class="wrapped">
<svg  viewBox="0 0 250 250">
  <defs>
    <clipPath id="cross">
      <rect y="110" x="137" width="90" height="90"/>
      <rect x="0" y="110" width="90" height="90"/>
      <rect x="137" y="0" width="90" height="90"/>
      <rect x="0" y="0" width="90" height="90"/>
    </clipPath>
  </defs> 

<image id="img1" width="100%" height="100%" xlink:href="https://upload.wikimedia.org/wikipedia/commons/0/02/SVG_logo.svg"/>

</svg> 

</div>

person Alexandr_TT    schedule 24.11.2019
comment
Можете ли вы уточнить, о каком родительском блоке и дочернем элементе вы говорите. Это элементы внутри svg? В этом случае я бы сомневался, что виноват svg, поскольку тот же svg clipPath работает с изображением. - person Rob Monhemius; 24.11.2019
comment
@RMo ‹div id=clipped› - родительский блок SVG - дочерний элемент Во втором примере - person Alexandr_TT; 24.11.2019
comment
Я не получаю здесь унаследованную часть? у нас нет никаких дочерних и родительских отношений, или я что-то упускаю? - person Temani Afif; 24.11.2019
comment
@Temani Afif В ссылке на w3C, которую я указал, написано однозначно clip-path: inherit NO Как я понял из примеров, ОП хотел применить clip-path к div, внутри которого будет располагаться изображение Возможно, я поспешил предугадать пожелания ОП :) - person Alexandr_TT; 24.11.2019
comment
Я предполагаю, что наследование объясняет другую вещь, потому что clip-path повлияет на все содержимое элемента: jsfiddle.net/89r5t630 ... возможно, дочерний элемент не наследует значение, но на него влияет значение его родителя (например, непрозрачность, отображение и т. д.) - person Temani Afif; 24.11.2019