Radar pulse
Radar chart whose data area breathes and vertices ping
Techniques: transform-box · polar → cartesian mapping · animation-delay · scale
<!--
============================================================
SVGarden — https://www.svgarden.dev
Author : Simon-Pierre Boucher
Contact: contact@spboucher.ai
File : snippets/charts/chart-radar-pulse.html
Desc : Radar chart whose data area breathes and vertices ping
============================================================
-->
<div class="sg-chart-radar-pulse" style="--sg-color:#7F77DD; --sg-size:170px; --sg-duration:2.5s;">
<svg viewBox="0 0 140 140" role="img" aria-label="Radar chart of five skills: speed 90, power 65, defense 80, stamina 55, accuracy 70 out of 100">
<title>Skill radar chart</title>
<g class="sg-chart-radar-pulse-rings">
<polygon points="70,18 119.5,53.9 100.6,112.1 39.4,112.1 20.5,53.9" />
<polygon points="70,31 107.1,58 92.9,101.6 47.1,101.6 32.9,58" />
<polygon points="70,44 94.7,62 85.3,91 54.7,91 45.3,62" />
<polygon points="70,57 82.4,66 77.6,80.5 62.4,80.5 57.6,66" />
<line x1="70" y1="70" x2="70" y2="18" />
<line x1="70" y1="70" x2="119.5" y2="53.9" />
<line x1="70" y1="70" x2="100.6" y2="112.1" />
<line x1="70" y1="70" x2="39.4" y2="112.1" />
<line x1="70" y1="70" x2="20.5" y2="53.9" />
</g>
<polygon class="sg-chart-radar-pulse-area" points="70,23.2 102.1,59.6 94.5,103.7 53.2,93.1 35.4,58.8" />
<g class="sg-chart-radar-pulse-dots">
<circle cx="70" cy="23.2" r="3" />
<circle cx="102.1" cy="59.6" r="3" />
<circle cx="94.5" cy="103.7" r="3" />
<circle cx="53.2" cy="93.1" r="3" />
<circle cx="35.4" cy="58.8" r="3" />
</g>
<g class="sg-chart-radar-pulse-labels">
<text x="70" y="12">spd</text>
<text x="128" y="52">pwr</text>
<text x="105" y="122">def</text>
<text x="35" y="122">sta</text>
<text x="12" y="52">acc</text>
</g>
</svg>
</div>
<style>
.sg-chart-radar-pulse {
width: var(--sg-size);
}
.sg-chart-radar-pulse svg {
display: block;
width: 100%;
font-family: inherit;
}
.sg-chart-radar-pulse-rings polygon,
.sg-chart-radar-pulse-rings line {
fill: none;
stroke: rgba(128, 128, 128, 0.3);
stroke-width: 1;
}
.sg-chart-radar-pulse-area {
fill: var(--sg-color);
fill-opacity: 0.35;
stroke: var(--sg-color);
stroke-width: 2;
stroke-linejoin: round;
transform-box: fill-box;
transform-origin: center;
animation: sg-chart-radar-pulse-breathe var(--sg-duration) ease-in-out infinite;
}
.sg-chart-radar-pulse-dots circle {
fill: var(--sg-color);
transform-box: fill-box;
transform-origin: center;
animation: sg-chart-radar-pulse-ping var(--sg-duration) ease-in-out infinite;
}
.sg-chart-radar-pulse-dots circle:nth-of-type(2) { animation-delay: calc(var(--sg-duration) * 0.2); }
.sg-chart-radar-pulse-dots circle:nth-of-type(3) { animation-delay: calc(var(--sg-duration) * 0.4); }
.sg-chart-radar-pulse-dots circle:nth-of-type(4) { animation-delay: calc(var(--sg-duration) * 0.6); }
.sg-chart-radar-pulse-dots circle:nth-of-type(5) { animation-delay: calc(var(--sg-duration) * 0.8); }
.sg-chart-radar-pulse-labels text {
font-size: 9px;
fill: currentColor;
opacity: 0.65;
text-anchor: middle;
}
@keyframes sg-chart-radar-pulse-breathe {
0%, 100% { transform: scale(1); fill-opacity: 0.3; }
50% { transform: scale(1.045); fill-opacity: 0.5; }
}
@keyframes sg-chart-radar-pulse-ping {
0%, 55%, 100% { transform: scale(1); opacity: 1; }
70% { transform: scale(1.9); opacity: 0.4; }
85% { transform: scale(1); opacity: 1; }
}
</style>