SVG Как отобразить несколько путей и вращать их вокруг центра?
Я пытаюсь определить "шаблон" с path
в defs
и повторно использовать его.
Я хочу, чтобы пути вращались вокруг центра с равным интервалом между ними.
Вот, что у меня получилось. Красная точка — центр вращения.
Ниже мой код:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<rect x="0" y="0" width="300" height="300" fill="#0B3E27"/>
<defs>
<path id="rotor" d="M140,140
c0,0,-40,-20,-100,0
c0,0,50,-10,50,20
c0,0,0,-5,50,-20"
fill="none"
stroke-width="2"
stroke="white"/>
</defs>
<g>
<use href="#rotor" x="-2" y="0"/>
<use href="#rotor" x="54" y="-160" transform="rotate(50)"/>
<use href="#rotor" x="-32" y="-305" transform="rotate(100)"/>
<use href="#rotor" x="-198" y="-332" transform="rotate(150)"/>
<use href="#rotor" x="-326" y="-223" transform="rotate(200)"/>
<use href="#rotor" x="-325" y="-55" transform="rotate(250)"/>
<use href="#rotor" x="-195" y="53" transform="rotate(300)"/>
</g>
<circle cx="150" cy="150" r="2" fill="red"></circle>
</svg>
Как сделать в SVG, чтобы пути вращались вокруг центра с равным интервалом между ними.
Свободный перевод вопроса SVG: How can I display multiple paths and rotate them around the center? от участника @S Mxller.
Ответы (3 шт):
Вам необходимо указать центр вращения для поворота одного фрагмента.
Вы можете использовать атрибут transform-origin или свойство CSS, или вы можете указать эту точку в атрибуте rotate() напрямую как 2. и 3. аргументы, например, rotate(50 150 150).
Кроме того, вы можете настроить положение формы ротора, отрегулировав первые координаты в атрибуте d
атрибута path
(M150 150).
Таким образом, вам не нужны дополнительные смещения x и y для каждого экземпляра . Мы можем переместить весь path таким образом, потому что он основан на относительных командах. Если вы не уверены, является ли ваш путь полностью относительным, вы можете преобразовать данные пути с помощью инструмента вроде svg-path-editor
M145 150 c0 0-40-20-100 0 0 0 50-10 50 20 0 0 0-5 50-20
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<rect x="0" y="0" width="300" height="300" fill="#0B3E27"/>
<defs>
<path id="rotor" d="M145 150 c0 0-40-20-100 0 0 0 50-10 50 20 0 0 0-5 50-20"
fill="none"
stroke-width="2"
stroke="white"/>
<style>
</defs>
<g >
<use href="#rotor" />
<use href="#rotor" transform="rotate(50 150 150)" />
<use href="#rotor" transform="rotate(100 150 150)"/>
<use href="#rotor" transform="rotate(150 150 150)"/>
<use href="#rotor" transform="rotate(200 150 150)"/>
<use href="#rotor" transform="rotate(250 150 150)"/>
<use href="#rotor" transform="rotate(300 150 150)"/>
</g>
<circle cx="150" cy="150" r="2" fill="red"></circle>
</svg>
Использование CSS transform-origin
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<rect x="0" y="0" width="300" height="300" fill="#0B3E27"/>
<defs>
<path id="rotor" d="M145 150 c0 0-40-20-100 0 0 0 50-10 50 20 0 0 0-5 50-20"
fill="none"
stroke-width="2"
stroke="white"/>
<style>
use{
transform-origin: 150px 150px;
}
</style>
</defs>
<g >
<use href="#rotor" />
<use href="#rotor" transform="rotate(50)" />
<use href="#rotor" transform="rotate(100)"/>
<use href="#rotor" transform="rotate(150)"/>
<use href="#rotor" transform="rotate(200)"/>
<use href="#rotor" transform="rotate(250)"/>
<use href="#rotor" transform="rotate(300)"/>
</g>
<circle cx="150" cy="150" r="2" fill="red"></circle>
</svg>
Вращение с большим количеством стилей CSS
Расчет угла немного странный — 7 лопастей ротора со смещением в 50 градусов не очень хорошо совпадают (покрывают только 350 градусов).
Кроме того, вы можете легко избежать использования фонового элемента <rect>
, применив фон непосредственно к самому внешнему элементу SVG.
:root {
--blades: 7;
--blade: 0;
}
/* base style for rotor blades */
.b {
transform-origin: 150px 150px;
stroke-width: 2px;
stroke: #fff;
transform: rotate(calc(360deg / var(--blades) * var(--blade)));
}
.b1 {
--blade: 1;
}
.b2 {
--blade: 2;
}
.b3 {
--blade: 3;
}
.b4 {
--blade: 4;
}
.b5 {
--blade: 5;
}
.b6 {
--blade: 6;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300" style="background:#0B3E27">
<defs>
<path id="rotor" d="M145 150 c0 0-40-20-100 0 0 0 50-10 50 20 0 0 0-5 50-20" />
</defs>
<!-- rotor blades -->
<use class="b b0" href="#rotor"/>
<use class="b b1" href="#rotor"/>
<use class="b b2" href="#rotor"/>
<use class="b b3" href="#rotor"/>
<use class="b b4" href="#rotor"/>
<use class="b b5" href="#rotor"/>
<use class="b b6" href="#rotor"/>
</svg>
Свободный перевод ответа от участника @herrstrietzel
@herrstrietzel дал вам совершенно правильный ответ. Это другой подход:
- Я изменяю атрибут d пути так, чтобы он начинался с 0,0. Поскольку путь полностью относительный, мне нужно изменить только первые 2 значения после команды M.
d="M0,0 c0,0,-40,-20,-100,0 c0,0,50,-10,50,20 c0,0,0,-5,50,-20 z"
- Поскольку я хочу, чтобы он находился на расстоянии 10 единиц от центра (красной точки), я меняю первое значение на -10.
d="M-10,0 c0,0,-40,-20,-100,0 c0,0,50,-10,50,20 c0,0,0,-5,50,-20 z"
- Далее я использую «ротор» несколько раз, каждый раз вращая элемент
transform="rotate(60)"
. Вращение происходит вокруг точки0,0
. - Я перемещаю всю группу, где нужно. В данном случае точка 150,150
<g transform="translate(150 150)">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<rect x="0" y="0" width="300" height="300" fill="#0B3E27" />
<defs>
<path id="rotor" d="M-10,0
c0,0,-40,-20,-100,0
c0,0,50,-10,50,20
c0,0,0,-5,50,-20 z" fill="none" stroke-width="2" stroke="white" />
</defs>
<g transform="translate(150 150)">
<use href="#rotor" />
<use href="#rotor" transform="rotate(60)" />
<use href="#rotor" transform="rotate(120)" />
<use href="#rotor" transform="rotate(180)" />
<use href="#rotor" transform="rotate(240)" />
<use href="#rotor" transform="rotate(300)" />
<use href="#rotor" transform="rotate(300)" />
</g>
<circle cx="150" cy="150" r="2" fill="red"></circle>
</svg>
Ответ на комментарий
Так как это перевод вопроса с EnSo я не имею права, по крайней мере этического, исправлять авторский код, поэтому вынужден дать отдельный ответ.
почему в группе 7 листков а отображается 6?
Кратко:
Последняя строка повторяется дважды:
<use href="#rotor" transform="rotate(300)" />
<use href="#rotor" transform="rotate(300)" />
Её можно либо удалить, результат будет тот же:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<rect x="0" y="0" width="300" height="300" fill="#0B3E27" />
<defs>
<path id="rotor" d="M-10,0
c0,0,-40,-20,-100,0
c0,0,50,-10,50,20
c0,0,0,-5,50,-20 z" fill="none" stroke-width="2" stroke="white" />
</defs>
<g transform="translate(150 150)">
<use href="#rotor" />
<use href="#rotor" transform="rotate(60)" />
<use href="#rotor" transform="rotate(120)" />
<use href="#rotor" transform="rotate(180)" />
<use href="#rotor" transform="rotate(240)" />
<use href="#rotor" transform="rotate(300)" />
</g>
<circle cx="150" cy="150" r="2" fill="red"></circle>
</svg>
Либо оставить, для наглядности я добавил последней строке другой стиль:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<rect x="0" y="0" width="300" height="300" fill="#0B3E27" />
<defs>
<path id="rotor" d="M-10,0
c0,0,-40,-20,-100,0
c0,0,50,-10,50,20
c0,0,0,-5,50,-20 z" fill="none" stroke="white" />
</defs>
<g transform="translate(150 150)">
<use href="#rotor" />
<use href="#rotor" transform="rotate(60)" />
<use href="#rotor" transform="rotate(120)" />
<use href="#rotor" transform="rotate(180)" />
<use href="#rotor" transform="rotate(240)" />
<use href="#rotor" transform="rotate(300)" />
<use href="#rotor" transform="rotate(360)" style=" stroke-width:2; stroke-dasharray:4 4" />
</g>
<circle cx="150" cy="150" r="2" fill="red"></circle>
</svg>
То есть последняя позиция лепестка накладывается сверху на первую позицию, которая была задана в секции <defs>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<rect x="0" y="0" width="300" height="300" fill="#0B3E27" />
<defs>
<path id="rotor" d="M-10,0
c0,0,-40,-20,-100,0
c0,0,50,-10,50,20
c0,0,0,-5,50,-20 z" fill="none" stroke="white" />
</defs>
<g transform="translate(150 150)">
<use href="#rotor" />
</g>
<circle cx="150" cy="150" r="2" fill="red"></circle>
</svg>