it-swarm.com.ru

Как применить фильтр отбрасывания тени с помощью CSS к SVG-определенному элементу/пути

Я хотел бы применить фильтр отбрасывания теней к определенному элементу/пути внутри встроенного SVG с помощью CSS, мне не нужно затенять весь графический объект, просто элемент внутри него.

.shadow {
  fill: red;
  
  -webkit-filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
          filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
}
  <svg height="150" width="150">
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>

Как вы можете видеть выше, я пытаюсь нанести тень на элемент красного круга SVG, но он не работает.

В поисках я не нашел никакой конкретной информации по этому вопросу, только несколько комментариев в других вопросах, связанных с SVG, просто заявляя, что он не работает с отдельными элементами SVG, но без особых объяснений.

ОБНОВЛЕНИЕ

Как отмечено в комментариях @ azeós , он корректно рендерится с помощью Firefox (v. 43.0.2), так что это проблема Chrome. Есть ли какой-нибудь способ сделать этот кроссбраузер без использования SVG-кода, как это предлагается в комментариях?

8
Gruber

Вы можете применить тень выборочно, выбрав цвет объекта, который вы хотите затенить, создав тень, а затем объединив ее с исходным изображением. Но вы должны сделать это с помощью фильтра SVG Trapdoor в CSS-фильтрах, который не работает в IE. (Так что ... хак, но возможно)

Спецификация находится здесь: w3.org/TR/SVG11/filters.html#feColorMatrixElement 

Демо-игрушка здесь:
https://beta.observablehq.com/@gitmullany/filter-effects-using-svg-color-matrices

Эта матрица удваивает непрозрачность всех красных значений, обнуляет непрозрачность всего остального, а затем вычитает 1. Эффект состоит в том, чтобы оставить только вещи с непрозрачностью 100%, которые являются rgb (255,0,0)

#mySVG {
   filter: url(#selective-shadow);
}

.shadow {
  fill: red;
}
<svg>
 <defs>
   <filter id="selective-shadow">
     <feColorMatrix type="matrix" values="0 0 0 0 0 
                                          0 0 0 0 0
                                          0 0 0 0 0 
                                          2 0 0 0 -1"/>
     <feGaussianBlur stdDeviation="3"/>
     <feOffset dy="2" dx="2"/>
     <feMerge>
       <feMergeNode/>
       <feMergeNode in="SourceGraphic"/>
     </feMerge>         
   </filter>
 </defs>
</svg>



<svg height="150" width="150" id="mySVG">
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>

2
Michael Mullany

Обновлено 2018-03: Я провел несколько экспериментов по этому вопросу, потому что я тоже не смог найти никакой информации по этому вопросу, и результаты довольно противоречивы. Версия TL; DR, если вы собираетесь использовать полифилл или просто сделать тень в SVG.

Эксперимент Codepen: http://codepen.io/staypuftman/pen/GoNoMq

Chrome 65 + Canary 67:

Ни Chrome, ни Edge Canary не уважают filter или -webkit-filter должным образом в контексте тени объекта SVG, но работают с простой div

 enter image description here

Firefox 58/Quantum + Firefox 53:

Выглядит неплохо как для SVG, так и для HTML-объектов.

 enter image description here

Safari 10.1+

Safari исправил эту проблему в серии 10.1 (и, возможно, 10.0).

 enter image description here

Safari 9.x

SVG CSS drophadow не отображается, а div drophadow по какой-то причине имеет меньшую непрозрачность

 enter image description here

IE11

Ничего такого.

 enter image description here

14
staypuftman

В это CodePen Я добавил разные drop-shadows в path и text, сгенерированные динамически. Здесь я нашел кросс-браузерное решение, которое можно применить, например, к class вместо #robbie img (во второй ссылке):

#robbie img { filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";   filter: url(#drop-shadow);   -webkit-filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5));   filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5)); }

В первом CodePen я прокомментировал другой альтернативный способ, который не использует classes, но использует #numbers_dropshadows_filter и #strokes_dropshadows_filter, определенные в <defs></defs>.

Ура

1
Riccardo Volpe