You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Firefox遵循用作裁剪路径的SVG rect的transform-origin属性

问题:Firefox中SVG裁剪路径的transform-origin属性不生效

缩放用作SVG图像裁剪路径的SVG矩形时,仅Firefox存在异常(Chrome、Safari表现正常,未测试Edge):Firefox不遵循rect的transform-origin CSS属性。

我制作了两段示例代码复现问题:

  • 示例1:rect覆盖在图像上方,验证Firefox能正确响应rect的transform-origin属性,也能正确返回bounding box,三款浏览器均正常工作。
  • 示例2:将rect用作裁剪路径,展示Firefox的问题——既无法正确应用变换,也不能返回正确的bounding box。

实际项目需要将transform-origin设置为center,求解决缩放后rect正确变换的方法。

运行代码片段时请展开至全屏


完整代码

HTML

<head>
    <title>Firefox Problem: transform-origin and getBBox()</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
</head>


<body>

    <h1>Example 1: Rect Overlaying Image</h1>

    <svg class="example1" viewBox="0 0 2119 2191" preserveAspectRatio="none">
        <image href="https://learn.robertvaessen.com/media/mandala.jpg"/>
        <rect x="530" y="547" width="1060" height="1095"/>
    </svg>

    <div class="example1">
        <h2>Overlay Setup</h2>

        <fieldset>
            <legend align="center">Transform Origin</legend>

            <label>
                Center
                <input type="radio" name="example1TransformOrigin" value="center" checked/>
            </label>

            <label>
                Top Left
                <input type="radio" name="example1TransformOrigin" value="top left"/>
            </label>
        </fieldset>

        <label>
            Scaled
            <input type="checkbox"/>
        </label>

        <input type="button" value="Report"/>
    </div>


    <h1 class="example2" >Example 2: Rect Clipping Image</h1>

    <svg class="example2" viewBox="0 0 2119 2191" preserveAspectRatio="none">
        <clipPath id="rect">
            <rect x="530" y="547" width="1060" height="1095"/>
        </clipPath>
        <image href="https://learn.robertvaessen.com/media/mandala.jpg" clip-path="url(#rect)"></image>
    </svg>

    <div class="example2" >
        <h2>Clipping Setup</h2>

        <fieldset>
            <legend align="center">Transform Origin</legend>

            <label>
                Center
                <input type="radio" name="example2TransformOrigin" value="center" checked/>
            </label>

            <label>
                Top Left
                <input type="radio" name="example2TransformOrigin" value="top left"/>
            </label>
        </fieldset>

        <label>
            Scaled
            <input type="checkbox"/>
        </label>

        <input type="button" value="Report"/>
    </div>

</body>

CSS

body {
    background-color: black;
}

h1 {
    position: fixed;
    left: 50%;
    translate: -50%;

    font: 25px Arial, sans-serif;
    color: white;
    text-align: center;
}
h1.example2 {
    top: 50vh;
}

h2 {
    font: 18px Arial, sans-serif;
    color: white;
    text-align: center;
    text-decoration: underline;
}

svg {
    position: fixed;
    left: 50%;
    translate: -50%;

    width: 200px;
    height: 200px;

    border: 1px solid white;
}
svg.example1 {
    top: 10vh;
}
svg.example2 {
    top: 60vh;
}

rect {
    fill: none;
    stroke: red;
    stroke-width: 20px;
    transform-box: fill-box;
}

div {
    display: flex;
    flex-direction: column;
    gap: 5px;
    align-items: center;

    position: fixed;
    left: 10vw;

    color: white;
    background-color: gray;
    border: 1px solid black;
    border-radius: 5px;

    padding: 8px;
}
div.example1 {
    top: 10vh;
}
div.example2 {
    top: 60vh;
}

JavaScript

window.onload = function() {
    setupExample('example1')
    setupExample('example2')
}

function setupExample(name) {

    let rect = $(`svg.${name} rect`)
    let scaledCheckBox = $(`div.${name} input[type=checkbox]`)
    let transformOriginFieldset = $(`div.${name} > fieldset`)


    function setTransform() {
        if (scaledCheckBox[0].checked) {
            rect.attr('transform', 'scale(1.5)')
        }
        else {
            rect.removeAttr('transform')
        }
    }
    scaledCheckBox.on('change', setTransform)
    setTransform();


    function setTransformOrigin() {
        let transformOrigin = document.querySelector(`div.${name} input[name=${name}TransformOrigin]:checked`).value
        rect.css('transform-origin', transformOrigin)
    }
    transformOriginFieldset.on('change', setTransformOrigin)
    setTransformOrigin()


    let reportButton = $(`div.${name} > input[type=button]`)
    reportButton.on('click', () => {
        let bb = rect[0].getBBox()
        alert(`Rect Bounding Box: ${bb.width} x ${bb.height} at ${bb.x}, ${bb.y}`)
    })
}

内容的提问来源于stack exchange,提问作者Verticon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:15:54