2013-11-06 2 views
4

Цели

Я пытаюсь написать SVG фильтр для визуализации волны освещения на вершине заданной формы. Поэтому внутри этой формы я хочу, чтобы волны применялись, но я не вижу видимого эффекта вне этой формы. Насколько я понимаю, я не могу использовать один и тот же источник изображения как для карты высоты, используемой для волн, так и в качестве целевого домена для atop composition. Поэтому я подумал, что элемент <feImage> может использоваться для получения карты высоты из отдельного заполненного градиентом объекта. Но до сих пор мне не удалось получить этот объект в области эффекта фильтра.feImage с внутренним источником

Первая попытка

код, который я до сих пор:

<?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, тогда ресурс изображения отображается в соответствии с поведением элемента ‘image’; в противном случае ссылочный ресурс отображается в соответствии с поведением элемента ‘use’. В любом случае текущая система координат пользователя зависит от значения атрибута ‘primitiveUnits’ от элемента ‘filter’.

Вторая попытка

use вместо image выглядит все права на меня, но я не уверен, как прямоугольная область определяется в этом случае. documentation for use, по-видимому, указывает, что в этом случае (ссылочный элемент не является ни элементом symbol, ни элементом svg), свойства и не имеют значения, но как это описывает прямоугольную область? Я также подумал, что, возможно, помощь примитивных подразделений поможет. Или бокс изображение внутри 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 моего фильтра?

Rasterizer

Этот образ не предназначен для развертывания веб, но будет растеризации на местном уровне. Таким образом, совместимость с браузером не является большой проблемой; если вещь правильно отображается под Inkscape или rsvg-convert, этого достаточно для меня.

ответ

3

Существует много причин, по которым это может не сработать.

  1. Возможно, вам потребуется указать единицы измерения для ширины и высоты svg (px, pt, em,% whatever). IE не любит неопределенные размеры элементов SVG.
  2. Вы используете неправильный термин для своего входа feComposite: «SourceImage» должен быть «SourceGraphic».
  3. Фильтры лучше применяются непосредственно через свойство фильтра не через свойство стиля.
  4. Я не думаю, что вы можете ссылаться на символ непосредственно в feImage, вы должны использовать его сначала, а затем ссылаться на идентификатор на элементе use. (В любом случае, почему бы просто не использовать прямой напрямую?)

Вот версия, которая работает в Chrome (и, вероятно, Safari), используя вашу методологию.

<svg version="1.1" width="512px" height="512px" viewbox="0 0 512 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" width="100%" height="100%" stroke="none" fill="url(#waveFill)"/> 

    <filter id="waveFilter" primitiveUnits="objectBoundingBox"> 
     <feImage xlink:href="#waveImg" x="0%" y="0%" width="100%" height="100%" result="waves"/> 
     <!-- feSpecularLighting and so on will be added later on --> 
     <feComposite operator="atop" in="waves" in2="SourceGraphic"/> 
    </filter> 
    </defs> 
    <g transform="translate(256 256)"> 


    <ellipse rx="200" ry="100" fill="#0000ff" stroke="none" 
      filter="url(#waveFilter)"/> 
    <ellipse rx="200" ry="100" fill="none" stroke="#ff0000"/> </g> </svg> 

Однако, это не будет работать в Firefox, так как объект входы feImage не поддерживаются, и из моего тестирования, блоки feImage довольно глючный в IE.

Нет причин, по которым вы не можете повторно использовать свою исходную графику для эффектов освещения - вот более короткая версия того, что вы пытаетесь сделать, что работает в браузере и избегает feImage.

<svg version="1.1" x="0px" y="0px" width="512px" height="512px" viewbox="0 0 512 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> 

    <filter id="waveFilter" x="0%" y="0%" width="100%" height="100%"> 
     <feFlood flood-color="#0000ff" result="blue"/> 
     <feComposite operator="in" in2="SourceGraphic" in="blue"/> 
    </filter> 
    </defs> 
    <g transform="translate(256 256)"> 
    <!-- use xlink:href="#waveImg"/ works --> 
    <ellipse rx="200" ry="100" fill="url(#waveFill)" filter="url(#waveFilter)"/> 
    <ellipse rx="200" ry="100" fill="none" stroke="#ff0000"/> </g> </svg> 

И (потому что, почему нет) вот пример с зеркальным освещением добавлены в:

<svg version="1.1" x="0px" y="0px" width="512px" height="512px" viewbox="0 0 512 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> 

    <filter id="waveFilter" x="0%" y="0%" width="100%" height="100%"> 
     <feFlood flood-color="#0000ff" result="blue"/> 
     <feComposite operator="in" in2="SourceGraphic" in="blue"     
      result="sourcewithblue"/> 

     <feSpecularLighting in="SourceAlpha" result="specOut" 
     specularConstant="2" specularExponent="20" lighting-color="white" 
     surfaceScale="2"> 
     <fePointLight x="-200" y="-200" z="200"/> 
     </feSpecularLighting> 

     <feComposite operator="arithmetic" in="specOut" in2="sourcewithblue" k1="0" k2="1" k3="1" result="unclippedoutput"/> 
     <feComposite operator="in" in="unclippedoutput" in2="SourceGraphic"/> 

    </filter> 
    </defs> 
<g transform="translate(256 256)"> 
<ellipse rx="200" ry="100" fill="url(#waveFill)" filter="url(#waveFilter)"/> 
<ellipse rx="200" ry="100" fill="none" stroke="#ff0000"/> 
</g> 
</svg> 
+0

Поддержка браузеров не так важно для меня, я растеризации на местном уровне. Но ни Inkscape, ни rsvg-convert не показывают ваше первое изображение, как и предполагалось. Все ли они багги? Если это так, я должен, вероятно, создавать отчеты об ошибках. Что касается 'symbol' вместо простого' rect': это была просто попытка, так как символ 'с' 'viewBox' стал немного больше напоминать самодостаточный образ и документировал, что' feImage' ведет себя так же, как ' use'. Использование самого объекта для шаблона и «feFill» для раскраски хорошо работает в этом случае, но не сработает, если базовый объект имеет несколько цветов или в некоторых местах полупрозрачен. – MvG

+0

Если вы пытаетесь применить световые эффекты поверх частично прозрачного контента, вам придется обрабатывать освещение независимо. Я не знаю, почему inkscape задыхается от импорта лимузина - извините. –

Смежные вопросы