Обрезка внешней зоны размытия элемента SVG фильтром Гаусса

Есть простой SVG код, который рисует две прямоугольные рамки с закругленными краями. Первая рамка размыта фильтром Гаусса. Вторая рамка нет, и она по тем же координатам.

Как обрезать размытую часть первой рамки, которая располагается снаружи второй рамки?

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200" version="1.1">
     <defs>
      <filter id="fg152620" clipPathUnits="objectBoundingBox">
       <feGaussianBlur in="SourceGraphic" stdDeviation="7" />
      </filter>
     </defs>
      
     <rect x="20" y="20" rx="10" ry="10" width="240" height="150" fill="none" stroke="black" stroke-width="5" filter="url(#fg152620)"/>      
     <rect x="20" y="20" rx="10" ry="10" width="240" height="150" fill="none" stroke="black" stroke-width="1" />
</svg>

У меня есть решение с использование clipPath, но оно требует повторного указания координат x,y... Объектов много, и они разного размера. Хотелось бы обойтись без указания координат, а за основу брать вторую рамку. Как бы обрезать её background-clip по border-box.

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200" version="1.1">
     <defs>
      <filter id="fg152620" clipPathUnits="objectBoundingBox">
       <feGaussianBlur in="SourceGraphic" stdDeviation="7" />
      </filter>
      
      <clipPath id="cut152620"  >
        <rect x="20" y="20" rx="10" ry="10" width="240" height="150" />
      </clipPath>
     </defs>
      
     <rect x="20" y="20" rx="10" ry="10" width="240" height="150" fill="none" stroke="black" stroke-width="5" filter="url(#fg152620)" clip-path="url(#cut152620)"/>
     <rect x="20" y="20" rx="10" ry="10" width="240" height="150" fill="none" stroke="black" stroke-width="1" />
     
</svg>


Ответы (3 шт):

Автор решения: MaximLensky

Может быть так ?

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="150" version="1.1" viewBox="-1 -1 242 152" style="border-radius: 10px;">
 <defs>
  <filter id="fg152620" clipPathUnits="objectBoundingBox">
   <feGaussianBlur in="SourceGraphic" stdDeviation="7" />
  </filter>
 </defs>

 <rect x="0" y="0" rx="10" ry="10" width="240" height="150" fill="none" stroke="black" stroke-width="5" filter="url(#fg152620)"/>    <rect x="0" y="0" rx="10" ry="10" width="240" height="150" fill="none" stroke="black" stroke-width="2" />
</svg>

→ Ссылка
Автор решения: Сергей Казаков

Вот на таком способе я пока что остановился. Использую clip-path="inset(0px round 10px)"

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" version="1.1">
 <defs>
  <filter id="fg152620" clipPathUnits="objectBoundingBox">
   <feGaussianBlur in="SourceGraphic" stdDeviation="10" />
  </filter>
 </defs>

 <rect x="20" y="20" rx="10" ry="10" width="210" height="110" fill="none" stroke="black" stroke-width="5" filter="url(#fg152620)" clip-path="inset(0px round 10px)" />
 <rect x="20" y="20" rx="10" ry="10" width="210" height="110" fill="none" stroke="black" stroke-width="1" />
</svg>

→ Ссылка
Автор решения: Alexandr_TT

Если я правильно понял, фильтр feGaussianBlur использовался для придания кнопке объема, но при этом появилось необходимость обрезать внешнюю зону размытия элемента SVG фильтром Гаусса.

Предлагаю для обрезки внешней стороны размытия, рассмотреть вариант с использованием фильтра feComposite.

Фильтры feSpecularLighting, feDistantLigh служат для создания большей реалистичности 3D эффекта.

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

.btn {
filter:url(#filterUp);
fill:#919191;
stroke:#919191;
stroke-width:2;
}
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
  <defs>
    <filter id="filterUp">
      <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>
	<rect id="back" width="100%" height="100%" fill="#d3d3d3" />
    <rect class="btn"   x="20" y="20" rx="10" ry="10" width="210" height="110"  /> 
	
</svg>

Пример визуального эффекта нажатия кнопки при наведении

Меняется всего один параметр elevation в фильтре отвечающем за направление света

<feDistantLight azimuth="225" elevation="145"/>

.btn {
filter:url(#filterUp);
fill:#919191;
stroke:#919191;
stroke-width:2;
}
.btn:hover {
filter:url(#filterDown);
fill:#919191;
stroke:#888888;
}
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
  <defs>
    <filter id="filterUp">
      <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>

    <filter id="filterDown">
      <feGaussianBlur in="SourceAlpha" stdDeviation="8" result="blur1"/>
      <feSpecularLighting result="specOut" in="blur1" specularConstant="1.2" specularExponent="12" lighting-color="#fff">
         <feDistantLight azimuth="225" elevation="145"/> 
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="1" k2="1" k3="1" k4="0" result="result"/>
      <feComposite operator="atop" in2="SourceGraphic"/>
    </filter>
 
 </defs>
	<rect id="back" width="100%" height="100%" fill="#d3d3d3" />
    <rect class="btn"   x="20" y="20" rx="10" ry="10" width="210" height="110"  /> 
	  <rect class="btn"   x="250" y="20" rx="10" ry="10" width="210" height="110"  /> 

</svg>

Пример эффекта нажатия круглой кнопки

.btn {
filter:url(#filterUp);
fill:#919191;
stroke:#919191;
stroke-width:2;
}
.btn:hover {
filter:url(#filterDown);
fill:#919191;
stroke:#888888;
}
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
  <defs>
    <filter id="filterUp">
      <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>

    <filter id="filterDown">
      <feGaussianBlur in="SourceAlpha" stdDeviation="8" result="blur1"/>
      <feSpecularLighting result="specOut" in="blur1" specularConstant="1.2" specularExponent="12" lighting-color="#fff">
         <feDistantLight azimuth="225" elevation="145"/> 
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="1" k2="1" k3="1" k4="0" result="result"/>
      <feComposite operator="atop" in2="SourceGraphic"/>
    </filter>
 
 </defs>
	 <rect id="back" width="100%" height="100%" fill="#d3d3d3" /> 
    
	  <circle class="btn" cx="100" cy="100" r="50" /> 
      <circle class="btn" cx="250" cy="100" r="50" />

</svg>

Пример эффекта нажатия двухцветной круглой кнопки

.btn {
filter:url(#filterUp);
fill:red;
stroke:red;
stroke-width:3;
}
.btn:hover {
filter:url(#filterDown);
fill:green;
stroke:green;
}
.btn2 {
filter:url(#filterUp);
fill:green;
stroke:green;
stroke-width:2;
}
.btn2:hover {
filter:url(#filterDown);
fill:dodgerblue;
stroke:dodgerblue;
}
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
  <defs>
    <filter id="filterUp">
      <feGaussianBlur in="SourceAlpha" stdDeviation="4" 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>

    <filter id="filterDown">
      <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur1"/>
      <feSpecularLighting result="specOut" in="blur1" specularConstant="1.2" specularExponent="12" lighting-color="#fff">
         <feDistantLight azimuth="225" elevation="145"/> 
      </feSpecularLighting>
      <feComposite in="SourceGraphic" in2="specOut" operator="arithmetic" k1="1" k2="1" k3="1" k4="0" result="result"/>
      <feComposite operator="atop" in2="SourceGraphic"/>
    </filter>
 
 </defs>
	 <rect id="back" width="100%" height="100%" fill="#d3d3d3" /> 
    
	  <circle class="btn" cx="100" cy="100" r="25" /> 
	    <circle class="btn2" cx="200" cy="100" r="25" />

</svg>

→ Ссылка