Рисование повернутого объекта Path2D на холсте

#javascript #html #css #svg #html5-canvas

Вопрос:

У меня есть холст, на котором я хочу нарисовать повернутый svg.

Для достижения этой цели я создал объект Path2D и использовал опцию context.fill() для рисования svg.

Более того, я использовал context.translate(x , y) для размещения svg.

Теперь вопрос в том, как это повернуть?

Я нашел несколько решений, в которых говорилось, что сначала используется context.translate(x , y) для установки точки преобразования, а затем используется context.rotate(deg) для поворота.

Теперь оба переводчика находятся в конфликте.

Вот код, который я пробовал до сих пор. Этот код поворачивает элемент svg. Но из его верхнего правого угла. Я хочу, чтобы он был повернут от центра:

Кодовая ссылка — https://codepen.io/asiancat54x/pen/jOwyeaR

Вот фрагмент кода

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas></canvas>

    <script>
        const canvas = document.querySelector("canvas")

        const ctx = canvas.getContext("2d")

        const path = new Path2D()

        path.addPath(new Path2D('M 25.214844 0.0664062 C 23.191406 0.332031 20.324219 1.554688 17.460938 3.378906 C 15.777344 4.441406 14.132812 5.679688 12.535156 7.082031 C 11.585938 7.917969 11.566406 7.929688 11.273438 7.929688 C 11.140625 7.929688 10.589844 7.824219 10.046875 7.691406 C 9.230469 7.492188 8.996094 7.457031 8.628906 7.472656 C 7.753906 7.519531 7.9375 7.367188 3.777344 11.53125 C 1.277344 14.035156 0.0546875 15.300781 0.0273438 15.402344 C -0.0351562 15.664062 0.0429688 15.851562 0.253906 15.941406 C 0.351562 15.988281 1.636719 16.222656 3.089844 16.445312 C 6.042969 16.90625 6.269531 16.917969 6.859375 16.648438 C 7.042969 16.5625 7.28125 16.429688 7.378906 16.355469 C 7.484375 16.273438 7.632812 16.207031 7.707031 16.207031 C 7.808594 16.207031 8.582031 16.949219 10.773438 19.140625 C 12.378906 20.75 13.703125 22.113281 13.703125 22.164062 C 13.703125 22.21875 13.636719 22.335938 13.5625 22.429688 C 13.34375 22.683594 13.132812 23.152344 13.054688 23.542969 C 12.984375 23.886719 12.996094 24.015625 13.402344 26.621094 C 13.636719 28.113281 13.851562 29.421875 13.878906 29.535156 C 13.945312 29.761719 14.082031 29.851562 14.355469 29.851562 C 14.527344 29.851562 14.851562 29.539062 18.292969 26.097656 C 21.648438 22.761719 22.066406 22.324219 22.210938 22.007812 C 22.496094 21.398438 22.492188 21.167969 22.183594 19.863281 C 22.027344 19.191406 21.925781 18.660156 21.949219 18.589844 C 21.972656 18.519531 22.285156 18.136719 22.644531 17.726562 C 26.28125 13.621094 28.867188 9.066406 29.644531 5.394531 C 29.792969 4.734375 29.808594 4.5 29.8125 3.613281 C 29.8125 2.660156 29.808594 2.5625 29.660156 2.117188 C 29.285156 1.003906 28.535156 0.320312 27.402344 0.0820312 C 26.996094 -0.0078125 25.792969 -0.0195312 25.214844 0.0664062 Z M 23.464844 4.5625 C 25.449219 5.203125 26.210938 7.632812 24.957031 9.285156 C 24.0625 10.472656 22.503906 10.855469 21.179688 10.199219 C 20.101562 9.675781 19.472656 8.65625 19.472656 7.460938 C 19.472656 6.601562 19.753906 5.910156 20.371094 5.304688 C 21.183594 4.488281 22.367188 4.203125 23.464844 4.5625 Z M 23.464844 4.5625'))

        path.addPath(new Path2D("M 6.871094 18.929688 C 5.667969 20.199219 4.289062 22.570312 3.445312 24.839844 C 3.039062 25.953125 2.84375 27.003906 3.027344 27.183594 C 3.113281 27.273438 3.285156 27.210938 4.402344 26.683594 C 4.914062 26.441406 5.910156 26.019531 6.613281 25.746094 C 8.675781 24.933594 9.160156 24.6875 9.96875 24.0625 C 10.480469 23.65625 11.269531 22.910156 11.328125 22.777344 C 11.351562 22.714844 11.335938 22.589844 11.28125 22.480469 C 11.226562 22.378906 10.375 21.472656 9.371094 20.476562 C 7.671875 18.792969 7.527344 18.65625 7.339844 18.65625 C 7.175781 18.65625 7.089844 18.707031 6.871094 18.929688 Z M 6.871094 18.929688 "))

        var rotation = 0

        canvas.width = innerWidth

        canvas.height = innerHeight

        const animate = () => {
            requestAnimationFrame(animate)

            ctx.fillStyle = "rgba(0 , 0 , 0 , 0.1)"

            ctx.fillRect(0 , 0 , canvas.width , canvas.height)

            ctx.fillStyle = "white"

            ctx.translate(70 , 70)

            ctx.rotate(rotation)

            rotation  = 0.1

            ctx.fill(path)

            ctx.resetTransform()
        }

        animate()


    </script>
</body>
</html> 

Ответ №1:

Я читал о том, как преобразования работают в компьютерной графике (матрицы преобразований).

Вот статья, в которой это подробно объясняется: https://learnopengl.com/Getting-started/Transformations

Ваша проблема, как вы указали, заключается в том, откуда поворачивается svg — transformation origin это не центр svg.

Чтобы изменить источник преобразования, вы можете применить перевод после поворота (прочитайте статью, чтобы понять, почему).

 ctx.rotate(rotation)
ctx.translate(-15 , -15)
 

Я поиграл с ним, и это попало в точку, хотя я бы рекомендовал найти фактическую вещь, которая в первую очередь вызывает смещение источника. (избегайте использования magic numbers — особенно при применении преобразований).

Комментарии:

1. Можете ли вы показать мне пример или отредактировать мой код, чтобы я понял это более четко

2. Я добавил пример, просто добавьте перевод(-15,-15) после поворота.

3. О да, я реализовал это неправильно. Спасибо за ваш ответ. 1 голос Принятое решение 😉

4. У меня тоже была эта проблема. Можете ли вы объяснить, почему вы написали ctx.translate(-15 , -15)

5. В основном преобразования работают в обратном направлении, поэтому перевод «после» вращения перемещает объект до применения вращения — следовательно, изменяет ось вращения. -15-это просто магическое число, которое я нашел. Рекомендуется найти причину,по которой требуется перевод, а затем использовать эти числа для применения преобразований. например, ось по умолчанию равна 0,0, но поскольку svg преобразуется по определению (ось пути не равна 0,0), вам нужно переместить его на x, y, чтобы сопоставить его с 0,0 перед вращением.