请原谅我的英语
我正在使用带过滤器的svg,但遇到以下问题。
这是svg的基础。结果是预期的:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<g>
<circle id="2" cx="50" cy="50" r="50"/>
<g id="1">
<rect x="0" y="0" width="50" height="50" fill="#ccc"/>
<rect x="50" y="50" width="50" height="50" fill="#ccc"/>
</g>
</g>
</svg>
但是使用过滤器feComposite
:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<defs>
<filter id="myFilter1">
<feImage href="#1" result="1"/>
<feImage href="#2" result="2"/>
<feComposite in="1" in2="2" operator="xor"/>
</filter>
</defs>
<g filter="url(#myFilter1)">
<circle id="2" cx="50" cy="50" r="50"/>
<g id="1">
<rect x="0" y="0" width="50" height="50" fill="#ccc"/>
<rect x="50" y="50" width="50" height="50" fill="#ccc"/>
</g>
</g>
</svg>
如您所见,图像已移动。如果您检查代码,则块将与可见图像不匹配:
在这里增加了交互性:
const value = (max = 100000000, min = 0) => Math.round(Math.random() * (max - min)) + min;
const createCircle = (size) => {
const r = value(10, 3);
const cx = value(size - r - 10, r + 10);
const cy = value(size - r - 10, r + 10);
return {
r,
cx,
cy
}
};
const createCircles = (counts, size) => Array(counts).fill().map(() => createCircle(size));
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
position: {
x: 0,
y: 0,
}
};
this.size = 300;
this.circlesData = createCircles(100, this.size);
const getCoords = (c, i) => c + (this.state.position.x * 0.002 * c * (i % 2 ? 1 : -1));
this.circles = () => this.circlesData.map((item, i) => <circle key = {`circles_12dew1_${i}`} cx={getCoords(item.cx, i)} cy={getCoords(item.cy, i)} r={item.r}/>);
}
onMouseMove = e => {
const position = {
x: e.pageX,
y: e.pageY,
};
this.setState({position});
}
render() {
return (
<div className = "App" >
<svg onMouseMove={this.onMouseMove} ref = {elem => this.svg = elem} xmlns = "http://www.w3.org/2000/svg" width = {this.size} height = {this.size} viewBox={`0 0 ${this.size} ${this.size}`}>
<defs>
<filter id="myFilter1">
<feImage href="#1" result="1"/>
<feImage href="#2" result="2"/>
<feComposite in ="1" in2="2" operator="xor"/>
</filter>
</defs>
<g id = "3" filter = "url(#myFilter1)" >
<circle id = "2" cx={this.size / 2 + 100} cy={this.size / 2 + 100} r={this.size / 3}/>
<g id="1"> {this.circles()} </g>
</g>
</svg>
</div>
);
}
}
ReactDOM.render( < App / > , document.getElementById('root'));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
如您所见,一个大圆圈在移动,但它不应该那样做。
如何解决?
还是像在没有svg的交互式示例中一样,如何使图形例外?例如使用画布,谢谢!
答案 0 :(得分:4)
您看到的图像放置行为是因为<feImage>
元素是使用过滤器区域或过滤器原始区域定位的。
https://www.w3.org/TR/SVG11/single-page.html#filters-feImageElement
默认情况下,滤镜区域的面积比所有原始对象大10%。
x =“-10%” y =“-10%” width =“ 120%” height =“ 120%”
这样做是为了迎合诸如<feGuassianBlur>
之类的过滤器原语,这些原语扩展到原始大小之外,否则将被裁剪。
要使图像定位所需的位置,请将滤镜区域或滤镜原始区域更改为与原始对象相同的大小。例如:
<feImage href="#1" x="0" y="0" width="100%" height="100%" result="1"/>
更新的演示:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
<defs>
<filter id="myFilter1">
<feImage href="#1" x="0" y="0" width="100%" height="100%" result="1"/>
<feImage href="#2" x="0" y="0" width="100%" height="100%" result="2"/>
<feComposite in="1" in2="2" operator="xor"/>
</filter>
</defs>
<g filter="url(#myFilter1)">
<circle id="2" cx="50" cy="50" r="50"/>
<g id="1">
<rect x="0" y="0" width="50" height="50" fill="#ccc"/>
<rect x="50" y="50" width="50" height="50" fill="#ccc"/>
</g>
</g>
</svg>