apptify 0.8.0 → 0.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apptify.css +1 -1
- package/dist/apptify.js +1503 -1721
- package/dist/components/button.d.ts +1 -1
- package/dist/components/foundation.d.ts +2 -4
- package/dist/components/link.d.ts +1 -1
- package/dist/core/image-gallery-motion.d.ts +1 -1
- package/dist/core/layers.d.ts +0 -1
- package/dist/index.d.ts +2 -46
- package/docs/COMPONENTS.md +7 -4
- package/package.json +1 -1
- package/templates/playground/README.md +1 -1
- package/templates/playground/package.json +1 -1
- package/templates/playground/source-snapshot.json +80 -40
- package/templates/playground/src/ComponentDemo.vue +2 -5
- package/templates/playground/src/catalog.ts +0 -1
- package/templates/playground/src/components/ErrorPagePreviews.vue +86 -0
- package/templates/playground/src/components/bad-request-paper-scene.vue +280 -0
- package/templates/playground/src/components/bad-request-paper-story.ts +169 -0
- package/templates/playground/src/components/gateway-paper-scene.vue +336 -0
- package/templates/playground/src/components/gateway-paper-story.ts +197 -0
- package/templates/playground/src/components/hamster-429-scene.vue +1045 -0
- package/templates/playground/src/components/server-fire-paper-scene.vue +249 -0
- package/templates/playground/src/components/server-fire-paper-story.ts +272 -0
- package/templates/playground/src/components/unavailable-paper-scene.vue +488 -0
- package/templates/playground/src/editor/component-metadata.ts +0 -1
- package/templates/playground/src/editor/handbooks/apple-dialog.ts +1 -1
- package/templates/playground/src/editor/playground-examples.ts +0 -1
- package/templates/playground/src/error-pages.ts +9 -0
- package/templates/playground/src/style.css +0 -2
- package/templates/playground/src/views/400.vue +74 -0
- package/templates/playground/src/views/403.vue +5 -2
- package/templates/playground/src/views/429.vue +74 -0
- package/templates/playground/src/views/500.vue +67 -0
- package/templates/playground/src/views/502.vue +68 -0
- package/templates/playground/src/views/503.vue +79 -0
- package/templates/playground/src/views/[...all].vue +5 -2
- package/templates/playground/src/views/components.vue +8 -8
- package/tooling/prepare-playground.mjs +2 -2
- package/dist/components/scrollbar.d.ts +0 -88
- package/dist/core/scrollbar.d.ts +0 -14
- package/templates/playground/src/editor/handbooks/apple-scroll-bar.ts +0 -15
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<figure ref="root" class="paper-503-shell unavailable-scene" :class="theme === 'auto' ? null : `is-${theme}`">
|
|
3
|
+
<div class="unavailable-scene__window"><svg class="unavailable-scene__art" data-scene viewBox="0 0 1200 720" xmlns="http://www.w3.org/2000/svg" role="img" :aria-labelledby="`${uid}-title ${uid}-desc`">
|
|
4
|
+
<title :id="`${uid}-title`">传送带、包裹山与熟睡的考拉</title>
|
|
5
|
+
<desc :id="`${uid}-desc`">包裹沿传送带移动,落到积压的包裹山上。镜头拉远后,值班的考拉正窝在椅子里熟睡,任由包裹不断堆积。</desc>
|
|
6
|
+
<defs>
|
|
7
|
+
<linearGradient :id="`${uid}-wall`" x2=".25" y2="1"><stop stop-color="var(--scene-wall-top)"/><stop offset="1" stop-color="var(--scene-wall)"/></linearGradient>
|
|
8
|
+
<linearGradient :id="`${uid}-window`" x2=".4" y2="1"><stop stop-color="#eee5c9"/><stop offset="1" stop-color="#d7dcc2"/></linearGradient>
|
|
9
|
+
<filter :id="`${uid}-shadow`" x="-30%" y="-30%" width="170%" height="180%"><feDropShadow dx="1.2" dy="4.5" stdDeviation="2.4" flood-color="#4b4031" flood-opacity=".15"/></filter>
|
|
10
|
+
<filter :id="`${uid}-soft`" x="-30%" y="-30%" width="170%" height="180%"><feDropShadow dx=".8" dy="2.5" stdDeviation="1.2" flood-color="#4b4031" flood-opacity=".13"/></filter>
|
|
11
|
+
<pattern :id="`${uid}-grain`" width="47" height="43" patternUnits="userSpaceOnUse"><path d="m4 8 1-.4m24 12 .7-.3m11 13 1-.2m-24 5 .6-.3" stroke="#665236" stroke-opacity=".12" stroke-width=".75"/><path d="m13 13 2-.6m19-7 1.2-.4m-10 24 1.8-.5" stroke="#fff9e5" stroke-opacity=".35" stroke-width=".9"/></pattern>
|
|
12
|
+
<clipPath :id="`${uid}-frame`"><path d="M38 80Q38 40 80 36L1111 22Q1155 22 1162 71L1183 631Q1185 670 1139 682L87 704Q35 702 34 657Z"/></clipPath>
|
|
13
|
+
<clipPath :id="`${uid}-belt-clip`"><path d="M-400 344H459a24 24 0 0 1 0 48H-400Z"/></clipPath>
|
|
14
|
+
<clipPath :id="`${uid}-window-clip`"><path d="M120 107 370 100 372 263 120 267Z"/></clipPath>
|
|
15
|
+
<g :id="`${uid}-box`">
|
|
16
|
+
<path d="M-42-60 28-60V0H-42Z" fill="var(--box-front,#c39260)"/>
|
|
17
|
+
<path d="m28-60 20-16v60L28 0Z" fill="var(--box-side,#a4754e)"/>
|
|
18
|
+
<path d="m-42-60 20-16h70L28-60Z" fill="var(--box-top,#dfb57e)"/>
|
|
19
|
+
<path d="M-12-60H2V0H-12Z" fill="#e6cca2"/>
|
|
20
|
+
<path d="m-12-60 20-16h14L2-60Z" fill="#f0d9b2"/>
|
|
21
|
+
<path d="m-40-58 66 0m4 1 16-13" stroke="#edca94" stroke-width="1.2" fill="none"/>
|
|
22
|
+
<path d="m-41-1 67 0m21-15-17 14" stroke="#795c42" stroke-width="1.2" stroke-opacity=".38" fill="none"/>
|
|
23
|
+
<path d="M9-41H24V-22H9Z" fill="#f0e5cb"/>
|
|
24
|
+
<path d="M12-36h8m-8 3h5m-5 5h1m2 0h1m2 0h2" stroke="#938574" stroke-width="1.3" fill="none"/>
|
|
25
|
+
<path d="m-34-17 0-10m-3 3 3-3 3 3m6 7v-10m-3 3 3-3 3 3" stroke="#816145" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity=".75"/>
|
|
26
|
+
<path d="m-30-49 6-2m-12 40 7-1m67-43 3-2" stroke="#f3d4a3" stroke-width="1.1" stroke-opacity=".5"/>
|
|
27
|
+
</g>
|
|
28
|
+
<g :id="`${uid}-leaf`"><path d="M0 0C-18-5-27-22-18-40 0-33 8-15 0 0Z" fill="currentColor"/><path d="M0 0-15-32" stroke="#d2d6b7" stroke-width="1" stroke-opacity=".55"/></g>
|
|
29
|
+
</defs>
|
|
30
|
+
<path d="M47 92Q46 49 88 47L1120 33Q1167 35 1175 84L1194 642Q1196 686 1146 694L94 715Q44 713 44 665Z" fill="var(--scene-frame-shadow)"/>
|
|
31
|
+
<g :clip-path="`url(#${uid}-frame)`">
|
|
32
|
+
<path d="M0 0H1200V720H0Z" :fill="`url(#${uid}-wall)`"/>
|
|
33
|
+
<g data-part="camera">
|
|
34
|
+
<!-- Everything in the depot shares one camera. -->
|
|
35
|
+
<path d="M-1800-700H2800V1200H-1800Z" :fill="`url(#${uid}-wall)`"/>
|
|
36
|
+
<path d="M-1400 530 2400 475V1400H-1400Z" fill="var(--scene-floor)"/>
|
|
37
|
+
<path d="M-1400 544 2400 489" stroke="var(--scene-floor-edge)" stroke-width="5"/>
|
|
38
|
+
<path d="M-100 603 1270 576M230 528-65 790m460-266-49 255m239-258 148 260m159-269 331 266" stroke="var(--scene-floor-line)" stroke-width="1.6" stroke-opacity=".52" fill="none"/>
|
|
39
|
+
<path d="m46 34 1098-17 10 54L42 92Z" fill="var(--scene-timber)"/>
|
|
40
|
+
<path d="m50 36 1094-17 4 14L46 53Z" fill="#c3aa85"/>
|
|
41
|
+
<path d="m1034 64 31-1 17 453-29 5Z" fill="var(--scene-timber)"/>
|
|
42
|
+
<path d="m1034 64 11 1 18 451-10 5Z" fill="#ceb58d"/>
|
|
43
|
+
<path d="m1048 82-126 111 9 13 123-103Z" fill="#b69c77"/>
|
|
44
|
+
<path d="m450 76 16-1 0 211-16 0Z" fill="#cabb99"/>
|
|
45
|
+
<path d="m450 76 6 0 1 207-7 3Z" fill="#d4c5a5"/>
|
|
46
|
+
<!-- A paper landscape through the workshop window. -->
|
|
47
|
+
<path d="m104 91 281-9 4 198-284 9Z" fill="#baa98b"/>
|
|
48
|
+
<path d="m112 99 265-8 2 181-266 8Z" fill="#8c9781"/>
|
|
49
|
+
<g :clip-path="`url(#${uid}-window-clip)`">
|
|
50
|
+
<path d="M110 91H386V280H110Z" :fill="`url(#${uid}-window)`"/>
|
|
51
|
+
<circle cx="294" cy="149" r="27" fill="#faf0c9"/>
|
|
52
|
+
<path d="m82 239 83-64 53 37 62-36 115 65v58H82Z" fill="#bcc5a6"/>
|
|
53
|
+
<path d="m165 175 53 37 62-36-23 43-57 10Z" fill="#d0d2b1"/>
|
|
54
|
+
<path d="M91 256 161 226 226 247 303 217 402 255V292H91Z" fill="#9eaf90"/>
|
|
55
|
+
<path d="M98 272Q181 246 252 264T402 256V300H98Z" fill="#b8bf95"/>
|
|
56
|
+
<path d="m137 268 3-41m0 24-15-18m16 5 10-20" stroke="#849579" stroke-width="4" fill="none"/>
|
|
57
|
+
<path d="m113 228 6-18 18-8 17 4 14 16-6 17-22 3-21-5Z" fill="#839979"/>
|
|
58
|
+
<path d="m119 210 18-8 17 4 5 13-20 10-26-1Z" fill="#a7b48c"/>
|
|
59
|
+
</g>
|
|
60
|
+
<path d="M240 102v163m-119-82 250-6" stroke="#d9c8a6" stroke-width="9"/>
|
|
61
|
+
<path d="M243 103v161m-121-80 248-6" stroke="#8e927a" stroke-width="2"/>
|
|
62
|
+
<path d="m97 279 294-9 10 13-305 10Z" fill="#d0b58d"/>
|
|
63
|
+
<path d="m96 293 305-10-2 8-303 11Z" fill="#a8906d"/>
|
|
64
|
+
<path d="M134 282 391 289 501 525 241 533Z" fill="#f9edc6" fill-opacity=".2"/>
|
|
65
|
+
<!-- Clock and an untouched work sheet. No explanatory text in the art. -->
|
|
66
|
+
<g transform="translate(676 156) rotate(-3)" :filter="`url(#${uid}-soft)`">
|
|
67
|
+
<path d="M-48-9-33-42 1-49 34-35 48-3 38 30 9 47-26 40-47 15Z" fill="#b19b78"/>
|
|
68
|
+
<path d="M-40-8-28-35 0-41 28-29 40-2 32 25 7 39-22 33-39 12Z" fill="#eee1be"/>
|
|
69
|
+
<path d="M0-31v6m29 25h-6M0 30v-6m-29-24h6" stroke="#a29476" stroke-width="2"/>
|
|
70
|
+
<path d="M0-19V0l15 8" stroke="#727562" stroke-width="3.2" stroke-linecap="round" fill="none"/>
|
|
71
|
+
<circle r="3.8" fill="#727562"/>
|
|
72
|
+
</g>
|
|
73
|
+
<g transform="translate(835 236) rotate(3)">
|
|
74
|
+
<path d="M-35-43 38-44 40 48-36 49Z" fill="#b49c76"/>
|
|
75
|
+
<path d="M-29-36 32-37 32 41-30 42Z" fill="#ede1c5"/>
|
|
76
|
+
<path d="M-12-44h27v8h-27Z" fill="#879487"/>
|
|
77
|
+
<path d="M-17-22h34m-34 13h29m-29 13h34m-34 13h24" stroke="#c2baa0" stroke-width="2.2"/>
|
|
78
|
+
<path d="m-21-22 3 0m-3 13h3m-3 13h3m-3 13h3" stroke="#9caa8b" stroke-width="3"/>
|
|
79
|
+
</g>
|
|
80
|
+
<!-- Belt legs remain attached to the moving upper belt. -->
|
|
81
|
+
<path d="m53 589 392-1 22 18-430 1Z" fill="#6c7561" fill-opacity=".14"/>
|
|
82
|
+
<path d="M103 394h24l-14 198H89Zm278 0h23l23 199h-24Z" fill="#748776"/>
|
|
83
|
+
<path d="M103 394h8L99 592H89Zm278 0h8l23 199h-9Z" fill="#9ba88c"/>
|
|
84
|
+
<path d="M116 473h281v15H115Z" fill="#a2ad91"/>
|
|
85
|
+
<path d="m120 408 276 170m-5-170L112 577" stroke="#8e9d83" stroke-width="7"/>
|
|
86
|
+
<path d="M82 589h39v8H82Zm315 0h39v8h-39Z" fill="#586b61"/>
|
|
87
|
+
<!-- Belt top and ribs share the parcel velocity. -->
|
|
88
|
+
<path d="M-450 343H459a25 25 0 0 1 0 50H-450Z" fill="#485e59"/>
|
|
89
|
+
<g :clip-path="`url(#${uid}-belt-clip)`" stroke="#829383" stroke-width="2.2"><g data-part="belt-ribs"><path d="M-480 345v6"/><path d="M-456 345v6"/><path d="M-432 345v6"/><path d="M-408 345v6"/><path d="M-384 345v6"/><path d="M-360 345v6"/><path d="M-336 345v6"/><path d="M-312 345v6"/><path d="M-288 345v6"/><path d="M-264 345v6"/><path d="M-240 345v6"/><path d="M-216 345v6"/><path d="M-192 345v6"/><path d="M-168 345v6"/><path d="M-144 345v6"/><path d="M-120 345v6"/><path d="M-96 345v6"/><path d="M-72 345v6"/><path d="M-48 345v6"/><path d="M-24 345v6"/><path d="M0 345v6"/><path d="M24 345v6"/><path d="M48 345v6"/><path d="M72 345v6"/><path d="M96 345v6"/><path d="M120 345v6"/><path d="M144 345v6"/><path d="M168 345v6"/><path d="M192 345v6"/><path d="M216 345v6"/><path d="M240 345v6"/><path d="M264 345v6"/><path d="M288 345v6"/><path d="M312 345v6"/><path d="M336 345v6"/><path d="M360 345v6"/><path d="M384 345v6"/><path d="M408 345v6"/><path d="M432 345v6"/><path d="M456 345v6"/><path d="M480 345v6"/></g><g data-part="belt-bottom-ribs"><path d="M-480 385v6"/><path d="M-456 385v6"/><path d="M-432 385v6"/><path d="M-408 385v6"/><path d="M-384 385v6"/><path d="M-360 385v6"/><path d="M-336 385v6"/><path d="M-312 385v6"/><path d="M-288 385v6"/><path d="M-264 385v6"/><path d="M-240 385v6"/><path d="M-216 385v6"/><path d="M-192 385v6"/><path d="M-168 385v6"/><path d="M-144 385v6"/><path d="M-120 385v6"/><path d="M-96 385v6"/><path d="M-72 385v6"/><path d="M-48 385v6"/><path d="M-24 385v6"/><path d="M0 385v6"/><path d="M24 385v6"/><path d="M48 385v6"/><path d="M72 385v6"/><path d="M96 385v6"/><path d="M120 385v6"/><path d="M144 385v6"/><path d="M168 385v6"/><path d="M192 385v6"/><path d="M216 385v6"/><path d="M240 385v6"/><path d="M264 385v6"/><path d="M288 385v6"/><path d="M312 385v6"/><path d="M336 385v6"/><path d="M360 385v6"/><path d="M384 385v6"/><path d="M408 385v6"/><path d="M432 385v6"/><path d="M456 385v6"/><path d="M480 385v6"/><path d="M504 385v6"/><path d="M528 385v6"/></g></g>
|
|
90
|
+
<path d="M-450 397H463l19-12 2 24-24 17H-450Z" fill="#879a83"/>
|
|
91
|
+
<path d="M-450 397H463l19-12-8 15-15 9H-450Z" fill="#b3bea0"/>
|
|
92
|
+
<path d="M-450 423H458" stroke="#5a7366" stroke-width="3"/>
|
|
93
|
+
<g fill="#c6cbb0"><circle cx="78" cy="411" r="3"/><circle cx="247" cy="411" r="3"/><circle cx="427" cy="411" r="3"/></g>
|
|
94
|
+
<g transform="translate(456 368)">
|
|
95
|
+
<circle r="21" fill="#b3baa0"/><circle r="14" fill="#7d8d7a"/>
|
|
96
|
+
<g data-part="roller"><path d="M-10 0H10M0-10V10" stroke="#cbd0b3" stroke-width="3"/><circle r="4" fill="#556e60"/></g>
|
|
97
|
+
</g>
|
|
98
|
+
<path d="m27 360 14 50H12L0 360Z" fill="#8b9a82"/>
|
|
99
|
+
<!-- Rear cartons give the moving parcels a real contact surface. -->
|
|
100
|
+
<g :filter="`url(#${uid}-soft)`" data-part="pile-back">
|
|
101
|
+
<use :href="`#${uid}-box`" transform="translate(506 585) rotate(-9) scale(1.1)" style="--box-front:#b48d63;--box-side:#97754f;--box-top:#d3b07e"/>
|
|
102
|
+
<use :href="`#${uid}-box`" transform="translate(680 551) rotate(13) scale(1.02)" style="--box-front:#bf9e71;--box-side:#a1835b;--box-top:#d9bf91"/>
|
|
103
|
+
<use :href="`#${uid}-box`" transform="translate(615 499) rotate(-7) scale(.99)" style="--box-front:#b68d5e;--box-side:#946e4d;--box-top:#d9b17a"/>
|
|
104
|
+
<use :href="`#${uid}-box`" transform="translate(750 582) rotate(18) scale(.96)" style="--box-front:#c4ae7e;--box-side:#9d8b64;--box-top:#e0cc9f"/>
|
|
105
|
+
<path d="m563 448 38-7 28 20-50 10Z" fill="#dfba80"/>
|
|
106
|
+
</g>
|
|
107
|
+
<!-- Actors enter from outside the frame and leave behind opaque cartons. -->
|
|
108
|
+
<g data-part="parcels" :filter="`url(#${uid}-soft)`"><g data-parcel="0" transform="translate(-1200 900)"><use :href="`#${uid}-box`"/></g><g data-parcel="1" transform="translate(-1200 900)"><use :href="`#${uid}-box`"/></g><g data-parcel="2" transform="translate(-1200 900)"><use :href="`#${uid}-box`"/></g><g data-parcel="3" transform="translate(-1200 900)"><use :href="`#${uid}-box`"/></g><g data-parcel="4" transform="translate(-1200 900)"><use :href="`#${uid}-box`"/></g></g>
|
|
109
|
+
<!-- A foreground mountain conceals each reset, without fading any carton. -->
|
|
110
|
+
<path d="m393 650 66-113 69-48 36-34 67-7 51 53 78 33 111 86 20 52Z" fill="#ac8b61"/>
|
|
111
|
+
<g :filter="`url(#${uid}-soft)`">
|
|
112
|
+
<use :href="`#${uid}-box`" transform="translate(474 589) rotate(-15) scale(1.02)" style="--box-front:#b9a272;--box-side:#96875d;--box-top:#d3c195"/>
|
|
113
|
+
<use :href="`#${uid}-box`" transform="translate(553 560) rotate(-8) scale(1.13)" style="--box-front:#cfac76;--box-side:#aa8456;--box-top:#e3c393"/>
|
|
114
|
+
<g data-part="impact-carton"><use :href="`#${uid}-box`" transform="translate(594 511) rotate(5) scale(.91)" style="--box-front:#cba06a;--box-side:#a87f53;--box-top:#e8c58f"/></g>
|
|
115
|
+
<use :href="`#${uid}-box`" transform="translate(665 573) rotate(9) scale(1.13)" style="--box-front:#c29b69;--box-side:#9c7a51;--box-top:#ddbd88"/>
|
|
116
|
+
<use :href="`#${uid}-box`" transform="translate(732 598) rotate(16) scale(1.05)" style="--box-front:#b49a6a;--box-side:#938158;--box-top:#d0b887"/>
|
|
117
|
+
</g>
|
|
118
|
+
<g data-part="impact-dust" fill="#efe0b9"><path d="m0-2 4-2 3 3-4 3Z"/><path d="m-19 2 4-3 2 3-3 2Z"/><path d="m17 1 3-3 3 3-3 2Z"/></g>
|
|
119
|
+
<!-- The work is waiting; its operator is very much asleep. -->
|
|
120
|
+
<g transform="translate(960 604)" :filter="`url(#${uid}-soft)`" data-part="koala-station"><!-- Paper-cut koala. Local ground: (0, 0). Suggested breath pivot: (8, -57).
|
|
121
|
+
The chair and feet stay planted; only the nested breathing group moves. -->
|
|
122
|
+
<g data-part="koala-chair">
|
|
123
|
+
<ellipse cx="9" cy="4" rx="104" ry="10" fill="#5b513f" fill-opacity=".12"/>
|
|
124
|
+
<!-- Splayed rear legs and the far side of the timber frame. -->
|
|
125
|
+
<path d="m50-97 17-3 24 103-13 3Z" fill="#8e684b"/>
|
|
126
|
+
<path d="m-46-91 15 1-38 95-13-2Z" fill="#997453"/>
|
|
127
|
+
<path d="m-64-194 12-12 132-20 12 10-16 141-14 7Z" fill="#ad825b"/>
|
|
128
|
+
<path d="m-52-206 132-20 12 10-133 23Z" fill="#d3ac78"/>
|
|
129
|
+
<path d="m80-226 12 10-16 141-14 7Z" fill="#855f46"/>
|
|
130
|
+
<path d="m-53-190 128-22-13 119-118 15Z" fill="#7d8e78"/>
|
|
131
|
+
<path d="m-53-190 38-6-8 108-33 10Z" fill="#8e9c83"/>
|
|
132
|
+
<path d="m-15-196 90-16-13 119-45 6Z" fill="#78856f"/>
|
|
133
|
+
<path d="m-45-183 111-20-2 15-110 20Z" fill="#a8b196"/>
|
|
134
|
+
<path d="m-49-141 111-19-2 16-110 18Z" fill="#9ca78d"/>
|
|
135
|
+
<path d="m-54-98 111-19-2 15-109 17Z" fill="#8e9b81"/>
|
|
136
|
+
<!-- Seat with a visible front edge; every leg meets its underside. -->
|
|
137
|
+
<path d="m-75-77 126-14 36 23-137 17Z" fill="#a5ac8a"/>
|
|
138
|
+
<path d="m-75-77 25 26 137-17-1 12-136 18-26-25Z" fill="#af835c"/>
|
|
139
|
+
<path d="m-50-51 137-17-1 12-136 18Z" fill="#c29769"/>
|
|
140
|
+
<path d="m-67-67 15 1-5 69-14 1Z" fill="#a87851"/>
|
|
141
|
+
<path d="m64-67 14-1 13 71-14 2Z" fill="#aa7952"/>
|
|
142
|
+
<path d="m-59-28 137-11 2 8-139 12Z" fill="#b88c60"/>
|
|
143
|
+
<path d="m-59-28 137-11 2 3-139 12Z" fill="#d0a572"/>
|
|
144
|
+
<!-- Far armrest, including its upright rather than a floating plank. -->
|
|
145
|
+
<path d="m74-121 10-2-4 67-9 2Z" fill="#976c4b"/>
|
|
146
|
+
<path d="m44-130 43-7 15 9-50 10Z" fill="#d0a575"/>
|
|
147
|
+
<path d="m52-118 50-10-1 8-48 11Z" fill="#a47a56"/>
|
|
148
|
+
<path d="m-49-202 118-20m-117 35 2 29m-13 103 2 38m135-27 5 31" fill="none" stroke="#ecd0a1" stroke-width="1.3" stroke-opacity=".48"/>
|
|
149
|
+
</g>
|
|
150
|
+
|
|
151
|
+
<g data-part="koala-feet">
|
|
152
|
+
<!-- Loose heels rest in front of the seat; neither foot changes with a breath. -->
|
|
153
|
+
<path d="M-38-69Q-54-68-61-53L-69-27Q-69-17-58-12L-37-10Q-26-13-25-22L-22-47Z" fill="#979f99"/>
|
|
154
|
+
<path d="M-52-55Q-61-37-62-25L-52-18-36-20-30-30-31-52Z" fill="#b5bcb1"/>
|
|
155
|
+
<path d="M-63-27Q-75-24-76-17Q-77-9-64-6L-38-6Q-25-8-25-17L-35-24Z" fill="#b6bcb1"/>
|
|
156
|
+
<path d="m-71-14 7-1m3 2 7-2m3 2 7-2" stroke="#777e76" stroke-width="1.5" stroke-linecap="round"/>
|
|
157
|
+
<path d="M28-65Q47-64 54-47L61-25Q62-16 52-11L31-10Q18-12 17-23L14-44Z" fill="#929d95"/>
|
|
158
|
+
<path d="m30-56 17 10 6 22-10 8-16-4-5-17Z" fill="#b8c0b4"/>
|
|
159
|
+
<path d="M31-25Q46-26 56-19L70-13Q75-7 67-3L37-2Q24-3 21-10L22-18Z" fill="#bfc5b9"/>
|
|
160
|
+
<path d="m46-9 7 1m-18-1 7 1m14-2 7 2" stroke="#7d857c" stroke-width="1.5" stroke-linecap="round"/>
|
|
161
|
+
</g>
|
|
162
|
+
|
|
163
|
+
<g data-part="koala-breath">
|
|
164
|
+
<!-- The torso slumps into its seat, with an asymmetric paper-fold silhouette. -->
|
|
165
|
+
<path d="M-29-173Q-53-166-58-142L-62-109Q-62-79-42-60L-16-48 22-48Q54-54 63-79L69-109Q71-141 49-159L16-173Z" fill="#a9b2a8"/>
|
|
166
|
+
<path d="m-29-173-23 24-10 40q0 30 20 49l26 12-14-34-7-46 10-35Z" fill="#919e95"/>
|
|
167
|
+
<path d="M-9-159Q15-167 35-146L45-115Q48-88 30-66L8-59-16-66Q-35-85-33-111L-26-139Z" fill="#dedfce"/>
|
|
168
|
+
<path d="m-26-139-7 28q-2 26 17 45l24 7-17-18-9-35 7-47Z" fill="#c6cdbb"/>
|
|
169
|
+
<path d="m4-154 23 7 9 27-7-9-4-15Z" fill="#f0ebd7"/>
|
|
170
|
+
<!-- An unbuttoned faded work vest leaves the pale belly visible. -->
|
|
171
|
+
<path d="m-30-174 21 11-12 29-3 42 10 39-26-8-17-28-4-28 9-32Z" fill="#81917a"/>
|
|
172
|
+
<path d="m-30-174 10 6-13 27-6 39 9 33-10-8-11-31 7-36Z" fill="#9eac8c"/>
|
|
173
|
+
<path d="m27-164 20 4 18 24 5 26-8 31-18 22-21 7 14-32 6-36-3-28Z" fill="#6f8470"/>
|
|
174
|
+
<path d="m27-164 20 4-5 22 4 25-9 31 6-36-3-28Z" fill="#a0af91"/>
|
|
175
|
+
<path d="m-44-115 19 3-1 21-16-1-5-8Z" fill="#6d806a"/>
|
|
176
|
+
<path d="m-43-114 17 3m-15 17 13 1" fill="none" stroke="#bcc2a0" stroke-width="1.1" stroke-opacity=".7"/>
|
|
177
|
+
<path d="m48-108 11-3-3 18-9 4Z" fill="#586f60"/>
|
|
178
|
+
<path d="m-26-135 5 3m63-4 5-1" stroke="#e1d4aa" stroke-width="2.8" stroke-linecap="round"/>
|
|
179
|
+
|
|
180
|
+
<!-- The far arm has gone completely limp over its armrest. -->
|
|
181
|
+
<path d="M51-146Q63-149 72-135L81-117 89-105 91-84Q91-73 82-71L70-76 67-91 66-107 54-121Z" fill="#929f96"/>
|
|
182
|
+
<path d="m56-143 11 7 7 21 9 16-1 18-7-1-2-20-11-17Z" fill="#b5bdb0"/>
|
|
183
|
+
<path d="m76-79 1-8m5 10 1-9m4 6-1-8" stroke="#738073" stroke-width="1.4" stroke-linecap="round"/>
|
|
184
|
+
|
|
185
|
+
<!-- Head hinge is intentionally outside the resting tilt, so animated nods
|
|
186
|
+
can be tiny without overwriting the authored sleeping posture. -->
|
|
187
|
+
<g data-part="koala-head">
|
|
188
|
+
<g transform="rotate(13 21 -184)">
|
|
189
|
+
<!-- Rounded scallops read as fur at scene scale, never as pointed ears. -->
|
|
190
|
+
<path d="M-19-231Q-30-247-45-246Q-59-249-64-240Q-77-240-81-227Q-88-216-81-206Q-83-192-71-186Q-63-175-50-180Q-38-175-27-185L-16-211Z" fill="#99a69d"/>
|
|
191
|
+
<path d="M-42-237Q-59-241-69-229Q-78-216-71-204L-63-194Q-49-190-37-201L-29-217Z" fill="#d0d1c1"/>
|
|
192
|
+
<path d="m-53-232-13 11 2 15 10 7 12-4 7-15-6-12Z" fill="#bcc5b6"/>
|
|
193
|
+
<path d="M61-231Q72-247 87-244Q101-246 107-235Q119-233 120-220Q126-208 118-198Q118-186 106-181Q96-172 84-179Q71-176 63-190L55-211Z" fill="#8d9c94"/>
|
|
194
|
+
<path d="M79-235Q94-241 105-227Q113-215 107-202Q101-190 88-191L74-201 70-219Z" fill="#d4d4c3"/>
|
|
195
|
+
<path d="m82-230 14 1 8 12-4 14-11 6-9-9-5-14Z" fill="#bfc8b9"/>
|
|
196
|
+
<!-- Broad cheek shape with small flat facets along the cut-paper edge. -->
|
|
197
|
+
<path d="M-26-218-10-234 11-241 38-239 60-227 73-208 78-185 69-164 49-151 21-147-7-154-27-170-36-191Z" fill="#b4bdb1"/>
|
|
198
|
+
<path d="m-26-218 16-16 21-7-13 22-11 28 6 29 14 15-14-7-20-16-9-21Z" fill="#a0ada3"/>
|
|
199
|
+
<path d="m11-241 27 2 22 12 13 19-26-14-27-3-22 6Z" fill="#ced0bf"/>
|
|
200
|
+
<path d="m47-222 26 14 5 23-9 21-20 13-28 4 21-11 13-19 2-24Z" fill="#a2afa4"/>
|
|
201
|
+
<!-- Soft pale cheeks meet underneath the large characteristic nose. -->
|
|
202
|
+
<path d="M-17-185Q-5-196 11-185L22-169 40-170 56-185Q68-185 66-174L55-161 34-153 14-154-4-161-16-173Z" fill="#d4d7c5"/>
|
|
203
|
+
<path d="m-15-178 14 7 15 3 7 11-7 3-18-7-12-12Z" fill="#c4cbb8"/>
|
|
204
|
+
<ellipse cx="-10" cy="-177" rx="10" ry="5.5" fill="#c1aca0" fill-opacity=".55"/>
|
|
205
|
+
<ellipse cx="61" cy="-177" rx="8" ry="4.5" fill="#c1aca0" fill-opacity=".48"/>
|
|
206
|
+
<!-- Closed eyes curve downward. Tiny lashes rest rather than frown. -->
|
|
207
|
+
<path d="M-18-194Q-10-185-1-192M47-192Q55-184 63-192" fill="none" stroke="#4d5a50" stroke-width="2.6" stroke-linecap="round"/>
|
|
208
|
+
<path d="m-15-190-3 2m76-1 3 2" fill="none" stroke="#4d5a50" stroke-width="1.7" stroke-linecap="round"/>
|
|
209
|
+
<!-- A charcoal pear-oval nose with one broad, subdued paper highlight. -->
|
|
210
|
+
<path d="M14-213Q22-218 30-213Q39-206 40-192L38-177Q34-168 24-168Q13-169 9-177L8-193Q7-207 14-213Z" fill="#414b43"/>
|
|
211
|
+
<path d="M15-211Q20-215 26-212L29-207 28-187 24-179 15-182 12-193Z" fill="#68776a"/>
|
|
212
|
+
<path d="m15-207 3-4 5 1-1 7-4 4-3-2Z" fill="#8a9581"/>
|
|
213
|
+
<path d="M24-165Q29-166 30-161Q30-157 26-157Q23-159 24-165Z" fill="#788472"/>
|
|
214
|
+
<!-- A few light paper fibres; no outline around the head. -->
|
|
215
|
+
<path d="m-22-213 5 3m5-14 7 3m50-1 5 4m-18 67 6-2m-86-78 4 6m146 2-3 6" fill="none" stroke="#f1eddb" stroke-width="1" stroke-opacity=".57"/>
|
|
216
|
+
</g>
|
|
217
|
+
</g>
|
|
218
|
+
|
|
219
|
+
<!-- Near arm crosses its own vest seam, then hangs beyond the chair. -->
|
|
220
|
+
<path d="M-34-147Q-49-151-58-136L-68-116-73-92-74-76Q-75-67-67-63L-56-65Q-49-70-52-80L-54-94-47-114-34-129Z" fill="#a4afa4"/>
|
|
221
|
+
<path d="m-43-142-10 9-9 22-5 25 2 15 7-3-2-20 8-24 13-14Z" fill="#c5ccbd"/>
|
|
222
|
+
<path d="m-68-70 1-9m5 10 1-10m5 7-1-9" stroke="#7e8b7d" stroke-width="1.5" stroke-linecap="round"/>
|
|
223
|
+
</g>
|
|
224
|
+
|
|
225
|
+
<!-- The near chair upright stays in front of the wrist, with no impossible
|
|
226
|
+
arm/wood intersections as the belly gently rises and falls. -->
|
|
227
|
+
<g data-part="koala-chair-front">
|
|
228
|
+
<path d="m-83-119 9-1 4 64-10 1Z" fill="#a57b55"/>
|
|
229
|
+
<path d="m-93-121 33-5 18 7-36 8Z" fill="#d7b07b"/>
|
|
230
|
+
<path d="m-93-121 15 10 36-8-1 7-37 8-13-9Z" fill="#b2895e"/>
|
|
231
|
+
<path d="m-83-114 6 4 3 51-4-1Z" fill="#cca070"/>
|
|
232
|
+
</g>
|
|
233
|
+
</g>
|
|
234
|
+
<g data-part="workstation" :filter="`url(#${uid}-soft)`">
|
|
235
|
+
<path d="m820 608 61-3 16 11-81 2Z" fill="#526454" fill-opacity=".17"/>
|
|
236
|
+
<path d="M848 508h16l6 98h-24Z" fill="#728772"/>
|
|
237
|
+
<path d="M845 604h29l9 7h-48Z" fill="#5c7363"/>
|
|
238
|
+
<path d="m806 479 80-6 18 25-87 7Z" fill="#a2b197"/>
|
|
239
|
+
<path d="m817 505 87-7-1 28-87 6Z" fill="#7f967f"/>
|
|
240
|
+
<path d="m806 479 11 26-1 27-10-29Z" fill="#607c6b"/>
|
|
241
|
+
<path d="m813 481 68-5 13 17-73 6Z" fill="#c1c9aa"/>
|
|
242
|
+
<path d="m846 486 21-2 2 8-21 2Z" fill="#c88e6c"/>
|
|
243
|
+
<ellipse cx="835" cy="490" rx="6" ry="4" fill="#6d8770"/>
|
|
244
|
+
<path d="m873 480 9-1 5 7-9 1Z" fill="#e0d1a7"/>
|
|
245
|
+
<path d="M820 518h29" stroke="#b2c1a1" stroke-width="3"/>
|
|
246
|
+
</g>
|
|
247
|
+
<!-- These nearest cartons occlude the station feet and the koala's feet. -->
|
|
248
|
+
<g data-part="pile-front" :filter="`url(#${uid}-soft)`">
|
|
249
|
+
<use :href="`#${uid}-box`" transform="translate(432 654) rotate(-12) scale(1.03)" style="--box-front:#c7a77b;--box-side:#a98c60;--box-top:#e2c795"/>
|
|
250
|
+
<use :href="`#${uid}-box`" transform="translate(521 648) rotate(1) scale(1.24)" style="--box-front:#c7a06e;--box-side:#a77e51;--box-top:#e2bd83"/>
|
|
251
|
+
<use :href="`#${uid}-box`" transform="translate(621 655) rotate(-8) scale(1.13)" style="--box-front:#b89a6c;--box-side:#9a7a50;--box-top:#d6b889"/>
|
|
252
|
+
<use :href="`#${uid}-box`" transform="translate(719 663) rotate(6) scale(1.12)" style="--box-front:#cfab76;--box-side:#ac8958;--box-top:#e8c68f"/>
|
|
253
|
+
<use :href="`#${uid}-box`" transform="translate(812 655) rotate(20) scale(.95)" style="--box-front:#b6a374;--box-side:#92835f;--box-top:#d5c396"/>
|
|
254
|
+
</g>
|
|
255
|
+
<!-- A scanner hangs unused beside the chair. -->
|
|
256
|
+
<path d="M1005 535q27 22 11 41t20 29" stroke="#6f7968" stroke-width="2.5" fill="none"/>
|
|
257
|
+
<path d="m1006 525 15 5-6 12-11-4-5 11-7-3Z" fill="#657c70"/>
|
|
258
|
+
<path d="m1007 525 14 5-3 5-14-5Z" fill="#adc0a4"/>
|
|
259
|
+
<g data-part="sleep-breath" fill="none" stroke="#889582" stroke-width="2.3" stroke-linecap="round">
|
|
260
|
+
<path data-sleep="0" d="M1022 325q12-6 5-14t3-14"/>
|
|
261
|
+
<path data-sleep="1" d="M1042 316q11-6 4-14t3-14"/>
|
|
262
|
+
</g>
|
|
263
|
+
<!-- Eucalyptus cutouts balance the far edge of the scene. -->
|
|
264
|
+
<g transform="translate(1111 615)">
|
|
265
|
+
<ellipse cx="0" cy="1" rx="45" ry="8" fill="#5f725c" fill-opacity=".16"/>
|
|
266
|
+
<path d="m-27-61 57-2-9 60-41 3Z" fill="#b68f6e"/>
|
|
267
|
+
<path d="m-27-61 13 6 5 54-11 1Z" fill="#c8a481"/>
|
|
268
|
+
<path d="m-30-66 62-2 0 14-61 2Z" fill="#cfb28b"/>
|
|
269
|
+
<path d="M0-65-5-162M-2-113-25-146M-3-130 23-169M-4-156-26-184" stroke="#88957b" stroke-width="3" fill="none"/>
|
|
270
|
+
<g color="#8d9f83"><use :href="`#${uid}-leaf`" transform="translate(-5 -158) rotate(-12)"/><use :href="`#${uid}-leaf`" transform="translate(-22 -145) rotate(-56) scale(.88)"/><use :href="`#${uid}-leaf`" transform="translate(16 -159) rotate(60) scale(.92)"/><use :href="`#${uid}-leaf`" transform="translate(-24 -180) rotate(-35) scale(.8)"/></g>
|
|
271
|
+
<g color="#a6b393"><use :href="`#${uid}-leaf`" transform="translate(-1 -114) rotate(58) scale(.86)"/><use :href="`#${uid}-leaf`" transform="translate(-3 -133) rotate(-64) scale(.83)"/><use :href="`#${uid}-leaf`" transform="translate(23 -168) rotate(10) scale(.82)"/></g>
|
|
272
|
+
</g>
|
|
273
|
+
<g fill="#cbb98f"><path d="m309 630 14-6 10 3-15 7Z"/><path d="m349 595 8-2 5 2-7 3Z"/><path d="m900 656 15-3 12 3-14 4Z"/></g>
|
|
274
|
+
<path d="m288 634 30-3m580 31 25-2m143-25 16 1" stroke="#b5a886" stroke-width="1.3"/>
|
|
275
|
+
</g>
|
|
276
|
+
<path d="M0 0H1200V720H0Z" :fill="`url(#${uid}-grain)`" pointer-events="none"/>
|
|
277
|
+
</g>
|
|
278
|
+
</svg>
|
|
279
|
+
</div>
|
|
280
|
+
<figcaption class="unavailable-scene__caption">
|
|
281
|
+
<p class="unavailable-scene__label" data-story-label>包裹到了。值班员呢?</p>
|
|
282
|
+
<div class="unavailable-scene__controls" role="group" aria-label="动画控制">
|
|
283
|
+
<button class="unavailable-scene__button" type="button" data-action="pause" aria-label="暂停动画" aria-pressed="false">暂停</button>
|
|
284
|
+
<button class="unavailable-scene__button" type="button" data-action="replay" aria-label="重播开场动画">重播</button>
|
|
285
|
+
</div>
|
|
286
|
+
</figcaption>
|
|
287
|
+
</figure>
|
|
288
|
+
</template>
|
|
289
|
+
|
|
290
|
+
<script setup lang="ts">
|
|
291
|
+
import { onBeforeUnmount, onMounted, ref, useId, watch } from 'vue'
|
|
292
|
+
|
|
293
|
+
const props = defineProps({
|
|
294
|
+
theme: { type: String, default: 'auto' },
|
|
295
|
+
reducedMotion: { type: Boolean, default: false }
|
|
296
|
+
})
|
|
297
|
+
const root = ref<HTMLElement | null>(null)
|
|
298
|
+
const uid = `paper-503-${useId().replace(/[^a-zA-Z0-9_-]/g, '')}`
|
|
299
|
+
let player: ReturnType<typeof createUnavailableScene> | undefined
|
|
300
|
+
|
|
301
|
+
function createUnavailableScene(root: HTMLElement, options: { reducedMotion?: boolean } = {}) {
|
|
302
|
+
const svg = root.querySelector<SVGSVGElement>('[data-scene]')!;
|
|
303
|
+
const part = (name: string) => svg.querySelector<SVGGraphicsElement>(`[data-part="${name}"]`)!;
|
|
304
|
+
const camera = part('camera');
|
|
305
|
+
const parcels = [...svg.querySelectorAll('[data-parcel]')];
|
|
306
|
+
const ribs = part('belt-ribs');
|
|
307
|
+
const bottomRibs = part('belt-bottom-ribs');
|
|
308
|
+
const roller = part('roller');
|
|
309
|
+
const breath = part('koala-breath');
|
|
310
|
+
const head = part('koala-head');
|
|
311
|
+
const bump = part('impact-carton');
|
|
312
|
+
const dust = part('impact-dust');
|
|
313
|
+
const sleepLines = [...svg.querySelectorAll('[data-sleep]')];
|
|
314
|
+
const pauseButton = root.querySelector<HTMLButtonElement>('[data-action="pause"]');
|
|
315
|
+
const replayButton = root.querySelector('[data-action="replay"]');
|
|
316
|
+
const label = root.querySelector('[data-story-label]');
|
|
317
|
+
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
318
|
+
let time = 0, raf = 0, disposed = false, paused = false, offscreen = false;
|
|
319
|
+
let last: number | null = null;
|
|
320
|
+
let story = '', userMotion = false, appReduced = Boolean(options.reducedMotion);
|
|
321
|
+
const prefersReduced = () => appReduced || reduced.matches;
|
|
322
|
+
const interval = 2.65, count = parcels.length, cycle = count * interval;
|
|
323
|
+
// The back-right bottom corner is 16 units above the front bottom edge.
|
|
324
|
+
// Put that back corner on the belt at y=343 so the whole carton sits on it.
|
|
325
|
+
const beltParcelY = 359;
|
|
326
|
+
const clamp = (x: number) => Math.max(0, Math.min(1, x));
|
|
327
|
+
const smooth = (x: number) => { x = clamp(x); return x * x * x * (x * (6 * x - 15) + 10); };
|
|
328
|
+
const lerp = (a: number, b: number, t: number) => a + (b-a)*t;
|
|
329
|
+
function setStory(next: 'intro' | 'settled') {
|
|
330
|
+
if (next === story) return;
|
|
331
|
+
story = next;
|
|
332
|
+
root.dataset.story = next;
|
|
333
|
+
if (label) label.textContent = next === 'intro' ? '包裹到了。值班员呢?' : '包裹在赶路,值班员在做梦。';
|
|
334
|
+
}
|
|
335
|
+
function pose(age: number) {
|
|
336
|
+
if (age < 5) return { x: -160 + 126 * age, y: beltParcelY, angle: 0 };
|
|
337
|
+
if (age < 5.7) {
|
|
338
|
+
const u = (age - 5) / .7;
|
|
339
|
+
return { x: 470 + 88.2 * u, y: beltParcelY + (431 - beltParcelY) * u * u, angle: 27 * u * u };
|
|
340
|
+
}
|
|
341
|
+
if (age < 6.18) {
|
|
342
|
+
const u = (age - 5.7) / .48;
|
|
343
|
+
return { x: 558.2 + 30 * u, y: 431 + 4 * u - 18 * Math.sin(Math.PI * u), angle: 27 - 17 * Math.sin(Math.PI * .5 * u) };
|
|
344
|
+
}
|
|
345
|
+
const u = clamp((age - 6.18) / 1.05);
|
|
346
|
+
return { x: 588.2 + 62 * u, y: 435 + 205 * u * u, angle: 10 + 52 * u };
|
|
347
|
+
}
|
|
348
|
+
function draw(t: number, still = false) {
|
|
349
|
+
const reveal = still ? 1 : smooth((t - 3.95) / 2.45);
|
|
350
|
+
const tracking = smooth(t / 3.85);
|
|
351
|
+
const scale = lerp(2.12, 1, reveal);
|
|
352
|
+
const focusX = lerp(lerp(273, 510, tracking), 600, reveal);
|
|
353
|
+
const focusY = lerp(lerp(311, 383, tracking), 360, reveal);
|
|
354
|
+
camera.setAttribute('transform', `translate(${600 - focusX * scale} ${360 - focusY * scale}) scale(${scale})`);
|
|
355
|
+
setStory(reveal >= .999 ? 'settled' : 'intro');
|
|
356
|
+
ribs.setAttribute('transform', `translate(${(t * 126) % 24} 0)`);
|
|
357
|
+
bottomRibs.setAttribute('transform', `translate(${-((t * 126) % 24)} 0)`);
|
|
358
|
+
roller.setAttribute('transform', `rotate(${t * 126 / 21 * 180 / Math.PI})`);
|
|
359
|
+
let latestImpact = Infinity;
|
|
360
|
+
parcels.forEach((parcel, i) => {
|
|
361
|
+
// Every reused actor begins beyond the left frame and finishes fully occluded.
|
|
362
|
+
const elapsed = t + 2.05 - i * interval;
|
|
363
|
+
if (elapsed < 0) { parcel.setAttribute('transform', 'translate(-1200 900)'); return; }
|
|
364
|
+
const age = elapsed % cycle;
|
|
365
|
+
if (age > 7.05) { parcel.setAttribute('transform', 'translate(-1200 900)'); return; }
|
|
366
|
+
const p = pose(age);
|
|
367
|
+
parcel.setAttribute('transform', `translate(${p.x.toFixed(3)} ${p.y.toFixed(3)}) rotate(${p.angle.toFixed(3)})`);
|
|
368
|
+
if (age >= 5.7) latestImpact = Math.min(latestImpact, age - 5.7);
|
|
369
|
+
});
|
|
370
|
+
const hit = latestImpact < .48 ? Math.sin(latestImpact / .48 * Math.PI * 2) * (1 - latestImpact / .48) : 0;
|
|
371
|
+
bump.setAttribute('transform', `rotate(${hit * 1.7} 594 511)`);
|
|
372
|
+
if (latestImpact < .5) {
|
|
373
|
+
const u = latestImpact / .5, s = Math.sin(Math.PI * u) * .85;
|
|
374
|
+
dust.setAttribute('transform', `translate(${569 + u * 9} ${441 - u * 21}) scale(${s})`);
|
|
375
|
+
} else dust.setAttribute('transform', 'translate(569 441) scale(0)');
|
|
376
|
+
const inhale = (1 - Math.cos(t * Math.PI * 2 / 4.4)) / 2;
|
|
377
|
+
if (breath) breath.setAttribute('transform', `translate(0 ${-inhale * 1.8}) translate(0 -49) scale(${1 + inhale * .009} ${1 + inhale * .014}) translate(0 49)`);
|
|
378
|
+
if (head) head.setAttribute('transform', `rotate(${Math.sin(t * Math.PI * 2 / 4.4 - .3) * .6} 21 -184)`);
|
|
379
|
+
sleepLines.forEach((line,i) => line.setAttribute('transform', `translate(${Math.sin(t * .7 + i) * 2} ${Math.sin(t * 1.1 + i) * 3})`));
|
|
380
|
+
root.dataset.camera = reveal >= .999 ? 'wide' : 'close';
|
|
381
|
+
root.dataset.time = t.toFixed(2);
|
|
382
|
+
}
|
|
383
|
+
function canRun() { return !disposed && !paused && !document.hidden && !offscreen && (!prefersReduced() || userMotion); }
|
|
384
|
+
function updateButtons() {
|
|
385
|
+
const isStill = prefersReduced() && !userMotion;
|
|
386
|
+
if (pauseButton) {
|
|
387
|
+
pauseButton.disabled = isStill;
|
|
388
|
+
pauseButton.textContent = paused ? '继续' : '暂停';
|
|
389
|
+
pauseButton.setAttribute('aria-label', paused ? '继续动画' : '暂停动画');
|
|
390
|
+
pauseButton.setAttribute('aria-pressed', String(paused));
|
|
391
|
+
}
|
|
392
|
+
root.dataset.playing = String(canRun());
|
|
393
|
+
}
|
|
394
|
+
function frame(now: number) {
|
|
395
|
+
raf = 0;
|
|
396
|
+
if (!canRun()) { last = null; return; }
|
|
397
|
+
// Positions are analytic, so actual elapsed time stays correct at low frame rates.
|
|
398
|
+
// Visibility/pause events reset `last` before resuming.
|
|
399
|
+
if (last !== null) time += Math.max(0, (now - last) / 1000);
|
|
400
|
+
last = now;
|
|
401
|
+
draw(time);
|
|
402
|
+
raf = requestAnimationFrame(frame);
|
|
403
|
+
}
|
|
404
|
+
function sync() {
|
|
405
|
+
if (raf) cancelAnimationFrame(raf);
|
|
406
|
+
raf = 0; last = null;
|
|
407
|
+
updateButtons();
|
|
408
|
+
if (canRun()) raf = requestAnimationFrame(frame);
|
|
409
|
+
}
|
|
410
|
+
function replay() { userMotion = true; paused = false; time = 0; draw(0); sync(); }
|
|
411
|
+
function togglePause() { paused = !paused; sync(); }
|
|
412
|
+
function motionChanged() {
|
|
413
|
+
userMotion = false;
|
|
414
|
+
if (prefersReduced()) draw(8, true);
|
|
415
|
+
else { time = Math.max(time, 8); draw(time); }
|
|
416
|
+
sync();
|
|
417
|
+
}
|
|
418
|
+
pauseButton?.addEventListener('click', togglePause);
|
|
419
|
+
replayButton?.addEventListener('click', replay);
|
|
420
|
+
reduced.addEventListener('change', motionChanged);
|
|
421
|
+
document.addEventListener('visibilitychange', sync);
|
|
422
|
+
const observer = 'IntersectionObserver' in window ? new IntersectionObserver(entries => {
|
|
423
|
+
offscreen = !entries[0].isIntersecting; sync();
|
|
424
|
+
}, {threshold: 0}) : null;
|
|
425
|
+
observer?.observe(svg);
|
|
426
|
+
draw(prefersReduced() ? 8 : 0, prefersReduced());
|
|
427
|
+
sync();
|
|
428
|
+
return {
|
|
429
|
+
replay,
|
|
430
|
+
setReducedMotion(value: boolean) { appReduced = Boolean(value); motionChanged(); },
|
|
431
|
+
setPaused(value: boolean) { paused = Boolean(value); sync(); },
|
|
432
|
+
dispose() {
|
|
433
|
+
disposed = true;
|
|
434
|
+
cancelAnimationFrame(raf);
|
|
435
|
+
observer?.disconnect();
|
|
436
|
+
reduced.removeEventListener('change', motionChanged);
|
|
437
|
+
document.removeEventListener('visibilitychange', sync);
|
|
438
|
+
pauseButton?.removeEventListener('click', togglePause);
|
|
439
|
+
replayButton?.removeEventListener('click', replay);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
onMounted(() => { if (root.value) player = createUnavailableScene(root.value, { reducedMotion: props.reducedMotion }) })
|
|
446
|
+
watch(() => props.reducedMotion, value => player?.setReducedMotion(value))
|
|
447
|
+
onBeforeUnmount(() => { player?.dispose() })
|
|
448
|
+
</script>
|
|
449
|
+
|
|
450
|
+
<style scoped>
|
|
451
|
+
.paper-503-shell {
|
|
452
|
+
--page-bg: #f7f6f0; --page-text: #393e34; --page-secondary: #797d6e; --page-button: #697c63; --page-button-hover: #52694d;
|
|
453
|
+
--scene-wall-top: #efe5d1; --scene-wall: #e3dcc2; --scene-floor: #cec7a3; --scene-floor-edge: #b8b597; --scene-floor-line: #b4ac87; --scene-frame-shadow: #d8d0be; --scene-timber: #b6a17e;
|
|
454
|
+
color: var(--apple-text, var(--page-text)); background: transparent; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif; -webkit-font-smoothing: antialiased; box-sizing: border-box; width: 100%;
|
|
455
|
+
}
|
|
456
|
+
.paper-503-shell *, .paper-503-shell *::before, .paper-503-shell *::after { box-sizing: border-box; }
|
|
457
|
+
.paper-503-shell.is-dark {
|
|
458
|
+
--page-bg: #222c29; --page-text: #ede9d8; --page-secondary: #b2b9a6; --page-button: #83957a; --page-button-hover: #98aa8c;
|
|
459
|
+
--scene-wall-top: #4b5648; --scene-wall: #56614d; --scene-floor: #777d5e; --scene-floor-edge: #535f4b; --scene-floor-line: #59674f; --scene-frame-shadow: #16251f; --scene-timber: #9a896a;
|
|
460
|
+
}
|
|
461
|
+
@media (prefers-color-scheme: dark) {
|
|
462
|
+
.paper-503-shell:not(.is-light) {
|
|
463
|
+
--page-bg: #222c29; --page-text: #ede9d8; --page-secondary: #b2b9a6; --page-button: #83957a; --page-button-hover: #98aa8c;
|
|
464
|
+
--scene-wall-top: #4b5648; --scene-wall: #56614d; --scene-floor: #777d5e; --scene-floor-edge: #535f4b; --scene-floor-line: #59674f; --scene-frame-shadow: #16251f; --scene-timber: #9a896a;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
.unavailable-scene__button:focus-visible { outline: 2px solid var(--page-button); outline-offset: 4px; }
|
|
468
|
+
.unavailable-scene { margin: 0; position: relative; min-width: 0; }
|
|
469
|
+
.unavailable-scene__window { overflow: hidden; padding: 4px; }
|
|
470
|
+
.unavailable-scene__art { width: 100%; height: auto; display: block; overflow: visible; }
|
|
471
|
+
.unavailable-scene__art [data-part='camera'] { transform-origin: 0 0; }
|
|
472
|
+
.unavailable-scene__caption { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 9px 0 0; padding-inline: 4.5%; min-height: 44px; }
|
|
473
|
+
.unavailable-scene__label { color: var(--apple-secondary, var(--page-secondary)); font-size: 11px; line-height: 1.6; margin: 0; }
|
|
474
|
+
.unavailable-scene__controls { display: flex; flex-shrink: 0; align-items: center; gap: 2px; }
|
|
475
|
+
.unavailable-scene__button { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; border: 0; border-radius: 7px; background: transparent; color: var(--apple-secondary, var(--page-secondary)); font-family: inherit; font-size: 11px; padding: 0 9px; cursor: pointer; }
|
|
476
|
+
.unavailable-scene__button:hover { background: #87917a14; }
|
|
477
|
+
.unavailable-scene__button:disabled { opacity: .5; cursor: default; }
|
|
478
|
+
@media (max-width: 880px) {
|
|
479
|
+
.unavailable-scene { grid-row: 1; }
|
|
480
|
+
.unavailable-scene__window { margin-inline: -10px; }
|
|
481
|
+
.unavailable-scene__caption { margin-top: 0; padding-inline: 2%; }
|
|
482
|
+
}
|
|
483
|
+
@media (max-width: 420px) {
|
|
484
|
+
.unavailable-scene__caption { padding-inline: 0; gap: 0; }
|
|
485
|
+
.unavailable-scene__label, .unavailable-scene__button { font-size: 10px; }
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
</style>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export interface ComponentMetadata { label: string; group: string; description: string }
|
|
2
2
|
|
|
3
3
|
export const componentMetadata: Record<string, ComponentMetadata> = {
|
|
4
|
-
AppleScrollBar: { label: '滚动条', group: '基础', description: '悬浮在内容之上。' },
|
|
5
4
|
AppleButton: {"label":"按钮","group":"基础","description":"清晰的操作层级。"},
|
|
6
5
|
AppleLink: {"label":"链接","group":"基础","description":"让下一步清楚可见。"},
|
|
7
6
|
AppleSearch: {"label":"搜索","group":"基础","description":"快速找到关心的内容。"},
|
|
@@ -62,7 +62,7 @@ export default defineHandbook({
|
|
|
62
62
|
"name": "showFooter",
|
|
63
63
|
"type": "boolean",
|
|
64
64
|
"default": "true",
|
|
65
|
-
"description": "
|
|
65
|
+
"description": "显示默认操作区,确认和取消按钮默认使用 borderless;自定义 footer 插槽始终可以显示。"
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
"name": "closable",
|
|
@@ -15,7 +15,6 @@ const gallery = JSON.stringify([{ src: image('#0071e3', 'Apptify'), alt: '蓝色
|
|
|
15
15
|
const scroll = '<div id="demo-scroll" class="scroll-demo" tabindex="0" aria-label="滚动示例"><div style="height: 900px">向下滚动,体验回到顶部。</div></div>'
|
|
16
16
|
|
|
17
17
|
const examples: Record<string, PlaygroundExample> = {
|
|
18
|
-
AppleScrollBar: { props: { target: '"#demo-scroll"' }, before: '<div id="demo-scroll" class="scroll-demo" tabindex="0" aria-label="滚动示例"><div style="width: 760px; height: 900px; display: grid; gap: 16px"><div v-for="n in 12" :key="n" class="tile">{{ n }}</div></div></div>' },
|
|
19
18
|
AppleButton: { slots: { default: { code: '继续', enabled: true } } },
|
|
20
19
|
AppleLink: { props: { as: '"button"' }, slots: { default: { code: '了解更多', enabled: true } } },
|
|
21
20
|
AppleProvider: { props: { theme: '"dark"' }, slots: { default: { code: '<AppleInput v-model="fieldValue" label="局部主题" /><AppleButton @click="record(\'click\')">继续</AppleButton>', enabled: true } } },
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const errorPages = {
|
|
2
|
+
400: { title: '请求有误', copy: ['这个包裹,猫实在看不懂。', '请检查请求内容后再试。'] },
|
|
3
|
+
403: { title: '无权访问', copy: ['这只鸡腿,可不能随便拿。', '你暂时没有访问此页面的权限。'] },
|
|
4
|
+
404: { title: '页面不存在', copy: ['有些东西,悄悄溜走了。', '就像松鼠的橡果,这一页也不知漂去了哪里。'] },
|
|
5
|
+
429: { title: '慢一点,慢一点。', copy: ['小仓鼠们已经拼尽全力,包裹却还在落下。', '请求过于频繁,请稍后再试。'] },
|
|
6
|
+
500: { title: '服务器内部错误', copy: ['包裹刚送达,服务器就招架不住了。', '请稍后重试,或先回到首页。'] },
|
|
7
|
+
502: { title: '网关错误', copy: ['包裹在城门口被拦住了。', '服务暂时无法响应,请稍后再试。'] },
|
|
8
|
+
503: { title: '服务暂时不可用', copy: ['包裹还在来,值班员却睡着了。', '请稍后再试,让它再缓一会儿。'] },
|
|
9
|
+
} as const
|
|
@@ -104,7 +104,6 @@ button { font: inherit; }
|
|
|
104
104
|
.feed-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-bottom: 14px; border-bottom: 1px solid var(--apple-border); }
|
|
105
105
|
.feed-count { font-size: 12px; font-weight: 500; }
|
|
106
106
|
.feed-count small { margin-left: 7px; color: var(--apple-secondary); font-size: 10px; font-variant-numeric: tabular-nums; }
|
|
107
|
-
.preview-controls { display: flex; gap: 4px; }
|
|
108
107
|
.feed-group { padding-bottom: 16px; }
|
|
109
108
|
.feed-group-heading { display: flex; align-items: baseline; gap: 12px; padding: 32px 0 20px; }
|
|
110
109
|
.feed-group-heading > span { color: var(--apple-secondary); font-size: 11px; font-variant-numeric: tabular-nums; }
|
|
@@ -123,7 +122,6 @@ button { font: inherit; }
|
|
|
123
122
|
.detail-preview .component-demo { width: 100%; max-width: 720px; min-width: 0; margin-inline: auto; }
|
|
124
123
|
.detail-preview .component-demo--compact { max-width: 420px; }
|
|
125
124
|
.detail-preview .component-demo--media { max-width: 560px; }
|
|
126
|
-
.detail-preview.mobile-preview { max-width: 390px; margin-inline: auto; }
|
|
127
125
|
.component-source { border-top: 1px solid color-mix(in srgb,var(--apple-border) 45%,transparent); }
|
|
128
126
|
.code-view { padding: 4px 28px 20px; min-width: 0; }
|
|
129
127
|
.code-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; color: var(--apple-secondary); font-size: 12px; }
|