SVG свет и тень 3D щупальце - PullRequest
1 голос
/ 21 февраля 2020

Я хочу сделать svg похожим на 3D, добавив маленький свет в верхнем и левом ГРАНИЦА и тень в нижнем и правом ГРАНИЦА

как то так

#div1 {
  background: #ddd;
}
#div1, #div2, #div3 {
  width: 100px;
  height: 100px;
  position: relative;
}
#div2 {
  box-shadow: inset -2px -2px 10px 1px #000;
  position: absolute;
}
#div3 {
  box-shadow: inset 2px 2px 14px 1px #fff;
  position: absolute;
}
<div id="div1">
  <div id="div2"></div>
  <div id="div3"></div>
</div>

Но я не знаю, как это сделать с помощью фильтра SVG

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="1000">


<defs>
  <filter id="filter1" x="0" y="0">
    <feSpecularLighting result="specOut"
        specularExponent="20" lighting-color="#bbbbbb">
      <fePointLight x="-100" y="-100" z="600"/>
    </feSpecularLighting>
    <feComposite in="SourceGraphic" in2="specOut"
        operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
  </filter>
</defs>

<path filter="url(#filter1)" fill="#fff" stroke="#000" d="M20,20 L220,20 L220,220 L20,220 L20,20 "></path>



</svg>

Помогите пожалуйста и спасибо

1 Ответ

5 голосов
/ 23 февраля 2020

Во-первых, вы пытаетесь осветить чистый белый прямоугольник тусклым белым светом. Вы ничего не увидите.

Если сделать прямоугольник темнее, вы начнете видеть какой-то эффект.

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">

  <defs>
    <filter id="filter1" x="0" y="0">
      <feSpecularLighting result="specOut"
          specularExponent="20" lighting-color="#bbbbbb">
        <fePointLight x="-100" y="-100" z="600"/>
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="specOut"
          operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
    </filter>
  </defs>

  <path filter="url(#filter1)" fill="#666" stroke="#000" d="M20,20 L220,20 L220,220 L20,220 L20,20 "></path>
</svg>

Но в приведенном выше примере мы получаем только градиент света над нашим прямоугольником. Как мы можем сделать своего рода скошенный край на прямоугольнике?

Важно знать, что на самом деле не RGB-каналы элемента определяют поведение компонентов фильтра освещения. Компоненты освещения обрабатывают альфа-компонент цвета как карту рельефа . Изменяющиеся значения альфа-канала становятся топологической картой, которая влияет на освещение пикселей.

Один из способов создания переменных значений альфа-канала - использовать фильтр размытия по Гауссу. Вот как это выглядит. Обратите внимание, что мы размываем альфа-канал (SourceAlpha) нашей фигуры.

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
  <defs>
    <filter id="filter2">
      <feGaussianBlur in="SourceAlpha" stdDeviation="8" result="blur1"/>
      <feBlend in="SourceGraphic" in2="blur1" mode="multiply"/>
    </filter>
  </defs>

  <path filter="url(#filter2)" fill="#666" stroke="#000" d="M20,20 L220,20 L220,220 L20,220 L20,20 "></path>
</svg>

Теперь, если использовать этот размытый альфа-канал, мы получим что-то близкое к тому, что вам нужно. Вы можете изменить размытие, значения фильтра освещения и значения feComposite, чтобы настроить эффект.

Обратите внимание, что я также переключился на использование feDistantLight здесь. Я думаю, что это более подходит для этой цели.

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
  <defs>
    <filter id="filter2">
      <feGaussianBlur in="SourceAlpha" stdDeviation="8" result="blur1"/>
      <feSpecularLighting result="specOut" in="blur1" specularConstant="1.2" specularExponent="12" lighting-color="#fff">
        <feDistantLight azimuth="225" elevation="45"/>
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
    </filter>
  </defs>

  <path filter="url(#filter2)" fill="#666" stroke="#000" d="M20,20 L220,20 L220,220 L20,220 L20,20 "></path>
</svg>

Обновление

Чтобы справиться с ситуацией, когда фигуры перекрываются (см. Комментарии), вам нужно будет обрезать любые части размытие, которое находится за пределами формы. Вы можете сделать это с помощью другой операции feComposite.

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
  <defs>
    <filter id="filter2">
      <feGaussianBlur in="SourceAlpha" stdDeviation="8" result="blur1"/>
      <feSpecularLighting result="specOut" in="blur1" specularConstant="1.2" specularExponent="12" lighting-color="#fff">
        <feDistantLight azimuth="225" elevation="45"/>
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="result"/>
      <feComposite operator="atop" in2="SourceGraphic"/>
    </filter>
  </defs>

  <path filter="url(#filter2)" fill="#666" stroke="#000" d="M20,20 L220,20 L220,220 L20,220 L20,20 "></path>
  <path filter="url(#filter2)" fill="#666" stroke="#000" d="M40,40 L200,40 L200,110 L40,110 L40,40 "></path>
  <path filter="url(#filter2)" fill="#666" stroke="#000" d="M40,120 L200,120 L200,200 L40,200 L40,120 "></path>
</svg>
...