#svg #xhtml #svg-filters
#svg #xhtml #svg-фильтры
Вопрос:
Я разрабатываю в Chrome и Firefox, и у меня возникли проблемы с фильтром SVG. при применении к rect это, похоже, влияет не только на <rect>
элемент. Ниже приведен скриншот результата. Как вы можете видеть, он скрывается за пределами <rect>
, что нежелательно.
Ниже приведен результат в Chrome:
Ниже приведен результат в Firefox:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" width="100%" height="100%">
<defs>
<filter id="dropshadow" height="130%">
<feGaussianBlur in="SourceAlpha" stdDeviation="10"/>
<feOffset dx="5" dy="5" result="offsetblur"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
<filter id = "I">
<feSpecularLighting specularExponent="2" lighting-color="#F3F4F3">
<fePointLight x="300" y="100" z="100"/>
</feSpecularLighting>
</filter>
</filter>
</defs>
<rect x="33%" y="33%" rx="30" ry="30" width="33%" height="300px" style="fill:#FFFFFF; filter:url(#I)"></rect>
</svg>
</body>
</html>
Ответ №1:
Это происходит потому, что область эффектов фильтра по умолчанию, определенная параметрами x
, y
, width
и height
для <filter>
элемента, составляет 120% от ограничивающей рамки фильтруемого элемента, а не 100%.
Спецификация уточняет:
Часто бывает необходимо предоставить пространство для заполнения, поскольку эффект фильтра может слегка повлиять на биты за пределами плотно прилегающей ограничивающей рамки для данного объекта. Для этих целей можно указать отрицательные процентные значения для ‘x’ и ‘y’, а также процентные значения, превышающие 100% для ‘width’ и ‘height’. Например, именно поэтому по умолчанию для области эффектов фильтра x=»-10%» y=»-10%» width=»120%» height=»120%».
Однако изменение этого значения на 100% все равно повлияет на всю ограничивающую рамку, включая области за пределами закругленных углов элемента <rect>
. Если вы хотите ограничить его только прямоугольником, вы можете использовать feComposite
. Например.
<filter id="I">
<feSpecularLighting specularExponent="2" lighting-color="#F3F4F3" result="light">
<fePointLight x="300" y="100" z="100"/>
</feSpecularLighting>
<feComposite in="light" in2="SourceAlpha" operator="in" result="lit"/>
</filter>
Кроме того, вы вложили #I
фильтр внутрь #dropshadow
фильтра. Это не то, что вы можете сделать. Вы пытаетесь объединить освещение и отбрасывание тени? Если это так, вы могли бы сделать это следующим образом:
<filter id="dropshadow">
<feSpecularLighting specularExponent="2" lighting-color="#F3F4F3" result="light">
<fePointLight x="300" y="100" z="100"/>
</feSpecularLighting>
<!-- Apply lighting inside rectangle -->
<feComposite in="light" in2="SourceAlpha" operator="in" result="lit"/>
<feGaussianBlur in="SourceAlpha" stdDeviation="10"/>
<feOffset dx="5" dy="5" result="blur"/>
<!-- Apply blur outside rectangle -->
<feComposite in="blur" in2="SourceAlpha" operator="out" result="shadow"/>
<!-- Combine lighting and shadow -->
<feComposite in="shadow" in2="lit" operator="xor" />
</filter>
Однако, похоже, это не работает в Firefox, но тогда ваш исходный пример также не работает в Firefox для меня.
Комментарии:
1. Спасибо! Я также указал фильтрующие элементы: <идентификатор фильтра =»I» Фильтрующие элементы =»userSpaceOnUse» x=»33%» y=»33%» ширина =»33%» высота =»300 пикселей»>
2. @mgm8870 Вместо этого я бы использовал
objectBoundingBox
единицы фильтрации по умолчанию :<filter id="I" x="0" y="0" width="100%" height="100%">
. Таким образом, вам не придется изменять их, когда вы решите изменить размер или положение элемента<rect>
.3. Это работает в разных браузерах, но только если вы явно определяете размер SVG canvas — в противном случае он, похоже, ломается в Firefox.