feat: add project icon picker component and integrate with project management

- Implemented ProjectIconPicker component for selecting project icons.
- Created ProjectIcon component to display selected icons.
- Updated calendar page to remove unused PageHeading component.
- Modified growth page to enhance UI and improve text clarity.
- Refactored index page to include project icons and improve layout.
- Added mine page for user profile management with avatar selection.
- Introduced projects-sort page for managing project order with drag-and-drop functionality.
- Enhanced projects page to allow icon selection when adding or editing projects.
- Updated record page to streamline user experience and improve form actions.
- Adjusted practice service to support project icon management.
- Added tests for project saving functionality to ensure correct handling of icons.
- Updated global type definitions to support SVG and PNG imports.
This commit is contained in:
yuxuanhui
2026-09-29 18:40:25 +08:00
parent 9644a68d07
commit b0c62d461e
71 changed files with 1305 additions and 125 deletions
+14
View File
@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Arabesque · 阿拉贝斯克</title>
<desc id="desc">修长的灰玫瑰线描舞者,侧身单腿站立,后腿伸直,手臂与脚尖以自然收细的曲线舒展。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M51 39C64 39 78 34 91 29L97 26C99 26 98 28 96 29C84 36 68 44 53 46Z" fill="#fff4ed"/>
<path d="M43 31C44 35 43 38 40 39C31 39 23 36 15 33L9 30C7 29 7 31 9 32C17 39 28 43 39 44C43 44 46 45 48 48C51 52 51 58 54 63C55 66 55 68 54 72C52 81 55 91 56 98C57 104 57 110 56 115L49 118C47 119 47 120 50 120H59C61 120 61 119 60 117C60 111 60 104 61 98C62 88 65 80 62 73C72 72 83 66 94 62C103 59 112 54 119 51C121 50 121 49 119 49L108 53C97 56 87 59 78 61C71 63 66 66 62 63C58 59 57 53 55 48C53 43 48 39 48 35L48 30Z" fill="#fff4ed"/>
<path d="M42 39C45 43 49 43 51 40C53 43 54 47 55 50C56 56 58 60 62 64L65 67C64 70 63 73 60 75C57 71 54 70 53 66C52 61 52 56 50 52C48 48 46 46 42 45Z" fill="#ead1d7"/>
<path d="M52 62C55 62 58 63 60 65" stroke="#bd8292" stroke-width="1.2"/>
<path d="M47 18C43 16 39 18 38 22L38 25L36 27C35 28 37 28 38 28C38 32 40 34 43 34C47 33 50 29 50 25C50 22 49 19 47 18Z" fill="#fff4ed"/>
<path d="M38 23C42 23 45 21 45 18C49 18 51 21 50 25" fill="#ead1d7"/>
<path d="M49 19C52 20 55 18 54 15C53 12 49 13 48 16" fill="#ead1d7"/>
<path d="M56 114L60 115M106 54L108 57" stroke-width="1.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+14
View File
@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Attitude · 阿蒂蒂德</title>
<desc id="desc">侧身舞者单腿支撑,工作腿向后抬起并屈膝,脚尖绷直;一臂举高,另一臂向前舒展。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M48 37C57 29 62 24 60 17C59 14 56 11 53 10C51 9 52 7 54 8C62 11 68 18 67 25C66 33 61 39 53 44Z" fill="#fff4ed"/>
<path d="M62 66C71 58 78 54 86 51C90 50 93 51 96 55L106 67L114 71C117 72 116 74 114 73L103 72C97 69 91 65 87 60C81 65 74 74 64 77Z" fill="#fff4ed"/>
<path d="M43 31C44 35 43 38 40 39C31 41 22 42 13 41C10 40 9 42 12 43C22 47 32 48 41 45C45 44 47 47 48 50C50 54 51 59 54 63C55 66 55 68 54 72C52 81 55 91 56 98C57 104 57 110 56 115L49 118C47 119 47 120 50 120H59C61 120 61 119 60 117C60 111 60 104 61 98C62 88 65 80 62 73L63 66C58 59 57 53 55 48C53 43 48 39 48 35L48 30Z" fill="#fff4ed"/>
<path d="M42 39C45 43 49 43 51 40C53 43 54 47 55 50C56 56 58 60 62 64L65 67C64 70 63 73 60 75C57 71 54 70 53 66C52 61 52 56 50 52C48 48 46 46 42 45Z" fill="#ead1d7"/>
<path d="M52 62C55 62 58 63 60 65M56 114L60 115M105 66L102 70" stroke="#bd8292" stroke-width="1.2"/>
<path d="M47 18C43 16 39 18 38 22L38 25L36 27C35 28 37 28 38 28C38 32 40 34 43 34C47 33 50 29 50 25C50 22 49 19 47 18Z" fill="#fff4ed"/>
<path d="M38 23C42 23 45 21 45 18C49 18 51 21 50 25" fill="#ead1d7"/>
<path d="M49 19C52 20 55 18 54 15C53 12 49 13 48 16" fill="#ead1d7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+18
View File
@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">小球核心</title>
<desc id="desc">舞者坐姿收腹,屈膝抬腿,双手在身前环抱一颗小球。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M16 111H113" stroke="#d8b6bf" stroke-width="1.2"/>
<path d="M57 83C64 77 72 66 79 64C84 63 87 65 90 69L105 82L112 83C115 83 115 85 112 86L103 86C95 82 89 78 82 73L65 91Z" fill="#f3e4e5"/>
<path d="M37 48C39 50 40 53 40 57C37 66 39 78 44 87C47 94 51 99 59 98C67 97 76 88 82 80L85 78C89 85 96 91 104 96C106 97 110 96 114 96C117 96 118 98 114 99L103 101C94 97 84 91 78 84C73 89 65 96 60 97L50 91C46 79 49 71 48 64C48 57 46 53 43 48Z" fill="#fff4ed"/>
<path d="M40 55C43 58 46 58 47 56C50 65 47 70 48 77C48 82 50 87 54 90L65 92C63 95 61 97 59 98C51 99 47 94 44 87C39 78 37 66 40 57Z" fill="#ead1d7"/>
<path d="M44 82C47 82 50 84 52 87M103 94L105 99" stroke="#bd8292" stroke-width="1.2"/>
<circle cx="69" cy="55" r="10" fill="#ead1d7"/>
<path d="M68 49C71 49 74 51 74 54" stroke="#fff4ed" stroke-width="1.65"/>
<path d="M44 58C49 61 51 67 55 69C58 69 61 65 63 62L64 58C64 56 66 56 67 58L67 62C65 67 62 72 57 74C50 74 46 69 43 64" fill="#fff4ed"/>
<path d="M48 57L58 60L60 55C61 53 63 54 62 56L62 61L58 64" fill="#fff4ed"/>
<path d="M32 35C28 34 28 30 31 29C35 28 37 31 36 34" fill="#ead1d7"/>
<path d="M34 33C38 32 42 35 44 39C46 43 44 48 41 50C37 52 33 49 31 44C29 39 30 35 34 33Z" fill="#fff4ed"/>
<path d="M31 41C34 39 36 36 35 33C39 34 42 36 44 40" fill="#ead1d7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+11
View File
@@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">把杆 · Barre</title>
<desc id="desc">灰玫瑰线描双层练习把杆,柔和木色横杆与稳定的立柱底座。</desc>
<g stroke="#9c5268" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<path d="M25 31H31V107H25ZM97 31H103V107H97Z" fill="#fff4ed"/>
<rect x="12" y="30" width="104" height="8" rx="4" fill="#ead1d7"/>
<rect x="12" y="58" width="104" height="8" rx="4" fill="#f3e4e5"/>
<path d="M17 110L24 104H32L39 110V113H17ZM89 110L96 104H104L111 110V113H89Z" fill="#ead1d7"/>
<path d="M19 34H28M19 62H28M44 113H84" stroke="#bd8292" stroke-width="1.4"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 782 B

