问题描述
编辑:尝试创建一个mcve,但无法解决该问题。现在我完全困惑了。在codeandBox上有效,不在我的项目中。
初始问题
我想创建一个动态的内联SVG元素,并将其旋转映射到[(ngModel)]
。没什么。
我想说的是,我想将<filter>
与<feDropShadow>
一起使用。而且我希望阴影是动态的(无论针的旋转如何,始终朝上)。这是我在使用Vue之前所做的事情。
这里有个小提琴,展示了这种效果:https://jsfiddle.net/websiter/y4ghan0k/
但是,为了我的一生,当<feDropShadow>
插入模板时,我无法使<svg>
在Angular中工作。它只是不会显示。没有错误或警告。如果我将其插入为<img src="path/to/svg">
,它将按预期工作(显示阴影),但是由于变换后的元素必须是带有过滤器的元素的子元素,所以我无法再旋转路径。 >
请注意,这不是由于this url() filter issue引起的-我为过滤器添加了this.location.path()
。
这是我的Angular代码的要旨:
component.ts:
import { Location } from '@angular/common';
export class SomeComponent {
constructor(private location: Location) {}
dsLink = `url(${this.location.path()}#drop-shadow)`;
}
component.html:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="180" y="100"
viewBox="0 0 180 100" xml:space="preserve">
<defs>
<filter xmlns="http://www.w3.org/2000/svg" id="drop-shadow" height="130%">
<feDropShadow dx="0" dy="-4" flood-color="rgba(0,.65)"/>
</filter>
</defs>
<g [attr.filter]="dsLink">
<path fill="#fff" d="M102.2,89.5c0-0.1,0-0.1,0-0.2c0-0.2,0-0.4-0.1-0.6L92.9,6.8c-0.1-0.8-3.2-0.9-3.3,0
L78.7,88.5c-0.1,0.2-0.1,0.4-0.1,0.6c0,0.1,0.2l0,0.1c0,0.1c0.5,2.4,5.6,4.4,11.7,4.4
c6.2,11.2-1.8,11.8-4.2c0,0.1-0.1,0.1-0.1L102.2,89.5z">
</path>
</g>
</svg>
为简单起见,我从应该旋转针的路径中删除了[(ngModel)]
。
为了使Angular句柄<svg>
元素内联,我需要做/知道是否有什么特别的事情?
我想念什么?
解决方法
我终于破解了它,因此我将其发布在这里,希望对其他人有所帮助。
简而言之:对每个组件实例中的过滤器使用唯一的ID 。否则,每个实例将使用在DOM中找到的第一个过滤器(具有该ID),并且如果该过滤器恰好位于display: none
,visibility:hidden
或opacity: 0
的父级中,则应用该过滤器使您将其应用于不可见的一切。
问题与我在不同选项卡中使用相同组件的事实有关。这将创建组件的单独实例,每个实例使用相同的ID(#drop-shadow
)。尽管具有重复的ID显然是无效的HTML,但如果我们不处理过滤器,实际上这并不是问题。因为<defs>
是相同的,所以第四个选项卡上的组件是否使用第一个选项卡上的组件定义的<defs>
并不重要。
除了处理<filter>
以外,因为它们实际上是逐像素地动态计算渲染结果。这意味着,当未渲染定义<svg>
的{{1}}时,使用滤镜将使浏览器(逐像素)计算应用滤镜的结果,并且始终导致所有像素不可见
因此,解决方案是在组件的每个单独实例中分配唯一的ID。