<section>
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path id="circlePath" fill="none" stroke-width="4" stroke="hsl(0 100% 50% / 0.5)" d="
M 10, 50
a 40,40 0 1,1 80,0
a 40,40 0 1,1 -80,0
" />
<text id="text" font-family="monospace" font-size="12" font-weight="bold" fill="var(--text-1)">
<textPath id="textPath" href="#circlePath"></textPath>
</text>
</svg>
</section>
:root {
--gray-0: #f8f9fa;
--gray-1: #f1f3f5;
--gray-2: #e9ecef;
--gray-3: #dee2e6;
--gray-4: #ced4da;
--gray-5: #adb5bd;
--gray-6: #868e96;
--gray-7: #495057;
--gray-8: #343a40;
--gray-9: #212529;
--gray-10: #16191d;
--gray-11: #0d0f12;
--gray-12: #030507;
/* Surfaces */
--text-1: var(--gray-12);
--text-2: var(--gray-10);
--text-3: var(--gray-8);
--text-4: var(--gray-7);
--surface-1: var(--gray-0);
--surface-2: var(--gray-1);
--surface-3: var(--gray-2);
--surface-4: var(--gray-3);
}
@media (prefers-color-scheme: dark) {
:root {
--text-1: var(--gray-1);
--text-2: var(--gray-3);
--text-3: var(--gray-5);
--text-4: var(--gray-6);
--surface-1: var(--gray-10);
--surface-2: var(--gray-9);
--surface-3: var(--gray-8);
--surface-4: var(--gray-7);
}
}
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
display: grid;
place-items: center;
min-height: 100vh;
font-family: 'Google Sans', sans-serif, system-ui;
overflow: hidden;
background: var(--surface-3);
color: var(--text-2);
}
svg {
width: 80vmin;
overflow: visible;
}
path {
opacity: var(--show, 0);
transition: opacity 0.2s;
}
.dg :is(.cr.string, .cr.number) input[type=text] {
color: white;
line-height: 1;
}
import { GUI } from "https://cdn.skypack.dev/dat.gui@0.7.9"
const CIRCLE_PATH = document.querySelector('#circlePath')
const TEXT_PATH = document.querySelector('#textPath')
const TEXT = document.querySelector('#text')
const OPTIONS = {
text: 'Your text here! • ',
size: 12,
radius: 20,
showPath: true,
spread: false,
inside: false,
}
const CTRL = new GUI()
const VIEWBOX = 100
const onUpdate = () => {
TEXT.setAttribute('font-size', OPTIONS.size)
const PATH = `
M ${VIEWBOX * 0.5 - OPTIONS.radius}, ${VIEWBOX * 0.5}
a ${OPTIONS.radius},${OPTIONS.radius} 0 1,${OPTIONS.inside ? 0 : 1} ${
OPTIONS.radius * 2
},0
${OPTIONS.radius},${OPTIONS.radius} 0 1,${OPTIONS.inside ? 0 : 1} -${
OPTIONS.radius * 2
},0
`
if (OPTIONS.spread) TEXT_PATH.setAttribute('textLength', Math.floor(Math.PI * 2 * OPTIONS.radius))
else TEXT_PATH.removeAttribute('textLength')
CIRCLE_PATH.setAttribute('d', PATH)
TEXT_PATH.innerHTML = OPTIONS.text
CIRCLE_PATH.style.setProperty('--show', OPTIONS.showPath ? 1 : 0)
}
CTRL.add(OPTIONS, 'text').name('Text').onChange(onUpdate)
CTRL.add(OPTIONS, 'size', 6, 16, 1).name('Font size').onChange(onUpdate)
CTRL.add(OPTIONS, 'radius', 20, 50, 1).name('Radius').onChange(onUpdate)
CTRL.add(OPTIONS, 'showPath').name('Show path').onChange(onUpdate)
CTRL.add(OPTIONS, 'spread').name('Spread text').onChange(onUpdate)
CTRL.add(OPTIONS, 'inside').name('Inside').onChange(onUpdate)
onUpdate()
// <circle
// id="MyPath"
// fill="none"
// stroke="red"
// cx="50"
// cy="50"
// r="25"
// />
// <path
// d="
// M (CX - R), CY
// a R,R 0 1,0 (R * 2),0
// a R,R 0 1,0 -(R * 2),0
// "
// />
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.