Цель
Я пытаюсь написать SVG-фильтр для визуализации волнового освещения поверх заданной формы. Итак, внутри этой формы я хочу, чтобы волны применялись, но я не хочу, чтобы за пределами этой формы был видимый эффект. Насколько я понимаю, я не могу использовать один и тот же источник изображения как для карты высот, используемой для волн, так и в качестве целевого домена для atop
композиция. Поэтому я подумал, что для получения карты высот из отдельный объект с градиентной заливкой. Но пока мне не удалось сделать этот объект видимым внутри области эффекта фильтра.
Первая попытка
Код у меня есть до сих пор:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" width="512" height="512"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<radialGradient id="waveFill" r="5%" spreadMethod="reflect">
<stop offset="0%" stop-opacity="1.00"/>
<stop offset="20%" stop-opacity="0.90"/>
<stop offset="40%" stop-opacity="0.65"/>
<stop offset="60%" stop-opacity="0.35"/>
<stop offset="80%" stop-opacity="0.10"/>
<stop offset="100%" stop-opacity="0.00"/>
</radialGradient>
<rect id="waveImg" x="-210" y="-105" width="420" height="210"
stroke="none" fill="url(#waveFill)"/>
<filter id="waveFilter">
<feImage xlink:href="#waveImg" result="waves"/>
<!-- feSpecularLighting and so on will be added later on -->
<feComposite operator="atop" in="waves" in2="SourceImage"/>
</filter>
</defs>
<g transform="translate(256 256)">
<!-- use xlink:href="#waveImg"/ works -->
<ellipse rx="200" ry="100" fill="#0000ff" stroke="none"
style="filter:url(#waveFilter)"/>
</g>
</svg>
Соответствующая документация
В документации для <feImage>
указано:
Если 'xlink:href' ссылается на отдельный ресурс изображения, например как файл JPEG, PNG или SVG, ресурс изображения отображается в соответствии с поведением 'изображение'; в противном случае указанный ресурс отображается в соответствии с поведением 'use' элемент. В любом случае текущая пользовательская система координат зависит от значения атрибута 'primitiveUnits' в элементе 'filter'.
Вторая попытка
use
вместо image
выглядит нормально, но я не уверен, как в этом случае определяется прямоугольная область. документация для use
указывает, что в таком случае (упомянутый элемент не является ни элементом symbol
, ни элементом svg
), свойства width
и height
не имеют значения, но как это описывает прямоугольную область? Я также подумал, что, возможно, поможет смена примитивных единиц измерения. Или поместите изображение внутрь symbol
. Итак, моя вторая попытка была следующей:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" width="512" height="512"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<radialGradient id="waveFill" r="5%" spreadMethod="reflect">
<stop offset="0%" stop-opacity="1.00"/>
<stop offset="20%" stop-opacity="0.90"/>
<stop offset="40%" stop-opacity="0.65"/>
<stop offset="60%" stop-opacity="0.35"/>
<stop offset="80%" stop-opacity="0.10"/>
<stop offset="100%" stop-opacity="0.00"/>
</radialGradient>
<symbol viewBox="0 0 100 100" id="waveImg" preserveAspectRatio="none">
<rect width="100" height="100" stroke="none" fill="url(#waveFill)"/>
</symbol>
<filter id="waveFilter" primitiveUnits="objectBoundingBox">
<feImage xlink:href="#waveImg" x="0" y="0" width="100%" height="100%"
preserveAspectRatio="none" result="waves"/>
<!-- feSpecularLighting and so on will be added later on -->
<feComposite operator="atop" in="waves" in2="SourceImage"/>
</filter>
</defs>
<g transform="translate(256 256)">
<!-- use xlink:href="#waveImg"/ works -->
<ellipse rx="200" ry="100" fill="#0000ff" stroke="none"
style="filter:url(#waveFilter)"/>
<ellipse rx="200" ry="100" fill="none" stroke="#ff0000"/>
</g>
</svg>
По-прежнему не видно изображения. Что я делаю не так?
Основной вопрос
Как я могу использовать фрагмент моего файла SVG в качестве карты рельефа для освещения, не используя его также в качестве SourceGraphic
моего фильтра?
растеризатор
Это изображение не предназначено для веб-развертывания, оно будет растрировано локально. Таким образом, совместимость с браузером не является большой проблемой; если вещь правильно отображается либо в Inkscape, либо в rsvg-convert, мне этого достаточно.