tools.css 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. * {
  2. padding: 0;
  3. margin: 0;
  4. }
  5. html,
  6. body {
  7. width: 100%;
  8. height: 100%;
  9. background: linear-gradient(160deg, #fff9f2 0%, #ffeedd 100%);
  10. transition: none;
  11. -webkit-tap-highlight-color: transparent; /*消除移动端的灰色背景闪烁*/
  12. -webkit-touch-callout: none; /*系统默认菜单被禁用*/
  13. -webkit-user-select: none; /*webkit浏览器*/
  14. -khtml-user-select: none; /*早期浏览器*/
  15. -moz-user-select: none; /*火狐*/
  16. -ms-user-select: none; /*IE10*/
  17. user-select: none;
  18. }
  19. input,
  20. textarea {
  21. -webkit-user-select: auto; /*webkit浏览器*/
  22. margin: 0px;
  23. padding: 0px;
  24. outline: none;
  25. }
  26. #container {
  27. display: flex;
  28. flex-direction: column;
  29. position: absolute;
  30. left: 0;
  31. top: 0;
  32. height: 100% !important;
  33. width: 100%;
  34. }
  35. /* ── 根布局:全 Flex,无 fixed/absolute 主结构 ──────────── */
  36. /* 竖屏:body flex column */
  37. /* sidebar → display:contents,子项直接排入 body */
  38. /* logo-bar(order:1) → game-col(order:2) → cta(order:10) */
  39. /* 横屏:body flex row,game-col 左(flex:1) + sidebar 右 */
  40. body {
  41. display: flex;
  42. flex-direction: column;
  43. position: relative;
  44. overflow: hidden;
  45. }
  46. /* ── 游戏列:canvas 区 + 工具栏 ── */
  47. #game-col {
  48. order: 2; /* 竖屏:位于 logo(1) 与 cta(10) 之间 */
  49. flex: 1;
  50. min-height: 0; /* 防止 flex 子项无法收缩 */
  51. display: flex;
  52. flex-direction: column;
  53. position: relative; /* promo-screen absolute 定位的父容器 */
  54. }
  55. /* 纯填色区域,flex:1 铺满 game-col 剩余空间 */
  56. #game-area {
  57. flex: 1;
  58. min-height: 0;
  59. position: relative;
  60. }
  61. /* canvas 绝对填满 game-area;syncCanvasSize() 同步像素尺寸 */
  62. #canvas {
  63. position: absolute;
  64. inset: 0;
  65. width: 100%;
  66. height: 100%;
  67. z-index: 1;
  68. }
  69. /* ── 竖屏:sidebar 用 display:contents,子项直接排入 body ── */
  70. #sidebar {
  71. display: contents;
  72. }
  73. .sidebar-flex-spacer {
  74. order: 5;
  75. display: none; /* 竖屏不需要 */
  76. }
  77. /* ── 横屏:body flex row,sidebar 作为右侧固定栏 ─────────── */
  78. @media (orientation: landscape) {
  79. body {
  80. flex-direction: row;
  81. }
  82. #game-col {
  83. order: 1;
  84. flex: 1;
  85. min-width: 0;
  86. }
  87. #sidebar {
  88. display: flex;
  89. order: 2;
  90. flex-direction: column;
  91. align-items: center;
  92. justify-content: flex-start;
  93. gap: 0;
  94. width: clamp(140px, 36%, 260px);
  95. height: 100%;
  96. background: transparent;
  97. padding: clamp(8px, 1.5vh, 16px) clamp(10px, 2vw, 16px);
  98. box-sizing: border-box;
  99. box-shadow: none;
  100. pointer-events: auto;
  101. overflow: hidden;
  102. }
  103. /* spacer 布局改用比例 flex,无需 spacer */
  104. .sidebar-flex-spacer {
  105. display: none;
  106. }
  107. }
  108. #progress-toolbar {
  109. height: clamp(12px, 2.5vh, 20px);
  110. }
  111. #toolbar-bottom {
  112. /* 在 game-col flex column 中正常流,不与 canvas 重叠 */
  113. flex-shrink: 0;
  114. text-align: center;
  115. z-index: 2;
  116. pointer-events: none;
  117. transition:
  118. transform 1s ease-in-out,
  119. opacity 1s ease-in-out;
  120. }
  121. .hidden-toolbar-bottom {
  122. transform: translateY(100%); /* 移出屏幕下方 */
  123. opacity: 0; /* 完全透明 */
  124. }
  125. .hidden-toolbar-right {
  126. transform: translateX(150%); /* 移出屏幕右方 */
  127. opacity: 0; /* 完全透明 */
  128. }
  129. #color-btns {
  130. display: flex;
  131. flex-direction: row;
  132. justify-content: flex-start;
  133. padding: 0px 10px 10px 10px;
  134. overflow-x: scroll;
  135. height: clamp(44px, 8vh, 60px);
  136. align-items: center;
  137. gap: 10px;
  138. user-select: none;
  139. /* 隐藏滚动条但保留滚动功能 */
  140. scrollbar-width: none;
  141. -ms-overflow-style: none;
  142. }
  143. #color-btns::-webkit-scrollbar {
  144. display: none;
  145. }
  146. .color-btn-container {
  147. position: relative;
  148. min-width: clamp(34px, 7vh, 48px);
  149. width: clamp(34px, 7vh, 48px);
  150. height: clamp(34px, 7vh, 48px);
  151. }
  152. .color-btn-container-selected {
  153. transform: scale(1.2);
  154. }
  155. /* SVG 充满容器 */
  156. .color-btn-progress-ring {
  157. width: 100%;
  158. height: 100%;
  159. }
  160. /* 进度条轨道 */
  161. .color-btn-progress-ring-track {
  162. transition: none;
  163. }
  164. /* 动态进度条 */
  165. .color-btn-progress-ring-value {
  166. transition: stroke-dashoffset 0.5s ease-in-out;
  167. transform: rotate(-90deg);
  168. transform-origin: 50% 50%;
  169. }
  170. .color-btn {
  171. position: absolute;
  172. min-width: clamp(28px, 5.5vh, 40px);
  173. width: clamp(28px, 5.5vh, 40px);
  174. height: clamp(28px, 5.5vh, 40px);
  175. line-height: clamp(28px, 5.5vh, 40px);
  176. text-align: center;
  177. border-radius: 50%;
  178. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  179. top: 50%;
  180. left: 50%;
  181. transform: translate(-50%, -50%);
  182. z-index: 2;
  183. box-sizing: border-box;
  184. cursor: pointer;
  185. pointer-events: auto; /*允许button接收事件*/
  186. transition: all 0.2s;
  187. }
  188. #progress-wrapper {
  189. box-sizing: border-box;
  190. display: flex;
  191. align-items: center;
  192. flex-direction: row;
  193. width: 100%;
  194. padding-left: 10px;
  195. padding-right: 10px;
  196. gap: 10px;
  197. }
  198. #progress-bar {
  199. box-sizing: border-box;
  200. flex-grow: 1;
  201. overflow: hidden;
  202. text-align: left;
  203. background-color: lightgray;
  204. border-radius: 2px;
  205. height: 4px;
  206. }
  207. #progress {
  208. transition: width 0.5s ease-in-out;
  209. width: 0%;
  210. height: 4px;
  211. background-color: rgb(7, 206, 7);
  212. }
  213. #percent {
  214. font-size: 12px;
  215. color: rgb(7, 206, 7);
  216. line-height: 12px;
  217. font-weight: 500;
  218. font-family: Arial, Helvetica, sans-serif;
  219. }
  220. /* 各种工具buuton */
  221. .btn-img {
  222. width: 100%;
  223. height: 100%;
  224. }
  225. .btn-img-mask {
  226. position: absolute;
  227. width: 100%;
  228. height: 100%;
  229. top: 0%;
  230. border-radius: 50%;
  231. opacity: 0;
  232. background: black;
  233. }
  234. /* 有兼容性问题, 干脆不用了,直接js代码里监听各种事件来做吧*/
  235. @media (hover: hover) and (pointer: fine) {
  236. .btn-img-mask:hover {
  237. opacity: 0.5;
  238. }
  239. }
  240. /* 移动端,解决按钮按下去再没复原的问题 */
  241. .btn-img-mask:active {
  242. opacity: 0.5;
  243. }
  244. .btn {
  245. z-index: 120;
  246. width: 40px;
  247. height: 40px;
  248. border-radius: 50%;
  249. box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.16);
  250. }
  251. /*adapt firefox*/
  252. @-moz-document url-prefix() {
  253. .star-rating input:checked ~ label::before {
  254. font-size: 36px;
  255. line-height: 21px;
  256. }
  257. }
  258. /*全部完成的撒花动画wrapper*/
  259. .finish-ani-wrapper {
  260. position: absolute;
  261. pointer-events: none;
  262. width: 95vw;
  263. height: 95vh;
  264. z-index: 90;
  265. top: 0%;
  266. }
  267. /*撒花动画的花片样式*/
  268. .finish-ani-div {
  269. position: absolute;
  270. width: 10px;
  271. height: 10px;
  272. top: 0%;
  273. opacity: 1;
  274. z-index: 90;
  275. transition:
  276. top 3s,
  277. left 3s,
  278. opacity 3s;
  279. }
  280. /*爆破动画canvas*/
  281. .finish-ani-canvas {
  282. position: fixed;
  283. pointer-events: none;
  284. bottom: 0px;
  285. z-index: 300;
  286. }
  287. .toast {
  288. position: fixed;
  289. bottom: 20px;
  290. left: 50%;
  291. transform: translateX(-50%);
  292. background: rgba(0, 0, 0, 0.8);
  293. color: white;
  294. padding: 12px 24px;
  295. border-radius: 4px;
  296. animation: fadeInOut 2.5s;
  297. z-index: 9999;
  298. }
  299. .toast-hidden {
  300. display: none;
  301. }
  302. @keyframes fadeInOut {
  303. 0% {
  304. opacity: 0;
  305. bottom: -20px;
  306. }
  307. 20% {
  308. opacity: 1;
  309. bottom: 20px;
  310. }
  311. 80% {
  312. opacity: 1;
  313. bottom: 20px;
  314. }
  315. 100% {
  316. opacity: 0;
  317. bottom: -20px;
  318. }
  319. }
  320. /* ── Canvas 缩小消失动画 ────────────────────────────── */
  321. #canvas.canvas-shrink-out {
  322. transition:
  323. transform 0.55s ease-in,
  324. opacity 0.55s ease-in;
  325. transform: scale(0.05);
  326. opacity: 0;
  327. pointer-events: none;
  328. }
  329. /* ── Logo 栏 ────────────────────────────────────────────── */
  330. /* 竖屏(display:contents 子项):横排,order:1 置顶,z:200 浮于 promo */
  331. /* 横屏(sidebar 内 flex 子项) :竖排,充满宽度 */
  332. #app-logo-bar {
  333. order: 1; /* 竖屏:body 第一行 */
  334. flex: 0 0 clamp(56px, 18dvh, 120px); /* ← 竖屏占屏高 18%,低分屏自动收窄 */
  335. display: flex;
  336. flex-direction: row; /* 竖屏:图标+文字横排 */
  337. align-items: center;
  338. justify-content: center;
  339. gap: clamp(8px, 3vw, 18px);
  340. padding: 0 20px;
  341. box-sizing: border-box;
  342. pointer-events: none;
  343. position: relative;
  344. z-index: 200;
  345. }
  346. #app-logo {
  347. height: clamp(36px, 12dvh, 80px); /* ≈ 55% of bar,低分屏自动收窄 */
  348. width: auto;
  349. display: block;
  350. flex-shrink: 0;
  351. object-fit: contain;
  352. }
  353. #app-logo-txt {
  354. height: clamp(36px, 12dvh, 80px);
  355. width: auto;
  356. max-width: 55%;
  357. display: block;
  358. object-fit: contain;
  359. }
  360. @media (orientation: landscape) {
  361. #app-logo-bar {
  362. /* sidebar 高度的 70%(logo图 4 + logo文字 3) */
  363. flex: 7 7 0;
  364. min-height: 0;
  365. order: 1;
  366. flex-direction: column;
  367. gap: clamp(4px, 1.5vh, 10px);
  368. padding: 0;
  369. width: 80%;
  370. position: static;
  371. z-index: auto;
  372. }
  373. #app-logo {
  374. /* 占 logo-bar 的 ~57%(4/7),用 max-height 限高 */
  375. width: 82%;
  376. height: auto;
  377. max-width: none;
  378. max-height: 55%;
  379. object-fit: contain;
  380. flex-shrink: 1;
  381. }
  382. #app-logo-txt {
  383. /* 占 logo-bar 的 ~43%(3/7) */
  384. width: 68%;
  385. height: auto;
  386. max-width: none;
  387. max-height: 40%;
  388. object-fit: contain;
  389. flex-shrink: 1;
  390. }
  391. }
  392. /* ── 广告标识 ────────────────────────────────────────── */
  393. #ad-badge {
  394. position: fixed;
  395. top: 6px;
  396. right: 8px;
  397. z-index: 300;
  398. background: rgba(0, 0, 0, 0.35);
  399. color: #fff;
  400. font-size: 10px;
  401. font-family: Arial, Helvetica, sans-serif;
  402. font-weight: 600;
  403. letter-spacing: 0.5px;
  404. padding: 2px 6px;
  405. border-radius: 4px;
  406. pointer-events: none;
  407. }
  408. /* ── CTA 按钮容器 ────────────────────────────────────────── */
  409. /* 竖屏(display:contents 子项):order:10 置底,z:200 浮于 promo */
  410. /* 横屏(sidebar 内 flex 子项) :在 spacer 之后贴底 */
  411. #cta-btn-wrapper {
  412. order: 10; /* 竖屏:body 最末行 */
  413. flex: 0 0 clamp(44px, 14dvh, 90px); /* ← 竖屏占屏高 14%,低分屏自动收窄 */
  414. display: flex;
  415. align-items: center;
  416. justify-content: center;
  417. pointer-events: none;
  418. padding: 0 16px;
  419. box-sizing: border-box;
  420. position: relative;
  421. z-index: 200; /* 竖屏:浮于 promo-screen 之上 */
  422. }
  423. @media (orientation: landscape) {
  424. #cta-btn-wrapper {
  425. /* sidebar 高度的 30% */
  426. flex: 3 3 0;
  427. min-height: 0;
  428. order: 10;
  429. width: 90%;
  430. padding: 0;
  431. position: static;
  432. z-index: auto;
  433. }
  434. #cta-btn {
  435. width: 100%;
  436. max-width: none;
  437. height: clamp(42px, 10vh, 54px);
  438. font-size: clamp(13px, 3.5vh, 17px);
  439. letter-spacing: clamp(1px, 0.8vw, 3px);
  440. padding: 0 clamp(8px, 2vw, 24px);
  441. white-space: nowrap;
  442. overflow: hidden;
  443. text-overflow: ellipsis;
  444. }
  445. }
  446. #cta-btn {
  447. pointer-events: auto;
  448. width: min(300px, 80vw);
  449. height: clamp(34px, 7vh, 48px);
  450. border: none;
  451. border-radius: 999px;
  452. background: linear-gradient(135deg, #ff5f1f 0%, #ffb300 100%);
  453. color: #fff;
  454. font-size: clamp(14px, 3vh, 18px);
  455. font-weight: 800;
  456. letter-spacing: clamp(1px, 0.5vw, 3px);
  457. font-family: Arial, Helvetica, sans-serif;
  458. cursor: pointer;
  459. /* 立体感阴影 */
  460. box-shadow:
  461. 0 4px 10px rgba(255, 95, 31, 0.45),
  462. 0 2px 0 rgba(255, 255, 255, 0.25) inset,
  463. 0 -3px 0 rgba(0, 0, 0, 0.18) inset;
  464. /* 按压效果 */
  465. transition:
  466. transform 0.1s ease,
  467. box-shadow 0.1s ease;
  468. /* 脉冲光晕动画 */
  469. animation: cta-pulse 2s ease-in-out infinite;
  470. }
  471. #cta-btn:active {
  472. transform: scale(0.96) translateY(2px);
  473. box-shadow:
  474. 0 2px 8px rgba(255, 95, 31, 0.4),
  475. 0 1px 0 rgba(255, 255, 255, 0.2) inset;
  476. }
  477. @keyframes cta-pulse {
  478. 0%,
  479. 100% {
  480. box-shadow:
  481. 0 4px 10px rgba(255, 95, 31, 0.45),
  482. 0 2px 0 rgba(255, 255, 255, 0.25) inset,
  483. 0 -3px 0 rgba(0, 0, 0, 0.18) inset;
  484. }
  485. 50% {
  486. box-shadow:
  487. 0 4px 16px rgba(255, 95, 31, 0.7),
  488. 0 2px 0 rgba(255, 255, 255, 0.25) inset,
  489. 0 -3px 0 rgba(0, 0, 0, 0.18) inset;
  490. }
  491. }
  492. /* 填色完成后的强化 CTA 状态 */
  493. @keyframes cta-highlight-pulse {
  494. 0%,
  495. 100% {
  496. transform: scale(1.08);
  497. box-shadow:
  498. 0 6px 24px rgba(255, 95, 31, 0.8),
  499. 0 2px 0 rgba(255, 255, 255, 0.3) inset,
  500. 0 -3px 0 rgba(0, 0, 0, 0.2) inset;
  501. }
  502. 50% {
  503. transform: scale(1.14);
  504. box-shadow:
  505. 0 8px 32px rgba(255, 95, 31, 1),
  506. 0 2px 0 rgba(255, 255, 255, 0.3) inset,
  507. 0 -3px 0 rgba(0, 0, 0, 0.2) inset;
  508. }
  509. }
  510. #cta-btn.cta-highlight {
  511. animation: cta-highlight-pulse 0.8s ease-in-out infinite;
  512. }
  513. /* ── 宣传界面 ──────────────────────────────────────────── */
  514. /* 在 game-area 内 position:absolute 展开,填满整个填色区域 */
  515. /* logo-bar(z:200) 和 cta-wrapper(z:200) 叠在其上 */
  516. #promo-screen {
  517. position: absolute;
  518. inset: 0;
  519. display: none;
  520. flex-direction: column;
  521. align-items: center;
  522. justify-content: center;
  523. gap: clamp(4px, 1vh, 8px);
  524. /* 背景由 body 提供,此处透明 */
  525. background: transparent;
  526. z-index: 10;
  527. /* padding-top 把重心下移,远离顶部 logo;overflow:hidden 防止 scale 动画溢出 */
  528. padding: clamp(24px, 12vh, 64px) 4vw clamp(8px, 2vh, 20px);
  529. box-sizing: border-box;
  530. overflow: hidden;
  531. }
  532. #promo-screen.visible {
  533. display: flex;
  534. }
  535. /* coloring-pages:从小(远)到大(近) */
  536. #promo-coloring {
  537. width: 96vw;
  538. max-width: 96vw;
  539. max-height: 56vh;
  540. object-fit: contain;
  541. opacity: 0;
  542. transform: scale(0.12);
  543. transition:
  544. transform 0.7s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0.05s,
  545. opacity 0.4s ease 0.05s;
  546. }
  547. #promo-coloring.animate-in {
  548. transform: scale(1);
  549. opacity: 1;
  550. }
  551. /* slogan:从超大(近)到正常,比 coloring-pages 晚 0.25s,加强弹跳感 */
  552. #promo-slogon {
  553. width: 90vw;
  554. max-width: 90vw;
  555. max-height: 22vh;
  556. object-fit: contain;
  557. opacity: 0;
  558. transform: scale(4);
  559. transition:
  560. transform 0.75s cubic-bezier(0.175, 0.885, 0.32, 1.6) 0.3s,
  561. opacity 0.25s ease 0.3s;
  562. }
  563. #promo-slogon.animate-in {
  564. transform: scale(1);
  565. opacity: 1;
  566. }
  567. /* ── 横屏:promo 占游戏区宽度 90% ── */
  568. @media (orientation: landscape) {
  569. #promo-screen {
  570. padding: clamp(12px, 10vh, 36px) 5% clamp(4px, 2vh, 12px);
  571. }
  572. #promo-coloring {
  573. width: 95%;
  574. max-width: 95%;
  575. max-height: 54vh;
  576. }
  577. #promo-slogon {
  578. width: 90%;
  579. max-width: 90%;
  580. max-height: 44vh;
  581. }
  582. }