Я использую React для рендеринга некоторых элементов SVG, которые включают фильтры. Вот упрощенный пример:
function ShadowCircle() {
return (
<g>
<defs>
<filter id="dropShadow" x="-20%" y="-20%" width="200%" height="200%">
<feOffset result="offOut" in="SourceAlpha" dx="1" dy="1" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="1" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<circle r="4" cx="50" cy="50" fill="blue" filter="url(#dropShadow)" />
</g>
);
}
function App() {
return <svg width="100" height="100">
<ShadowCircle />
</svg>
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Это прекрасно работает, если я только отображаю только один экземпляр моего <ShadowCircle />
, в противном случае я получаю дублирующие фильтры (и дублирующие идентификаторы) вDOM.
В идеале я хотел бы иметь возможность:
- Убедитесь, что при визуализации одного или нескольких теневых кругов отображается только один фильтр
- Удалите фильтркогда он не используется
Я пробовал индивидуальный подход, используя createPortal
и useEffect
hook, но я столкнулся с парой проблем:
- ItНевозможно отобразить SVG Elements, не заключая их в теги
<svg>
, поэтому портал должен быть <div>
, и все мои фильтры заканчиваются отдельными <svg>
документами. - Вызов
getElementById
внутриuseEffect
, чтобы проверить, был ли фильтр уже на странице, оказался ненадежным, особенно когда на страницу одновременно выводятся несколько элементов.
Как можно отобразить один фильтр при необходимости(одним или несколькими компонентами) и remпосле этого?