+17
View File
@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">呼吸训练</title>
<desc id="desc">舞者自然盘坐,双手轻放身体两侧,下肋旁的柔和弧线表现呼吸节奏。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 113H107" stroke="#d8b6bf" stroke-width="1.2"/>
<path d="M53 81C44 82 35 88 29 94C25 98 27 103 32 105C44 109 62 106 75 104L87 103C90 102 91 99 88 97L77 94L72 83Z" fill="#fff4ed"/>
<path d="M74 81C84 83 94 90 99 96C102 100 99 104 94 105C83 107 67 104 54 101L41 102C37 102 36 100 39 98L48 93L53 82Z" fill="#fff4ed"/>
<path d="M61 37C61 41 59 43 55 45C48 46 45 52 43 59L39 74C38 78 40 81 44 80L57 75C60 74 59 72 57 72L46 75L51 61C54 68 53 75 51 83C55 86 59 88 64 91C69 88 73 86 77 83C75 75 74 68 77 61L82 75L71 72C69 72 68 74 71 75L84 80C88 81 90 78 89 74L85 59C83 52 80 46 73 45C69 43 67 41 67 37Z" fill="#fff4ed"/>
<path d="M55 46C60 51 68 51 73 46L78 54L77 61C74 68 75 75 77 83C73 86 69 88 64 91C59 88 55 86 51 83C53 75 54 68 51 61L50 54Z" fill="#ead1d7"/>
<path d="M46 75L57 72C59 72 60 74 57 75L50 78M82 75L71 72C69 72 68 74 71 75L78 78" fill="#fff4ed"/>
<path d="M56 80C61 82 67 82 72 80M48 94L57 97" stroke="#bd8292" stroke-width="1.2"/>
<path d="M60 24C57 22 58 18 62 18C67 17 70 20 67 23" fill="#ead1d7"/>
<path d="M57.5 30C57.5 25.5 60 23 64 23C68 23 70.5 25.5 70.5 30C70.5 34.5 68 39 64 39C60 39 57.5 34.5 57.5 30Z" fill="#fff4ed"/>
<path d="M57.5 30C60 30 63 27 64 24C66 27 68 29 70.5 30" fill="#ead1d7"/>
<path d="M32 60C28 65 28 72 32 77M25 56C19 64 19 73 25 81M96 60C100 65 100 72 96 77M103 56C109 64 109 73 103 81" stroke="#bd8292" stroke-width="1.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+15
View File
@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">核心臀腿</title>
<desc id="desc">侧面臀桥轮廓:肩背贴近垫面,髋部抬起,双膝屈曲,双脚平放,手臂沿身体两侧伸展。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 103H116" stroke="#d8b6bf" stroke-width="1.2"/>
<path d="M66 62L82 57C87 55 90 58 92 63L102 88L111 93C114 95 113 97 110 96L99 95C97 91 95 85 93 81L83 68L71 75Z" fill="#f3e4e5"/>
<path d="M27 90C31 87 34 85 37 82C45 74 53 66 62 61C67 58 71 62 74 65L85 75C89 79 91 85 94 92L106 94C110 94 112 97 108 98H93C90 98 89 96 88 93L78 80L67 74C60 81 52 85 44 88C39 91 35 95 30 95L25 96Z" fill="#fff4ed"/>
<path d="M37 82C45 74 53 66 62 61C67 58 71 62 74 65C70 68 67 72 67 75C60 81 52 85 44 88L37 92L32 87Z" fill="#ead1d7"/>
<path d="M58 64C61 66 64 70 66 74M91 92L96 92" stroke="#bd8292" stroke-width="1.2"/>
<path d="M36 86C42 87 47 91 54 93L70 94C73 95 73 97 70 97L54 97C46 96 40 94 33 93" fill="#fff4ed"/>
<path d="M16 88C13 87 11 90 13 93C15 95 18 94 19 92" fill="#ead1d7"/>
<path d="M17 84C21 82 26 83 28 87L31 89C32 90 30 91 29 91C28 96 25 99 21 99C17 99 14 95 14 91C14 88 15 86 17 84Z" fill="#fff4ed"/>
<path d="M15 87C18 89 20 94 19 98C15 97 13 92 15 87Z" fill="#ead1d7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+14
View File
@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">软开素质</title>
<desc id="desc">坐姿舞者一腿舒展、一腿收拢,手臂弧线越过头顶,身体向伸展腿一侧延长。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M15 114H115" stroke="#d8b6bf" stroke-width="1.2"/>
<path d="M70 55C66 48 62 38 67 31C73 24 84 27 94 31L103 37C105 38 104 40 102 39L91 34C84 32 76 30 73 34C71 38 74 45 77 51Z" fill="#fff4ed"/>
<path d="M77 51C76 54 78 56 81 58C86 63 89 70 93 79L103 94L111 98C114 100 113 102 110 101L101 98C96 92 91 87 87 81L77 68C74 75 71 80 68 85C80 88 90 96 101 102L113 104C116 104 117 106 113 107L99 108C85 104 73 98 59 96C50 100 43 103 35 103C41 105 48 105 54 106C57 107 56 109 53 109L31 108C27 108 24 106 26 103C33 96 42 88 52 85C56 79 61 71 65 63C68 57 72 55 73 50Z" fill="#fff4ed"/>
<path d="M69 58C73 61 78 62 81 58L85 64L77 68C74 75 71 80 68 85C64 87 61 92 59 96C55 94 51 91 48 90L52 85C56 79 61 71 65 63Z" fill="#ead1d7"/>
<path d="M56 79C59 82 63 83 68 83M102 102L101 107" stroke="#bd8292" stroke-width="1.2"/>
<path d="M72 37C68 36 68 32 71 31C75 30 77 33 76 36" fill="#ead1d7"/>
<path d="M73 36C77 34 81 36 84 40C86 44 85 50 81 52C77 54 73 50 71 46C69 42 70 38 73 36Z" fill="#fff4ed"/>
<path d="M71 44C74 42 76 39 75 36C79 36 82 38 84 41" fill="#ead1d7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+16
View File
@@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">足髋训练</title>
<desc id="desc">坐姿舞者一腿屈曲外展、一腿向前伸展并勾起脚尖,以足部与髋部的轮廓表达基础训练。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M16 113H114" stroke="#d8b6bf" stroke-width="1.2"/>
<path d="M48 74C58 74 73 77 80 85C85 91 85 97 79 101L62 108C58 109 56 108 59 106L73 98C76 96 76 93 73 91L51 86Z" fill="#fff4ed"/>
<path d="M41 37C43 41 41 44 38 46C35 55 32 67 30 78L26 94L19 97C17 98 18 100 21 99L30 98C31 98 32 97 32 95L36 79L42 60C44 66 44 70 42 77C40 83 43 88 49 89C62 91 76 99 91 103C97 105 102 106 108 105C111 104 112 101 111 97L112 87C112 85 110 85 109 88L106 96C105 99 103 100 100 99L78 88C68 83 60 80 53 79C56 69 52 60 53 51C52 47 48 44 47 41L47 36Z" fill="#fff4ed"/>
<path d="M39 47C42 50 47 50 50 46L53 51C52 61 56 70 53 79C58 80 61 81 64 82C62 86 59 89 56 91L49 89C43 88 40 83 42 77C44 70 44 66 42 60L37 56Z" fill="#ead1d7"/>
<path d="M51 48C56 53 59 62 62 70L70 82L76 85C78 86 77 88 75 87L68 85C65 81 61 77 58 73C54 67 50 61 48 55" fill="#fff4ed"/>
<path d="M43 75C46 77 50 77 53 77M103 98L108 101" stroke="#bd8292" stroke-width="1.2"/>
<path d="M43 24C39 22 40 18 44 18C48 18 50 21 47 24" fill="#ead1d7"/>
<path d="M39 25C42 22 47 23 49 27C51 32 48 38 44 39C40 39 37 34 37 30C37 28 38 26 39 25Z" fill="#fff4ed"/>
<path d="M37 30C41 30 44 27 45 24C48 26 49 28 49 30" fill="#ead1d7"/>
<path d="M115 95C118 91 118 87 116 83" stroke="#bd8292" stroke-width="1.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+15
View File
@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Grand jeté · 大跳</title>
<desc id="desc">腾空舞者,前后双腿伸展成大幅分腿线,双脚绷直,双臂舒展。</desc>
<g transform="translate(0 10)" stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M68 39C80 35 90 28 100 19L105 15C107 14 108 15 106 17C99 28 85 39 71 45Z" fill="#fff4ed"/>
<path d="M67 67C80 67 92 72 104 76L119 77C122 78 121 80 118 81L105 81C92 82 80 78 66 76Z" fill="#fff4ed"/>
<path d="M59 67C50 68 43 74 31 77L11 82C7 82 6 85 9 85L29 84C42 83 53 79 64 76Z" fill="#fff4ed"/>
<path d="M62 31C62 35 60 37 57 38C49 35 42 29 35 24L24 17C21 15 20 16 22 18C28 26 41 39 55 44C59 47 58 54 60 59L67 72L73 68C68 59 67 53 66 48C65 43 66 38 67 33Z" fill="#fff4ed"/>
<path d="M57 38C60 41 64 41 66 38C68 44 66 48 68 53C69 59 71 64 74 68C71 71 67 73 63 75C61 72 60 68 60 64C61 58 60 53 58 49L55 44Z" fill="#ead1d7"/>
<path d="M61 62C65 62 68 64 71 66M23 79L24 84M108 76V81" stroke="#bd8292" stroke-width="1.2"/>
<path d="M66 16C62 14 58 16 57 20L57 23L55 25C54 26 56 26 57 26C57 30 59 32 62 32C66 31 69 27 69 23C69 20 68 17 66 16Z" fill="#fff4ed"/>
<path d="M57 21C61 21 64 19 64 16C68 16 70 19 69 23" fill="#ead1d7"/>
<path d="M68 17C71 18 74 16 73 13C72 10 68 11 67 14" fill="#ead1d7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+15
View File
@@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">钢琴 · Piano</title>
<desc id="desc">灰玫瑰线描三角钢琴,弧形琴身、浅色琴盖与简洁黑白琴键。</desc>
<g stroke="#9c5268" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<path d="M26 86V111H31L34 86M86 85L91 109H96V80" fill="#ead1d7"/>
<path d="M25 37H63C85 37 108 48 108 63C108 77 95 83 85 83H25Z" fill="#f3e4e5"/>
<path d="M25 37L63 17C81 17 105 29 112 44L108 63L25 56Z" fill="#ead1d7"/>
<path d="M93 61L96 43M25 37V56"/>
<path d="M22 75H84V90H22Z" fill="#fff4ed"/>
<path d="M22 70H84V76H22Z" fill="#ead1d7"/>
<path d="M31 76V90M40 76V90M49 76V90M58 76V90M67 76V90M76 76V90" stroke-width="1.2"/>
<path d="M31 76V83M40 76V83M58 76V83M67 76V83M76 76V83" stroke-width="3.5"/>
<path d="M54 90V98H64M60 94V99"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 969 B

