Как я могу заставить Firefox учитывать начало преобразования прямоугольника SVG, используемого в качестве пути клипа?

У меня есть ситуация, когда я масштабирую прямоугольник SVG, который используется для обрезки изображения SVG. Я столкнулся только с проблемой Firefox (работает, как и ожидалось, в Chrome и Safari; не тестировался с Edge): Firefox не учитывает свойство CSS Transform-Origin прямоугольника.

Я собрал фрагмент, который раскрывает проблему. Есть два примера.

В примере 1 рисуется прямоугольник поверх изображения. Цель примера 1 — продемонстрировать, что Firefox способен правильно реагировать на значение свойства Transform-Origin прямоугольника (а также правильно сообщать об ограничивающем прямоугольнике прямоугольника. Я упоминал ограничивающую рамку?). Пример 1 работает должным образом во всех трех браузерах.

Пример 2 фактически демонстрирует проблему, используя прямоугольник в качестве контура обрезки. Пример 2 также показывает, что Firefox неправильно сообщает об ограничивающей рамке.

Может ли кто-нибудь помочь мне правильно преобразовать масштабированный прямоугольник? В моем реальном проекте я устанавливаю начало преобразования в центр.

Кстати: когда вы запустите фрагмент, разверните его на всю страницу.

            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}`)
                })
            }
        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;
        }
    <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>

Загрузите исходный код Firefox (он с открытым исходным кодом) и исправьте его.

Robert Longson 30.07.2024 17:53
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
1
1
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если я правильно понял проблему, кажется, вы можете исправить ее, применив:

transform-box: view-box;

К элементу rect.

Привет @LS_, изменение поля преобразования с поля заполнения на поле просмотра приводит к тому, что Transform-origin = center работает правильно во всех трех браузерах. Однако теперь Transform-Origin = Top Left не работает должным образом. Хммм... давайте почитаем еще немного о Transform-Box. Тем не менее, я доволен – я могу с этим работать. Спасибо.

Verticon 01.08.2024 14:12

Другие вопросы по теме