WelcomePage.css 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /**
  2. * WelcomePage 屏幕适配方案 - postcss-px-to-viewport
  3. *
  4. * 设计稿基准: 375px × 812px (iPhone X/11/12/13/14)
  5. * 适配策略: vw/vh 单位,通过 postcss-px-to-viewport 自动转换
  6. *
  7. * 核心思路:
  8. * - CSS 中的 px 自动转换为 vw
  9. * - 使用百分比和 vw/vh 实现流式响应式布局
  10. * - 无需媒体查询,自动适配所有屏幕尺寸
  11. */
  12. /* ========================================
  13. 外层容器 - 全屏布局
  14. ======================================== */
  15. .welcome-page {
  16. position: relative;
  17. width: 100%;
  18. /* 让欢迎页本身也跟随视口高度自适应,而不是依赖父级固定高度 */
  19. min-height: 100dvh;
  20. min-height: calc(var(--vh, 1vh) * 100);
  21. overflow: hidden;
  22. background-color: #E8E8E8;
  23. /* iOS 安全区域适配 */
  24. padding-top: env(safe-area-inset-top);
  25. padding-left: env(safe-area-inset-left);
  26. padding-right: env(safe-area-inset-right);
  27. padding-bottom: env(safe-area-inset-bottom);
  28. }
  29. /* ========================================
  30. 背景层 - 全屏覆盖,消除空白
  31. ======================================== */
  32. .welcome-bg {
  33. position: absolute;
  34. top: 0;
  35. left: 0;
  36. width: 100%;
  37. height: 100%;
  38. background-size: cover;
  39. background-position: center;
  40. background-repeat: no-repeat;
  41. background-image: url('https://lyrria-pro.oss-cn-beijing.aliyuncs.com/chatbot-bg.svg');
  42. z-index: 0;
  43. }
  44. /* ========================================
  45. 内容容器 - 基于 vw/vh 响应式适配
  46. ======================================== */
  47. .welcome-content {
  48. position: relative;
  49. /* 宽度跟随父级,在大屏上也保持全宽自适应 */
  50. width: 100%;
  51. /* 使用动态视口高度(dvh),降级方案使用 JavaScript 设置的 CSS 变量 */
  52. min-height: 100dvh; /* 现代浏览器:动态视口高度 */
  53. min-height: calc(var(--vh, 1vh) * 100); /* 降级方案:JavaScript 计算的视口高度 */
  54. margin: 0 auto;
  55. z-index: 1;
  56. }
  57. /* ========================================
  58. Lumi 图片 - 基于 vh 的响应式布局
  59. 设计稿: 375 × 812, 元素尺寸:
  60. width: 520px, height: 520px, top: 186.38px, left: -133px
  61. 规则:
  62. - 高度跟随视口高度 (vh) 等比缩放
  63. - 宽度 auto,由图片本身比例决定
  64. ======================================== */
  65. .welcome-lumi {
  66. position: absolute;
  67. /* 纵向位置:按高度 812px 等比缩放 */
  68. top: 22.95vh; /* 186.38 / 812 × 100 = 22.95vh */
  69. /* 高度:按设计稿 520px 高度等比缩放 */
  70. height: 64.04vh; /* 520 / 812 × 100 = 64.04vh */
  71. /* 宽度自动,由图片比例决定,不直接跟随 vw 缩放 */
  72. width: 100%;
  73. /* 横向位置:仍按设计稿等比缩放,宽度封顶 600px 时不再继续偏移 */
  74. /* left: calc(-133PX * min(100vw, 600PX) / 375PX); */
  75. object-fit: contain;
  76. }
  77. /* ========================================
  78. Hello 文字 - 基于 vh 的响应式布局
  79. 设计稿: 812px 高度基准, width: 245px, height: 113px
  80. ======================================== */
  81. .welcome-hello {
  82. position: absolute;
  83. top: 17vh; /* 138 / 812 × 100 = 17vh */
  84. /* 横向位置与宽度:
  85. - 视口宽度 ≤ 600px 时:按 375 设计稿等比缩放
  86. - 视口宽度 > 600px 时:按 600px 视口封顶,不再继续放大 */
  87. left: calc(45PX * min(100vw, 600PX) / 375PX);
  88. width: calc(245PX * min(100vw, 600PX) / 375PX);
  89. height: 13.92vh; /* 113 / 812 × 100 = 13.92vh */
  90. /* 文字渐变色 */
  91. background: linear-gradient(97.3deg, rgba(245, 243, 240, 0.8) 2.21%, rgba(245, 243, 240, 0.3) 150.89%);
  92. -webkit-background-clip: text;
  93. -webkit-text-fill-color: transparent;
  94. background-clip: text;
  95. opacity: 1;
  96. /* 文字样式 - 使用系统字体 */
  97. display: flex;
  98. align-items: center;
  99. justify-content: center;
  100. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  101. font-weight: 500;
  102. font-style: normal;
  103. /* 字体大小:同时考虑宽度和高度,取二者中较小的值 */
  104. /* 宽度方向:96PX * min(100vw, 600PX) / 375PX (≤600 等比缩放,>600 封顶) */
  105. /* 高度方向:96PX * 100vh / 812PX (按设计稿高度 812px 等比缩放) */
  106. /* 最终:min(宽度方案, 高度方案),防止某一维度过大导致文字过大或被遮挡 */
  107. font-size: min(
  108. calc(96PX * min(100vw, 600PX) / 375PX),
  109. calc(96PX * 100vh / 812PX)
  110. );
  111. line-height: 1; /* 使用数值而非百分比,更稳定 */
  112. letter-spacing: 0;
  113. text-align: center;
  114. text-transform: capitalize;
  115. /* 交互 */
  116. cursor: pointer;
  117. transition: opacity 0.2s ease, transform 0.2s ease;
  118. user-select: none;
  119. -webkit-tap-highlight-color: transparent;
  120. touch-action: manipulation;
  121. }
  122. .welcome-hello:hover {
  123. opacity: 0.9;
  124. }
  125. .welcome-hello:active {
  126. opacity: 0.8;
  127. }
  128. /* ========================================
  129. 性能优化
  130. ======================================== */
  131. .welcome-lumi,
  132. .welcome-hello {
  133. /* 启用硬件加速 */
  134. transform: translateZ(0);
  135. will-change: transform;
  136. /* 图片优化 */
  137. image-rendering: -webkit-optimize-contrast;
  138. image-rendering: crisp-edges;
  139. /* 防止图片拖拽 */
  140. -webkit-user-drag: none;
  141. }
  142. /* ========================================
  143. 视频播放器容器
  144. ======================================== */
  145. .player-container {
  146. position: fixed;
  147. top: 0;
  148. left: 0;
  149. width: 100%;
  150. height: 100%;
  151. z-index: 10;
  152. transition: opacity 0.3s ease-in;
  153. }
  154. .player-container.player-visible {
  155. opacity: 1;
  156. visibility: visible;
  157. pointer-events: auto;
  158. }
  159. .player-container.player-hidden {
  160. opacity: 0;
  161. visibility: hidden;
  162. pointer-events: none;
  163. }
  164. /* Video.js 容器样式 */
  165. .video-js {
  166. position: absolute;
  167. top: 0;
  168. left: 0;
  169. width: 100% !important;
  170. height: 100% !important;
  171. padding-top: 0 !important;
  172. background: transparent;
  173. z-index: 1;
  174. }
  175. /* Video.js 技术层(实际video元素) */
  176. .video-js .vjs-tech {
  177. position: absolute;
  178. top: 0;
  179. left: 0;
  180. width: 100%;
  181. height: 100%;
  182. object-fit: contain;
  183. z-index: 2;
  184. }
  185. /* 隐藏 Video.js 控制栏 */
  186. .video-js .vjs-control-bar {
  187. display: none !important;
  188. opacity: 0 !important;
  189. visibility: hidden !important;
  190. }
  191. .video-js:hover .vjs-control-bar,
  192. .video-js.vjs-user-active .vjs-control-bar,
  193. .video-js.vjs-user-inactive .vjs-control-bar,
  194. .video-js.vjs-paused .vjs-control-bar {
  195. display: none !important;
  196. opacity: 0 !important;
  197. visibility: hidden !important;
  198. }
  199. /* 隐藏原生浏览器控制栏 */
  200. .video-js video::-webkit-media-controls {
  201. display: none !important;
  202. -webkit-appearance: none !important;
  203. opacity: 0 !important;
  204. visibility: hidden !important;
  205. }
  206. .video-js video::-webkit-media-controls-enclosure {
  207. display: none !important;
  208. -webkit-appearance: none !important;
  209. opacity: 0 !important;
  210. visibility: hidden !important;
  211. }
  212. .video-js video::-webkit-media-controls-panel,
  213. .video-js video::-webkit-media-controls-play-button,
  214. .video-js video::-webkit-media-controls-timeline,
  215. .video-js video::-webkit-media-controls-current-time-display,
  216. .video-js video::-webkit-media-controls-time-remaining-display,
  217. .video-js video::-webkit-media-controls-mute-button,
  218. .video-js video::-webkit-media-controls-volume-slider,
  219. .video-js video::-webkit-media-controls-fullscreen-button {
  220. display: none !important;
  221. }
  222. /* 移动端 iOS Safari - 隐藏播放开始按钮和叠加层 */
  223. video::-webkit-media-controls-start-playback-button,
  224. video::-webkit-media-controls-overlay-enclosure,
  225. video::-webkit-media-controls-overlay-play-button {
  226. display: none !important;
  227. -webkit-appearance: none !important;
  228. opacity: 0 !important;
  229. }
  230. /* 移动端强制隐藏所有原生控件 */
  231. .player-container video,
  232. .video-js video {
  233. -webkit-appearance: none !important;
  234. appearance: none !important;
  235. }
  236. /* 移除Video.js的聚焦轮廓 */
  237. .video-js *:focus {
  238. outline: none;
  239. }
  240. /* 隐藏大播放按钮 */
  241. .video-js .vjs-big-play-button {
  242. display: none !important;
  243. opacity: 0 !important;
  244. visibility: hidden !important;
  245. pointer-events: none !important;
  246. }
  247. /* 隐藏加载动画 */
  248. .video-js .vjs-loading-spinner {
  249. display: none !important;
  250. opacity: 0 !important;
  251. visibility: hidden !important;
  252. pointer-events: none !important;
  253. }
  254. /* 视频元素本身需要可见和可交互(用于播放) */
  255. .video-js,
  256. .video-js .vjs-tech,
  257. .video-js video {
  258. pointer-events: auto !important;
  259. cursor: default;
  260. }
  261. /* Video.js 响应式处理 */
  262. .vjs-fluid {
  263. padding-top: 0 !important;
  264. }
  265. .vjs-16-9 {
  266. padding-top: 0 !important;
  267. }
  268. /* 确保video元素填充满容器 */
  269. .video-js video {
  270. width: 100% !important;
  271. height: 100% !important;
  272. object-fit: contain;
  273. z-index: 2;
  274. display: block !important;
  275. }
  276. /* 禁用文本选择和拖拽 */
  277. .player-container,
  278. .video-js {
  279. user-select: none;
  280. -webkit-user-select: none;
  281. -moz-user-select: none;
  282. -ms-user-select: none;
  283. -webkit-touch-callout: none;
  284. }
  285. /* ========================================
  286. 加载动画遮罩
  287. ======================================== */
  288. .video-loading-overlay {
  289. position: fixed;
  290. top: 0;
  291. left: 0;
  292. width: 100%;
  293. height: 100%;
  294. background: rgba(0, 0, 0, 0.7);
  295. display: flex;
  296. justify-content: center;
  297. align-items: center;
  298. z-index: 10000;
  299. backdrop-filter: blur(4px);
  300. }
  301. .video-loading-content {
  302. display: flex;
  303. flex-direction: column;
  304. align-items: center;
  305. gap: 24px; /* 0.24rem = 24px (基于 1rem = 100px) */
  306. }
  307. .video-loading-spinner {
  308. position: relative;
  309. width: 80px; /* 0.8rem = 80px */
  310. height: 80px; /* 0.8rem = 80px */
  311. }
  312. .spinner-ring {
  313. position: absolute;
  314. top: 0;
  315. left: 0;
  316. width: 100%;
  317. height: 100%;
  318. border: 3px solid transparent;
  319. border-top-color: #fff;
  320. border-radius: 50%;
  321. animation: spin 1s linear infinite;
  322. }
  323. .spinner-ring-1 {
  324. border-top-color: rgba(255, 255, 255, 0.9);
  325. animation-duration: 1s;
  326. }
  327. .spinner-ring-2 {
  328. width: 70%;
  329. height: 70%;
  330. top: 15%;
  331. left: 15%;
  332. border-top-color: rgba(255, 255, 255, 0.7);
  333. animation-duration: 1.5s;
  334. animation-direction: reverse;
  335. }
  336. .spinner-ring-3 {
  337. width: 40%;
  338. height: 40%;
  339. top: 30%;
  340. left: 30%;
  341. border-top-color: rgba(255, 255, 255, 0.5);
  342. animation-duration: 2s;
  343. }
  344. @keyframes spin {
  345. 0% {
  346. transform: rotate(0deg);
  347. }
  348. 100% {
  349. transform: rotate(360deg);
  350. }
  351. }
  352. .video-loading-text {
  353. color: #fff;
  354. font-size: 16px; /* 0.16rem = 16px */
  355. font-weight: 500;
  356. text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  357. animation: pulse 1.5s ease-in-out infinite;
  358. }
  359. @keyframes pulse {
  360. 0%, 100% {
  361. opacity: 1;
  362. }
  363. 50% {
  364. opacity: 0.6;
  365. }
  366. }
  367. /* ========================================
  368. 协议文字 - 基于 vh 的响应式布局
  369. 设计稿: 812px 高度基准,top: 700px
  370. ======================================== */
  371. .agreement-container {
  372. position: absolute;
  373. left: 0;
  374. right: 0;
  375. /* 改为使用 bottom + 安全区,避免被浏览器底栏遮挡 */
  376. bottom: calc(env(safe-area-inset-bottom, 0px) + 24PX);
  377. display: flex;
  378. justify-content: center;
  379. align-items: center;
  380. /* 协议区域左右留白在大屏上保持固定,不跟随宽度无限放大 */
  381. padding: 0 20PX;
  382. z-index: 2;
  383. }
  384. .agreement-login-tip {
  385. position: absolute;
  386. left: 0;
  387. right: 0;
  388. bottom: calc(env(safe-area-inset-bottom, 0px) + 56PX); /* 在协议文字上方留出间距 */
  389. text-align: center;
  390. font-size: 12PX; /* 与 .agreement-text 一致 */
  391. line-height: 1.5;
  392. color: rgba(245, 243, 240, 1); /* 白色文字,与协议文字一致 */
  393. text-decoration: underline;
  394. user-select: none;
  395. cursor: pointer;
  396. transition: opacity 0.2s ease;
  397. -webkit-tap-highlight-color: transparent;
  398. z-index: 2;
  399. }
  400. .agreement-login-tip:active,
  401. .agreement-login-tip:hover {
  402. opacity: 0.8;
  403. }
  404. .agreement-content {
  405. display: flex;
  406. align-items: center;
  407. /* 间距固定,不随视口宽度变化 */
  408. gap: 8PX;
  409. }
  410. .agreement-checkbox {
  411. width: 16PX;
  412. height: 16PX;
  413. min-width: 16PX;
  414. border-radius: 50%;
  415. /* 边框宽度固定为 1.5PX,使用大写 PX 避免被 postcss-px-to-viewport 转换 */
  416. border: 1.5PX solid rgba(245, 243, 240, 1);
  417. background: transparent;
  418. cursor: pointer;
  419. transition: all 0.2s ease;
  420. position: relative;
  421. }
  422. .agreement-checkbox.checked {
  423. background: rgba(191, 157, 248, 1);
  424. border-color: rgba(191, 157, 248, 1);
  425. }
  426. .agreement-checkbox.checked::after {
  427. content: '';
  428. position: absolute;
  429. top: 50%;
  430. left: 50%;
  431. transform: translate(-50%, -50%);
  432. width: 6PX;
  433. height: 6PX;
  434. background: white;
  435. border-radius: 50%;
  436. }
  437. .agreement-text {
  438. /* 协议文字在大屏上保持固定字号,避免过大 */
  439. font-size: 12PX;
  440. line-height: 1.5;
  441. color: rgba(245, 243, 240, 1);
  442. user-select: none;
  443. }
  444. .agreement-link {
  445. color: rgba(191, 157, 248, 1);
  446. text-decoration: none;
  447. cursor: pointer;
  448. transition: opacity 0.2s ease;
  449. }
  450. .agreement-link:hover,
  451. .agreement-link:active {
  452. opacity: 0.8;
  453. }