将您的patternUnits更改为objectBoundingBox并使用preserveAspectRatio来正确定位您的图像。如果源图像具有不同的宽高比,preserveAspectRatio 的切片选项将裁剪掉较短尺寸周围的任何空白。但是,您可能会发现,如果头部不在同一相对位置,则需要调整相对位置(yMin 或 yMid 或 yMax)。
<svg width="450" height="250">
<defs>
<pattern id="image" patternUnits="userSpaceOnUse" height="100" width="100">
<image x="0" y="0" width="100" xlink:href="https://storage.googleapis.com/cbb-image-files/PlayerHeadshots/103536-934915.png" preserveAspectRatio="xMidYMax slice"></image>
</pattern>
</defs>
<circle id='top' cx="50" cy="50" r="49" stroke="black" fill="url(#image)"/>
<defs>
<pattern id="image2" patternUnits="objectBoundingBox" height="100%" width="100%">
<image x="0" y="0" width="100" height="100" xlink:href="https://storage.googleapis.com/cbb-image-files/PlayerHeadshots/104201-933650.png" preserveAspectRatio="xMaxYMin slice"></image>
</pattern>
</defs>
<circle id='top2' cx="175" cy="50" r="49" stroke="black" fill="url(#image2)"/>
<defs>
<pattern id="image3" patternUnits="objectBoundingBox" height="100%" width="100%">
<image x="0" y="0" width="100" height="100" xlink:href="https://storage.googleapis.com/cbb-image-files/PlayerHeadshots/104041-1917730.png" preserveAspectRatio="xMidYMin slice"></image>
</pattern>
</defs>
<circle id='top3' cx="300" cy="50" r="49" stroke="black" fill="url(#image3)"/>
</svg>
如果您的图像元素的宽度/高度=100,那么当它们位于 cx 和 cy 都等于 50 的圆内时,它们看起来会居中。
鉴于此,您只需要将它们翻译到您想要的位置即可。
您可以使用 viewBox 来修复第三个图像,但如果您想适应未知内容,则需要 javascript,即获取图像尺寸,然后根据需要创建适当的 viewBox。
顺便说一句,在 SVG 图像元素上指定 x="0" 和 y="0" 是多余的,因为这是默认值。我已经删除了这些属性。
<svg width="450" height="250">
<defs>
<pattern id="image" patternUnits="userSpaceOnUse" height="100" width="100">
<image width="100" xlink:href="https://storage.googleapis.com/cbb-image-files/PlayerHeadshots/103536-934915.png"></image>
</pattern>
</defs>
<circle id='top' cx="50" cy="50" r="49" stroke="black" fill="url(#image)"/>
<defs>
<pattern id="image2" patternUnits="userSpaceOnUse" height="100" width="100">
<image width="100" xlink:href="https://storage.googleapis.com/cbb-image-files/PlayerHeadshots/104201-933650.png"></image>
</pattern>
</defs>
<circle id='top2' transform="translate(125, 0)" cx="50" cy="50" r="49" stroke="black" fill="url(#image2)"/>
<defs>
<pattern id="image3" patternUnits="userSpaceOnUse" height="100" width="100" viewBox="5 0 90 90">
<image width="100" xlink:href="https://storage.googleapis.com/cbb-image-files/PlayerHeadshots/104041-1917730.png"></image>
</pattern>
</defs>
<circle id='top3' transform="translate(250, 0)" cx="50" cy="50" r="49" stroke="black" fill="url(#image3)"/>
</svg>
为了不陷入
SVG-wants-unique-id-values
陷阱,您可以创建一个 Web 组件:
customElements.define("svg-avatar", class extends HTMLElement {
connectedCallback() {
this.style.display = "inline-block";
let id = Math.floor(Math.random() * 1e6);
let file = this.getAttribute("file");
let href = `https://octodex.github.com/images/` + file;
let ratio = this.getAttribute("ratio") || "xMidYMin";
this.innerHTML = `<svg viewBox="0 0 100 100">
<defs>
<pattern id="im${id}" patternUnits="objectBoundingBox" height="100%" width="100%">
<image width="100" height="100" href="${href}" preserveAspectRatio="${ratio} slice"/>
</pattern>
</defs>
<circle cx="50" cy="50" r="49" stroke="black" fill="url(#im${id})"/>`;
}
});
svg-avatar {
width: 180px;
background: rebeccapurple;
}
<svg-avatar file="saint_nictocat.jpg"></svg-avatar>
<svg-avatar file="grinchtocat.gif"></svg-avatar>
<svg-avatar file="original.jpg"></svg-avatar>