Спустя неоднократные попытки анимировать круг со свойством stroke-dasharray
, придумал вариант вложенности circle в circle:
svg {
width: 300px;
}
svg circle {
fill: none;
stroke-width: 10;
stroke: #000;
}
svg circle.default {
opacity: .2;
stroke-dasharray: 125.6;
}
svg circle.default.inner {
opacity: .5;
stroke-dashoffset: 125.6;
animation: circle-default 3s infinite;
}
@keyframes circle-default {
to {
stroke-dashoffset: 0;
}
}
svg circle.dashed {
stroke-dasharray: 1px;
}
<svg viewBox="0 0 120 120">
<g>
<circle class="default" cx="25" cy="25" r="20"></circle>
<circle class="default inner" cx="25" cy="25" r="20"></circle>
</g>
<g>
<circle class="dashed" cx="80" cy="25" r="20"></circle>
</g>
</svg>
JSFIDDLE
Если слева анимирование происходит без каких-либо проблем, то объект справа не поддаётся такому же анимированию.
Идея заключается в помещении одного circle (который по частям) в чистый circle (в котором dasharray
высчитывается как в первом). Тогда удастся анимировать внешний circle и сделать загрузку кружка по частям.
Хочется сделать анимацию разворачивания блока, но чтобы всё это было по частям (см. второй объект).
Когда вы разбиваете круг на равные сегменты с помощью stroke-dasharray
, то невозможно
анимировать их появление с заполнением круга с помощью stroke-dashoffset
Так как круг уже занят полностью. Можно поиграться с изменением величины и количества сегментов, то получатся интересные варианты, но это не то, что вы хотели получить:
<svg width="360" height="360" viewBox="0 0 120 120">
<circle class="background" cx="25" cy="25" r="20" fill="none" stroke="#E4E4E4" stroke-width="8" />
<circle class="default" cx="25" cy="25" r="20" fill="none" stroke="black" stroke-width="8"
stroke-dasharray="125.6" stroke-dashoffset="125.6">
<animate attributeName="stroke-dasharray" dur="7s" values="1.57, 124.03; 1.57,1.57" fill="freeze" />
</circle>
</svg>
Поэтому можно решить данный вопрос с помощью маски, которая будет открывать круг, заранее разбитый на сегменты, создавая иллюзию заполнения:
Маска будет двигаться с помощью stroke-dashoffset
, как у вас первая окружность.
<svg width="360" height="360" viewBox="0 0 120 120">
<defs>
<mask id="msk1">
<circle class="maskCircle" cx="25" cy="25" r="20" fill="none" stroke="white" stroke-width="8" stroke-dashoffset="0" stroke-dasharray="125.6">
<animate attributeName="stroke-dashoffset" dur="4s" values="125.6;0" fill="freeze" repeatCount="indefinite" />
</circle>
</mask>
</defs>
<circle class="background" cx="25" cy="25" r="20" fill="none" stroke="#E4E4E4" stroke-width="8" />
<circle class="default" cx="25" cy="25" r="20" fill="none" stroke="black" stroke-width="8"
stroke-dasharray="1.57" stroke-dashoffset="20" mask="url(#msk1)">
</circle>
</svg>
Если поддержка браузерами позволяет, то можно так (при желании можно ещё поиграться с длиной штриха и анимацией steps(5)
):
html, body, svg {
margin: auto;
display: block;
height: 100%;
}
.dashed {
fill: none;
stroke-width: 10;
stroke: black;
stroke-dasharray: 2.61;
stroke-dashoffset: -1.275;
}
.hidden {
fill: transparent;
}
g {
animation: clip 7s linear infinite;
}
@keyframes clip {
from { clip-path: polygon(50% 50%, 150% 50%, 150% 50%, 50% 50%, 50% 150%, 50% 150%, 50% 50%, -50% 50%, -50% 50%, 50% 50%, 50% -50%, 50% -50%, 50% 50%); }
25% { clip-path: polygon(50% 50%, 150% 50%, 50% 150%, 50% 50%, 50% 150%, 50% 150%, 50% 50%, -50% 50%, -50% 50%, 50% 50%, 50% -50%, 50% -50%, 50% 50%); }
50% { clip-path: polygon(50% 50%, 150% 50%, 50% 150%, 50% 50%, 50% 150%, -50% 50%, 50% 50%, -50% 50%, -50% 50%, 50% 50%, 50% -50%, 50% -50%, 50% 50%); }
75% { clip-path: polygon(50% 50%, 150% 50%, 50% 150%, 50% 50%, 50% 150%, -50% 50%, 50% 50%, -50% 50%, 50% -50%, 50% 50%, 50% -50%, 50% -50%, 50% 50%); }
to { clip-path: polygon(50% 50%, 150% 50%, 50% 150%, 50% 50%, 50% 150%, -50% 50%, 50% 50%, -50% 50%, 50% -50%, 50% 50%, 50% -50%, 150% 50%, 50% 50%); }
}
<svg viewBox="-32 -32 64 64">
<g>
<circle r="25" class="hidden" />
<circle r="20" class="dashed" />
</g>
</svg>
Таким вот способом можно получить нечто по сложнее окружности:
let r = 80
function draw(t){
let a = (t/500)%(Math.PI*7)
let pts = [];
for (let i=0; i<a; i+=0.01){
pts.push([Math.cos(i)*(r-i*3), Math.sin(i)*(r-i*3)])
}
circle.setAttribute('d', 'M' + pts.join('L'))
requestAnimationFrame(draw)
}
requestAnimationFrame(draw)
body {margin:0;overflow:hidden}
<svg width="100vw" height="100vh" viewBox="-100 -100 200 200">
<path id=circle fill="none" stroke="black" stroke-width="18"
stroke-dasharray="2"></path>
</svg>
Использовал эффект анимации рисования сегментов из первого ответа.
При наведении курсора рисуется сегментный круг с анимацией появления изображения.
При уводе курсора сегментный круг сворачивается и прозрачность изображения уменьшается.
Подробности в комментариях к коду:
.container {
width:75%;
height:75%;
}
<div class="container">
<svg viewBox="0 0 120 120">
<defs>
<mask id="msk1">
<circle class="maskCircle" cx="25" cy="25" r="20" fill="none" stroke="white" stroke-width="5" stroke-dashoffset="125.6" stroke-dasharray="125.6">
<!-- анимация рисования черточек -->
<animate
attributeName="stroke-dashoffset"
begin="background.mouseover"
end="background.mouseout"
dur="3s"
values="125.6;0"
fill="freeze"
repeatCount="1" />
<!-- анимация стирания черточек -->
<animate
attributeName="stroke-dashoffset"
begin="background.mouseout"
dur="1s"
values="0;125.6"
fill="freeze"
repeatCount="1" />
</circle>
</mask>
<pattern id="image" x="0%" y="0%" height="100%" width="100%">
<image x="5" y="3" width="29%" height="29%" opacity="0.1" xlink:href="https://i.stack.imgur.com/acozx.jpg">
<!-- анимация увеличения прозрачности изображения при наведении -->
<animate id="an1"
attributeName="opacity"
begin="background.mouseover"
dur="4s"
values="0.05;1"
fill="freeze" />
<!-- анимация уменьшения прозрачности изображения при уводке курсора-->
<animate
attributeName="opacity"
begin="background.mouseout"
dur="1s"
to="0.05"
fill="freeze" />
</image>
</pattern>
</defs>
<g id="gr1">
<circle id="background" cx="25" cy="25" r="20" fill="url(#image)" stroke="#E4E4E4" stroke-width="5" />
<circle class="default" cx="25" cy="25" r="20" fill="none" stroke="black" stroke-width="5"
stroke-dasharray="1.57" stroke-dashoffset="20" mask="url(#msk1)">
</circle>
</g>
</svg>
</div>
Пример анимации из одной точки 2 линиями
.container {
width:75%;
height:75%;
}
<div class="container">
<svg viewBox="0 0 120 120">
<defs>
<mask id="msk1">
<circle class="maskCircle" cx="25" cy="25" r="20" fill="none" stroke="white" stroke-width="5" stroke-dashoffset="-31.4" stroke-dasharray="0,62.8;0, 62.8">
<!-- анимация рисования черточек -->
<animate
attributeName="stroke-dasharray"
begin="background.mouseover"
end="background.mouseout"
dur="3s"
values="0, 62.8 0, 62.8;0,0 125.6,0"
fill="freeze"
repeatCount="1"
restart="whenNotActive" />
<!-- анимация стирания черточек -->
<animate
attributeName="stroke-dasharray"
begin="background.mouseout"
dur="1s"
values="0,0 125.6,0;0, 62.8 0, 62.8"
fill="freeze"
repeatCount="1"
restart="whenNotActive" />
</circle>
</mask>
<pattern id="image" x="0%" y="0%" height="100%" width="100%">
<image x="-2.8" y="0" width="38%" height="38%" opacity="0.1" xlink:href="https://i.stack.imgur.com/EyUuX.jpg">
<!-- анимация увеличения прозрачности изображения при наведении -->
<animate id="an1"
attributeName="opacity"
begin="background.mouseover"
dur="4s"
values="0.05;1"
fill="freeze" />
<!-- анимация уменьшения прозрачности изображения при убирании курсора-->
<animate
attributeName="opacity"
begin="background.mouseout"
dur="1s"
to="0.05"
fill="freeze" />
</image>
</pattern>
</defs>
<g id="gr1">
<circle id="background" cx="25" cy="25" r="20" fill="url(#image)" stroke="#E4E4E4" stroke-width="5" />
<circle class="default" cx="25" cy="25" r="20" fill="none" stroke="black" stroke-width="5"
stroke-dasharray="1.57" stroke-dashoffset="20" mask="url(#msk1)">
</circle>
</g>
</svg>
</div>
В целом что-то такое всегда можно изобразить при помощи js математики и команды arc:
let r = 80
function draw(t){
let a = (t/1000)%(Math.PI*2)
let x = Math.cos(a)*r;
let y = Math.sin(a)*r;
let largeArc = a > Math.PI ? 1 : 0;
circle.setAttribute('d', `M${r},0A${r},${r},0,${largeArc},1,${x},${y}`)
requestAnimationFrame(draw)
}
requestAnimationFrame(draw)
body {margin:0;overflow:hidden}
<svg width="100vw" height="100vh" viewBox="-100 -100 200 200">
<path id=circle fill="none"stroke="black" stroke-width="18" stroke-dasharray="2"></path>
</svg>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
У меня есть path SVG со следующими точками в атрибуте d
Есть задачаНаписать функцию, которая принимает время (часы, минуты, секунды) и выводит его на экран в формате «чч:мм:сс»
Как обратиться к вложенной функции и вложенной в нее функции?