+16
View File
@@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Pirouette · 旋转</title>
<desc id="desc">旋转中的代表姿态:单脚半脚尖支撑,另一脚收至支撑腿膝旁,双臂围圆,短弧线提示旋转。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M37 101C21 108 39 118 55 117M88 102C104 108 93 115 80 116L84 112M80 116L85 118" stroke="#bd8292" stroke-width="1.35"/>
<path d="M63 69C61 79 63 90 64 99L65 111L69 116L72 120H80C82 120 81 119 79 117L72 112L71 99C75 87 76 79 73 70Z" fill="#fff4ed"/>
<path d="M54 69C49 75 44 80 40 84C37 87 38 90 42 93L58 98C61 99 64 99 65 96C64 94 61 94 59 94L47 87L60 75Z" fill="#fff4ed"/>
<path d="M61 30C61 34 60 36 56 37L53 43C55 49 58 53 58 59C58 64 55 67 54 71C58 71 62 74 64 77C66 74 70 71 74 71C73 67 70 64 70 59C70 53 73 49 75 43L72 37C68 36 67 34 67 30Z" fill="#fff4ed"/>
<path d="M56 38C60 45 68 45 72 38L74 43C72 49 69 54 69 59C69 64 72 68 74 70C69 71 66 73 64 76C62 73 59 71 54 70C56 68 59 64 59 59C59 54 56 49 54 43Z" fill="#ead1d7"/>
<path d="M54 40C44 42 39 46 40 52C41 58 51 61 61 59C63 59 63 57 61 56C53 56 47 54 47 51C47 49 50 47 55 46M74 40C84 42 89 46 88 52C87 58 77 61 67 59C65 59 65 57 67 56C75 56 81 54 81 51C81 49 78 47 73 46" fill="#fff4ed"/>
<path d="M61 17C58 14 60 11 64 11C68 11 70 14 67 17" fill="#ead1d7"/>
<path d="M57.5 23C57.5 18.5 60 16 64 16C68 16 70.5 18.5 70.5 23C70.5 27.5 68 32 64 32C60 32 57.5 27.5 57.5 23Z" fill="#fff4ed"/>
<path d="M57.5 23C60 23 63 20 64 17C66 20 68 22 70.5 23" fill="#ead1d7"/>
<path d="M65 109L71 109M58 94V97" stroke-width="1.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+13
View File
@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Plié · 一位半蹲</title>
<desc id="desc">灰玫瑰线描舞者,以一位脚位半蹲,脚跟相接并着地,双膝向外打开,小腿收向脚跟,躯干保持直立。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M61 30C61 34 60 36 56 37C47 36 39 39 31 44C24 48 18 52 12 54C10 55 11 56 13 56C22 53 29 49 37 46C43 43 49 43 54 44C55 49 58 53 58 59C58 63 56 66 53 69C49 74 43 78 40 84C37 88 36 90 39 94C42 97 46 103 51 109C54 112 57 115 60 117L49 120C47 120 47 121 50 121H62C64 121 64 120 63 118C62 114 58 111 56 107C53 102 51 96 46 92C45 91 45 90 46 89C50 85 55 80 60 75C62 74 63 75 64 77C65 75 66 74 68 75C73 80 78 85 82 89C83 90 83 91 82 92C77 96 75 102 72 107C70 111 66 114 65 118C64 120 64 121 66 121H78C81 121 81 120 79 120L68 117C71 115 74 112 77 109C82 103 86 97 89 94C92 90 91 88 88 84C85 78 79 74 75 69C72 66 70 63 70 59C70 53 73 49 74 44C79 43 85 43 91 46C99 49 106 53 115 56C117 56 118 55 116 54C110 52 104 48 97 44C89 39 81 36 72 37C68 36 67 34 67 30Z" fill="#fff4ed"/>
<path d="M56 38C58 41 60 43 64 43C68 43 70 41 72 38L74 43C72 49 69 54 69 59C69 64 73 68 75 70C70 70 66 73 64 76C62 73 58 70 53 70C55 68 59 64 59 59C59 54 56 49 54 43Z" fill="#ead1d7"/>
<path d="M59 60C62 62 66 62 69 60" stroke="#bd8292" stroke-width="1.2"/>
<path d="M61 17C58 14 60 11 64 11C68 11 70 14 67 17" fill="#ead1d7"/>
<path d="M57.5 23C57.5 18.5 60 16 64 16C68 16 70.5 18.5 70.5 23C70.5 27.5 68 32 64 32C60 32 57.5 27.5 57.5 23Z" fill="#fff4ed"/>
<path d="M57.5 23C60 23 63 20 64 17C66 20 68 22 70.5 23" fill="#ead1d7"/>
<path d="M58 114L61 113M67 113L70 114" stroke-width="1.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">足尖鞋 · Pointe shoes</title>
<desc id="desc">灰玫瑰线描的成对足尖鞋,浅玫瑰鞋身与自然垂落的缎带。</desc>
<g stroke="#9c5268" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<path d="M55 58C46 43 46 34 58 26C68 19 71 15 66 10C62 6 55 9 54 13C52 20 60 28 70 36C81 45 84 52 84 62"/>
<path d="M48 58C42 44 43 34 54 26M77 39C84 35 85 27 80 24C75 20 68 23 67 29M74 44C71 48 68 53 68 60"/>
<g transform="rotate(14 81 85)">
<path d="M79 52C70 52 66 63 65 75L64 101C64 108 67 113 72 114H85C90 113 92 109 92 102L93 76C94 62 91 52 84 52Z" fill="#ead1d7"/>
<path d="M80 57C74 57 71 67 70 78C70 84 72 88 78 89C84 89 87 85 88 78C89 68 86 57 83 57Z" fill="#fff4ed"/>
<path d="M66 102C72 100 85 100 91 103M71 65L87 76M87 65L70 77"/>
</g>
<g transform="rotate(18 44 84)">
<path d="M44 49C34 49 29 61 28 75L29 102C29 110 32 115 37 116H50C55 115 58 110 58 103L60 73C60 59 55 49 49 49Z" fill="#f3e4e5"/>
<path d="M45 55C38 55 34 65 34 78C34 85 37 90 43 90C50 90 53 85 54 78C55 65 51 55 48 55Z" fill="#fff4ed"/>
<path d="M30 104C38 101 49 102 57 105M36 64L54 77M53 64L34 77"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Port de bras · 手臂练习</title>
<desc id="desc">以一个手位瞬间表达手臂练习:一臂柔和地举过头顶,另一臂向侧方舒展。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M70 37C77 31 80 26 77 20C75 16 71 13 67 12C65 11 64 9 67 9C77 10 85 17 86 25C87 33 82 40 74 44Z" fill="#fff4ed"/>
<path d="M61 30C61 34 60 36 56 37C47 36 39 39 31 44C24 48 18 52 12 54C10 55 11 56 13 56C22 53 29 49 37 46C43 43 49 43 54 44C55 49 58 53 58 59C58 64 55 67 54 71C53 81 57 92 58 99L59 116L51 119C49 120 50 121 52 121H63L64 98L65 121H76C78 121 79 120 77 119L69 116L70 99C71 92 75 81 74 71C73 67 70 64 70 59C70 53 73 49 74 43L72 37C68 36 67 34 67 30Z" fill="#fff4ed"/>
<path d="M56 38C60 45 68 45 72 38L74 43C72 49 69 54 69 59C69 64 72 68 74 70C69 71 66 73 64 76C62 73 59 71 54 70C56 68 59 64 59 59C59 54 56 49 54 43Z" fill="#ead1d7"/>
<path d="M59 60C62 62 66 62 69 60M59 114H63M65 114H69" stroke="#bd8292" stroke-width="1.2"/>
<path d="M61 17C58 14 60 11 64 11C68 11 70 14 67 17" fill="#ead1d7"/>
<path d="M57.5 23C57.5 18.5 60 16 64 16C68 16 70.5 18.5 70.5 23C70.5 27.5 68 32 64 32C60 32 57.5 27.5 57.5 23Z" fill="#fff4ed"/>
<path d="M57.5 23C60 23 63 20 64 17C66 20 68 22 70.5 23" fill="#ead1d7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+209
View File
@@ -0,0 +1,209 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>芭蕾岛 · 项目图标库</title>
<link rel="icon" type="image/svg+xml" href="pointe-shoes.svg">
<style>
:root { color-scheme: light; --ink: #3e3435; --muted: #827572; --accent: #9c5268; --surface: #fffdfa; --line: #e9dfd9; --sample: #f4ece8; }
* { box-sizing: border-box; }
[hidden] { display: none !important; }
body { margin: 0; background: #faf7f3; color: var(--ink); font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif; line-height: 1.55; }
button { font: inherit; cursor: pointer; }
button:focus-visible, a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
main { width: min(1080px, calc(100% - 64px)); margin: 0 auto; padding: 32px 0 24px; }
.topline, .header, .preview-strip, .controls, .control, .project-row, .sample-footer { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.topline { padding-bottom: 17px; border-bottom: 1px solid var(--line); font-size: 12px; color: var(--muted); }
.brand { font-size: 14px; font-weight: 600; letter-spacing: 2px; color: var(--ink); }
.header { margin: 22px 0; align-items: flex-end; }
h1 { margin: 0 0 5px; font-size: 29px; font-weight: 600; letter-spacing: -.7px; }
p { margin: 0; }
.muted { font-size: 13px; color: var(--muted); }
.palette { display: flex; gap: 6px; padding-bottom: 6px; }
.palette span { width: 20px; height: 20px; border-radius: 50%; border: 1px solid #00000006; }
.preview-strip { padding: 17px; border: 1px solid var(--line); border-radius: 17px; background: var(--surface); }
.project-preview { width: 390px; max-width: 100%; }
.preview-label { display: flex; justify-content: space-between; margin-bottom: 8px; font-size: 11px; color: var(--muted); }
.project-row { justify-content: flex-start; gap: 12px; min-height: 52px; padding: 5px 16px; border: 1px solid #e7ded8; border-radius: 14px; background: var(--sample); }
.project-row img { width: var(--list-icon-size, 32px); height: var(--list-icon-size, 32px); flex-shrink: 0; }
.project-name { min-width: 0; overflow-wrap: anywhere; font-size: 15px; font-weight: 500; }
.preview-options { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; }
.control { justify-content: flex-start; gap: 12px; font-size: 12px; color: var(--muted); }
.swatches, .sizes, .filters { display: flex; gap: 6px; }
.filters { flex-wrap: wrap; }
.swatch { width: 23px; height: 23px; border-radius: 50%; border: 1px solid #dacdc6; padding: 0; }
.swatch[aria-pressed="true"] { outline: 1.5px solid var(--accent); outline-offset: 3px; }
.size, .filter, .clear { border: 1px solid var(--line); border-radius: 7px; color: var(--muted); background: transparent; padding: 3px 10px; font-size: 12px; white-space: nowrap; }
.size[aria-pressed="true"], .filter[aria-pressed="true"] { background: var(--surface); border-color: var(--accent); color: var(--accent); }
.clear { padding: 0; border: 0; color: var(--accent); }
.controls { padding: 23px 1px 16px; flex-wrap: wrap; }
.filter { padding: 5px 12px; }
.samples { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.sample { overflow: hidden; border: 1px solid var(--line); border-radius: 17px; background: var(--surface); }
.sample:has(.sample-stage[aria-pressed="true"]) { border-color: var(--accent); }
.sample-stage { position: relative; display: grid; place-items: center; width: 100%; height: 144px; padding: 0; border: 0; background: var(--sample); color: var(--accent); }
.sample-stage[aria-pressed="true"]:after { content: '✓'; position: absolute; top: 12px; right: 16px; font-size: 13px; }
.sample-stage img { width: 112px; height: 112px; }
.number { position: absolute; top: 13px; left: 15px; color: #9b8985; font-size: 10px; font-variant-numeric: tabular-nums; }
.sample-body { padding: 12px 15px; }
h2 { margin: 0; font-size: 14px; font-weight: 600; }
.english { color: var(--muted); font-size: 11px; margin-top: 2px; min-height: 18px; }
.sample-footer { margin-top: 10px; padding-top: 9px; border-top: 1px solid #f0e9e3; gap: 8px; }
.scale { display: flex; align-items: flex-end; gap: 10px; }
.scale span { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.scale small { color: #998b83; font-size: 9px; }
.download { color: var(--accent); font-size: 11px; text-decoration: none; padding: 8px 0; }
.download:hover { text-decoration: underline; }
footer { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; margin-top: 23px; padding-top: 16px; border-top: 1px solid var(--line); color: #998b83; font-size: 11px; }
footer a { color: var(--muted); text-decoration: none; }
@media (max-width: 850px) { .samples { grid-template-columns: repeat(3, minmax(0, 1fr)); } .scale { gap: 6px; } }
@media (max-width: 600px) {
main { width: calc(100% - 32px); padding-top: 24px; }
h1 { font-size: 25px; }
.samples { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.sample-stage { height: 132px; }
.sample-stage img { width: 100px; height: 100px; }
.sample-body { padding: 10px 12px; }
.sample-footer { gap: 4px; }
.scale span:last-child { display: none; }
.scale { gap: 8px; }
.download { font-size: 10px; }
.preview-strip { flex-direction: column; align-items: stretch; padding: 13px; }
.preview-options { flex-direction: column; align-items: stretch; gap: 10px; }
.preview-options .control { justify-content: space-between; }
.control { gap: 7px; }
.size { padding: 3px 7px; }
.controls { gap: 18px; padding-top: 20px; }
.filter { padding: 4px 8px; }
.palette span { width: 15px; height: 15px; }
}
</style>
</head>
<body>
<main>
<div class="topline"><span class="brand">芭蕾岛</span><span>18 枚项目图标</span></div>
<header class="header">
<div><h1>项目图标库</h1><p class="muted">柔和线描 · 浅色填充</p></div>
<div class="palette" aria-label="灰玫瑰、浅玫瑰、暖白配色"><span style="background:#9c5268"></span><span style="background:#ead1d7"></span><span style="background:#fff4ed"></span></div>
</header>
<section class="preview-strip" aria-label="项目图标预览">
<div class="project-preview">
<p class="preview-label"><span>项目列表预览</span><span>52 px 行高</span></p>
<div class="project-row"><img id="chosen-project-icon" src="arabesque.svg" alt="阿拉贝斯克"><span class="project-name">周末基础课</span></div>
</div>
<div class="preview-options">
<div class="control"><span>图标尺寸</span><div class="sizes" role="group" aria-label="列表图标大小"><button type="button" class="size" data-size="24" aria-pressed="false">24 px</button><button type="button" class="size" data-size="32" aria-pressed="true">32 px</button><button type="button" class="size" data-size="40" aria-pressed="false">40 px</button></div></div>
<div class="control"><span id="chosen-label" aria-live="polite">阿拉贝斯克</span><button type="button" class="clear" id="clear-icon">无图标</button></div>
</div>
</section>
<div class="controls">
<div class="filters" role="group" aria-label="图标分类"><button type="button" class="filter" data-filter="all" aria-pressed="true">全部 18</button><button type="button" class="filter" data-filter="motion" aria-pressed="false">专业动作 8</button><button type="button" class="filter" data-filter="training" aria-pressed="false">基础练习 6</button><button type="button" class="filter" data-filter="object" aria-pressed="false">物件 4</button></div>
<div class="control"><span>预览底色</span><div class="swatches" role="group" aria-label="预览底色"><button type="button" class="swatch" data-background="#f4ece8" style="background:#f4ece8" aria-label="浅玫瑰" aria-pressed="true"></button><button type="button" class="swatch" data-background="#fffdfa" style="background:#fffdfa" aria-label="暖白" aria-pressed="false"></button><button type="button" class="swatch" data-background="#eef0e7" style="background:#eef0e7" aria-label="灰绿" aria-pressed="false"></button></div></div>
</div>
<section class="samples" aria-label="项目图标库,点击图案试选"></section>
<footer><span>透明背景 · 可编辑 SVG · 点击图案试选</span><span>预览稿,尚未接入小程序</span><span>动作参考:<a href="https://australianballet.com.au/ballet-101/ballet-vocabulary" target="_blank" rel="noreferrer">澳大利亚芭蕾舞团</a> · <a href="https://www.atlantaballet.com/resources/ballet-terms-and-positions" target="_blank" rel="noreferrer">亚特兰大芭蕾舞团</a></span></footer>
</main>
<script>
const icons = [
{ id: 'plie', name: '蹲', term: 'Plié · 一位半蹲', group: 'motion' },
{ id: 'tendu', name: '擦地', term: 'Tendu', group: 'motion' },
{ id: 'releve', name: '立半脚尖', term: 'Relevé', group: 'motion' },
{ id: 'port-de-bras', name: '手臂练习', term: 'Port de bras', group: 'motion' },
{ id: 'arabesque', name: '阿拉贝斯克', term: 'Arabesque', group: 'motion' },
{ id: 'attitude', name: '阿蒂蒂德', term: 'Attitude derrière', group: 'motion' },
{ id: 'pirouette', name: '旋转', term: 'Pirouette', group: 'motion' },
{ id: 'grand-jete', name: '大跳', term: 'Grand jeté', group: 'motion' },
{ id: 'foot-hip', name: '足髋训练', term: 'Foot & hip', group: 'training' },
{ id: 'flexibility', name: '软开素质', term: 'Flexibility', group: 'training' },
{ id: 'ball-core', name: '小球核心', term: 'Small ball core', group: 'training' },
{ id: 'swan-arms', name: '天鹅臂颈', term: 'Swan arms & neck', group: 'training' },
{ id: 'breathing', name: '呼吸训练', term: 'Breathing', group: 'training' },
{ id: 'core-glutes', name: '核心臀腿', term: 'Core, glutes & legs', group: 'training' },
{ id: 'soft-shoes', name: '软底舞鞋', term: 'Ballet slippers', group: 'object' },
{ id: 'pointe-shoes', name: '足尖鞋', term: 'Pointe shoes', group: 'object' },
{ id: 'barre', name: '把杆', term: 'Barre', group: 'object' },
{ id: 'piano', name: '钢琴', term: 'Piano', group: 'object' },
];
const gallery = document.querySelector('.samples');
icons.forEach((icon, index) => {
const card = document.createElement('article');
card.className = 'sample';
card.dataset.group = icon.group;
const stage = document.createElement('button');
stage.type = 'button';
stage.className = 'sample-stage';
stage.dataset.icon = icon.id;
stage.setAttribute('aria-label', '选择' + icon.name);
stage.setAttribute('aria-pressed', String(icon.id === 'arabesque'));
const number = document.createElement('span');
number.className = 'number';
number.textContent = String(index + 1).padStart(2, '0');
const image = document.createElement('img');
image.src = icon.id + '.svg';
image.alt = icon.name;
stage.append(number, image);
const body = document.createElement('div');
body.className = 'sample-body';
const title = document.createElement('h2');
title.textContent = icon.name;
const term = document.createElement('p');
term.className = 'english';
term.textContent = icon.term;
const footer = document.createElement('div');
footer.className = 'sample-footer';
const scale = document.createElement('div');
scale.className = 'scale';
[24, 32, 48].forEach(size => {
const item = document.createElement('span');
const preview = document.createElement('img');
preview.src = icon.id + '.svg';
preview.width = size;
preview.height = size;
preview.alt = icon.name + ' ' + size + ' 像素';
const label = document.createElement('small');
label.textContent = size;
item.append(preview, label);
scale.append(item);
});
const download = document.createElement('a');
download.className = 'download';
download.href = icon.id + '.svg';
download.download = icon.id + '.svg';
download.setAttribute('aria-label', '下载' + icon.name + ' SVG');
download.textContent = 'SVG ↓';
footer.append(scale, download);
body.append(title, term, footer);
card.append(stage, body);
gallery.append(card);
stage.addEventListener('click', () => selectIcon(icon));
});
function selectIcon(icon) {
const preview = document.getElementById('chosen-project-icon');
preview.hidden = !icon;
if (icon) { preview.src = icon.id + '.svg'; preview.alt = icon.name; }
document.getElementById('chosen-label').textContent = icon ? icon.name : '无图标';
document.querySelectorAll('[data-icon]').forEach(button => button.setAttribute('aria-pressed', String(Boolean(icon) && button.dataset.icon === icon.id)));
}
document.getElementById('clear-icon').addEventListener('click', () => selectIcon(null));
document.querySelectorAll('[data-background]').forEach(button => {
button.addEventListener('click', () => {
document.documentElement.style.setProperty('--sample', button.dataset.background);
document.querySelectorAll('[data-background]').forEach(item => item.setAttribute('aria-pressed', String(item === button)));
});
});
document.querySelectorAll('[data-size]').forEach(button => {
button.addEventListener('click', () => {
document.documentElement.style.setProperty('--list-icon-size', button.dataset.size + 'px');
document.querySelectorAll('[data-size]').forEach(item => item.setAttribute('aria-pressed', String(item === button)));
});
});
document.querySelectorAll('[data-filter]').forEach(button => {
button.addEventListener('click', () => {
document.querySelectorAll('.sample').forEach(card => { card.hidden = button.dataset.filter !== 'all' && card.dataset.group !== button.dataset.filter; });
document.querySelectorAll('[data-filter]').forEach(item => item.setAttribute('aria-pressed', String(item === button)));
});
});
</script>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Relevé · 立半脚尖</title>
<desc id="desc">修长舞者直立,双脚脚跟抬起,前脚掌着地,双臂在身前自然围圆。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M56 68C54 78 56 88 58 96L58 109C58 112 53 116 49 118C46 119 46 121 49 121H56C58 118 60 115 62 114L63 96L64 75L65 96L66 114C68 115 70 118 72 121H79C82 121 82 119 79 118C75 116 70 112 70 109L70 96C72 88 74 78 72 68Z" fill="#fff4ed"/>
<path d="M61 30C61 34 60 36 56 37L53 43C55 49 58 53 58 59C58 64 55 67 54 71C58 71 62 74 64 77C66 74 70 71 74 71C73 67 70 64 70 59C70 53 73 49 75 43L72 37C68 36 67 34 67 30Z" fill="#fff4ed"/>
<path d="M56 38C60 45 68 45 72 38L74 43C72 49 69 54 69 59C69 64 72 68 74 70C69 71 66 73 64 76C62 73 59 71 54 70C56 68 59 64 59 59C59 54 56 49 54 43Z" fill="#ead1d7"/>
<path d="M54 40C43 43 37 50 39 58C41 67 50 73 61 74C63 74 63 72 61 71C52 67 47 61 46 56C45 52 49 48 55 46M74 40C85 43 91 50 89 58C87 67 78 73 67 74C65 74 65 72 67 71C76 67 81 61 82 56C83 52 79 48 73 46" fill="#fff4ed"/>
<path d="M61 17C58 14 60 11 64 11C68 11 70 14 67 17" fill="#ead1d7"/>
<path d="M57.5 23C57.5 18.5 60 16 64 16C68 16 70.5 18.5 70.5 23C70.5 27.5 68 32 64 32C60 32 57.5 27.5 57.5 23Z" fill="#fff4ed"/>
<path d="M57.5 23C60 23 63 20 64 17C66 20 68 22 70.5 23" fill="#ead1d7"/>
<path d="M58 108L62 109M66 109L70 108" stroke-width="1.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+16
View File
@@ -0,0 +1,16 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">软底舞鞋 · Ballet slippers</title>
<desc id="desc">灰玫瑰线描软底舞鞋,圆润鞋头、浅色鞋身与交叉松紧带。</desc>
<g stroke="#9c5268" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(19 83 68)">
<path d="M83 24C73 24 67 36 66 51L66 89C66 101 71 109 80 110C89 111 96 103 97 91L99 54C100 35 94 24 86 24Z" fill="#ead1d7"/>
<path d="M83 31C76 31 72 44 72 57C72 63 75 67 81 68C88 68 92 63 92 57C93 44 89 31 85 31Z" fill="#fff4ed"/>
<path d="M75 41L92 57M90 41L72 57M72 93C75 99 87 100 91 94"/>
</g>
<g transform="rotate(24 44 70)">
<path d="M44 27C34 27 27 40 27 55L28 91C28 105 35 113 44 112C54 111 60 102 60 89L60 55C60 38 54 27 47 27Z" fill="#f3e4e5"/>
<path d="M44 34C37 34 33 46 33 59C33 67 37 71 44 71C51 71 55 66 54 59C54 45 50 34 46 34Z" fill="#fff4ed"/>
<path d="M35 45L54 60M53 45L33 60M34 96C38 102 49 102 54 95"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+13
View File
@@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">天鹅臂颈</title>
<desc id="desc">修长肩颈与轻柔展开的双臂,手腕自然垂落,形成舒展的翼形轮廓。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M60 39C61 45 59 49 55 51C47 51 41 46 35 41C32 39 30 39 28 42C23 49 18 55 12 59L8 64C7 67 9 67 11 65L16 61C24 57 29 51 32 47C38 54 46 59 52 59C54 68 57 72 57 80C57 89 51 98 48 109C56 113 72 113 80 109C77 98 71 89 71 80C71 72 74 68 76 59C82 59 90 54 96 47C99 51 104 57 112 61L117 65C119 67 121 67 120 64L116 59C110 55 105 49 100 42C98 39 96 39 93 41C87 46 81 51 73 51C69 49 67 45 68 39Z" fill="#fff4ed"/>
<path d="M55 52C60 58 68 58 73 52L76 58C74 68 71 73 71 80C71 89 77 98 80 109C72 113 56 113 48 109C51 98 57 89 57 80C57 73 54 68 52 58Z" fill="#ead1d7"/>
<path d="M57 82C61 84 67 84 71 82M52 59C56 61 59 61 61 61M67 61C70 61 72 60 76 59" stroke="#bd8292" stroke-width="1.2"/>
<path d="M59 22C55 19 57 15 62 15C67 15 69 18 66 21" fill="#ead1d7"/>
<path d="M61 21C56 22 54 26 55 31C55 36 59 42 64 42C68 41 72 36 72 31C72 26 69 21 65 21Z" fill="#fff4ed"/>
<path d="M55 30C60 29 63 25 64 21C67 24 69 27 72 29" fill="#ead1d7"/>
<path d="M20 73C26 73 30 69 33 65M95 65C98 69 102 73 108 73" stroke="#d8b6bf" stroke-width="1.2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+12
View File
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128" fill="none" role="img" aria-labelledby="title desc">
<title id="title">Tendu · 擦地</title>
<desc id="desc">修长舞者单腿直立,工作腿向侧方伸长,绷直的脚尖仍触地。</desc>
<g stroke="#9c5268" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round">
<path d="M61 30C61 34 60 36 56 37C47 36 39 39 31 44C24 48 18 52 12 54C10 55 11 56 13 56C22 53 29 49 37 46C43 43 49 43 54 44C55 49 58 53 58 59C58 64 55 67 54 71C51 81 53 90 54 99V114L46 118C44 119 44 120 47 120H59C61 120 61 118 60 116L61 97C63 88 65 80 64 74C72 88 80 96 91 107L106 119C108 121 110 120 109 118L98 104C89 91 83 80 75 69C72 65 70 63 70 59C70 53 73 49 74 44C79 43 85 43 91 46C99 49 106 53 115 56C117 56 118 55 116 54C110 52 104 48 97 44C89 39 81 36 72 37C68 36 67 34 67 30Z" fill="#fff4ed"/>
<path d="M56 38C58 41 60 43 64 43C68 43 70 41 72 38L74 43C72 49 69 54 69 59C69 64 73 68 75 70C70 70 66 73 64 76C62 73 58 70 53 70C55 68 59 64 59 59C59 54 56 49 54 43Z" fill="#ead1d7"/>
<path d="M59 60C62 62 66 62 69 60M54 113L60 114M99 111L102 108" stroke="#bd8292" stroke-width="1.2"/>
<path d="M61 17C58 14 60 11 64 11C68 11 70 14 67 17" fill="#ead1d7"/>
<path d="M57.5 23C57.5 18.5 60 16 64 16C68 16 70.5 18.5 70.5 23C70.5 27.5 68 32 64 32C60 32 57.5 27.5 57.5 23Z" fill="#fff4ed"/>
<path d="M57.5 23C60 23 63 20 64 17C66 20 68 22 70.5 23" fill="#ead1d7"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB