| 32 | // MAIN PLUGIN CODE |
| 33 | |
| 34 | async function main(): Promise<string | undefined> { |
| 35 | // Inter Regular is the font that objects will be created with by default in |
| 36 | // Figma. We need to wait for fonts to load before creating text using them. |
| 37 | await figma.loadFontAsync({ family: "Inter", style: "Regular" }) |
| 38 | |
| 39 | // Make sure the selection is a single piece of text before proceeding. |
| 40 | if (figma.currentPage.selection.length !== 1) { |
| 41 | return "Select a single node." |
| 42 | } |
| 43 | |
| 44 | const node = figma.currentPage.selection[0] |
| 45 | if (node.type !== 'TEXT') { |
| 46 | return "Select a single text node." |
| 47 | } |
| 48 | |
| 49 | // Replace spaces with nonbreaking spaces. |
| 50 | const text = node.characters.replace(/ /g, " ") |
| 51 | const gap = 5 |
| 52 | |
| 53 | // Create a new text node for each character, and |
| 54 | // measure the total width. |
| 55 | const nodes = [] |
| 56 | let width = 0 |
| 57 | for (let i = 0; i < text.length; i++) { |
| 58 | const letterNode = figma.createText() |
| 59 | letterNode.fontSize = node.fontSize |
| 60 | letterNode.fontName = node.fontName |
| 61 | |
| 62 | letterNode.characters = text.charAt(i) |
| 63 | width += letterNode.width |
| 64 | if (i !== 0) { |
| 65 | width += gap |
| 66 | } |
| 67 | node.parent.appendChild(letterNode) |
| 68 | nodes.push(letterNode) |
| 69 | } |
| 70 | |
| 71 | // Make the radius half the width of the original text, minus a bit. |
| 72 | const r = node.width / 2 - 30 |
| 73 | const pi = 3.1415926 |
| 74 | |
| 75 | // The arclength should be equal to the total desired width of the text, |
| 76 | // => theta * r = width |
| 77 | // => theta = width / r |
| 78 | // |
| 79 | // We define this angle such that 0 means pointing to the right, and pi/2 means |
| 80 | // pointing straight up. |
| 81 | // |
| 82 | // Using these conventions, the starting angle for our curved text is |
| 83 | // pi/2 + theta/2, and the ending angle is pi/2 - theta/2. |
| 84 | |
| 85 | let angle = pi / 2 + width / (2*r) |
| 86 | const gapAngle = gap / r |
| 87 | |
| 88 | const centerX = node.x + node.width / 2 |
| 89 | const centerY = node.y + node.height / 2 |
| 90 | |
| 91 | // Walk through each letter and position it on a circle of radius r. |