new-chat.tsx 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { useEffect, useRef } from "react";
  2. import { SlotID } from "../constant";
  3. import { EmojiAvatar } from "./emoji";
  4. import styles from "./new-chat.module.scss";
  5. function getIntersectionArea(aRect: DOMRect, bRect: DOMRect) {
  6. const xmin = Math.max(aRect.x, bRect.x);
  7. const xmax = Math.min(aRect.x + aRect.width, bRect.x + bRect.width);
  8. const ymin = Math.max(aRect.y, bRect.y);
  9. const ymax = Math.min(aRect.y + aRect.height, bRect.y + bRect.height);
  10. const width = xmax - xmin;
  11. const height = ymax - ymin;
  12. const intersectionArea = width < 0 || height < 0 ? 0 : width * height;
  13. return intersectionArea;
  14. }
  15. function Mask(props: { avatar: string; name: string }) {
  16. const domRef = useRef<HTMLDivElement>(null);
  17. useEffect(() => {
  18. const changeOpacity = () => {
  19. const dom = domRef.current;
  20. const parent = document.getElementById(SlotID.AppBody);
  21. if (!parent || !dom) return;
  22. const domRect = dom.getBoundingClientRect();
  23. const parentRect = parent.getBoundingClientRect();
  24. const intersectionArea = getIntersectionArea(domRect, parentRect);
  25. const domArea = domRect.width * domRect.height;
  26. const ratio = intersectionArea / domArea;
  27. const opacity = ratio > 0.9 ? 1 : 0.4;
  28. dom.style.opacity = opacity.toString();
  29. };
  30. setTimeout(changeOpacity, 30);
  31. window.addEventListener("resize", changeOpacity);
  32. return () => window.removeEventListener("resize", changeOpacity);
  33. }, [domRef]);
  34. return (
  35. <div className={styles["mask"]} ref={domRef}>
  36. <div className={styles["mask-avatar"]}>
  37. <EmojiAvatar avatar={props.avatar} />
  38. </div>
  39. <div className={styles["mask-name"] + " one-line"}>{props.name}</div>
  40. </div>
  41. );
  42. }
  43. export function NewChat() {
  44. const masks = new Array(20).fill(0).map(() =>
  45. new Array(10).fill(0).map((_, i) => ({
  46. avatar: "1f" + (Math.round(Math.random() * 50) + 600).toString(),
  47. name: ["撩妹达人", "编程高手", "情感大师", "健康医生", "数码通"][
  48. Math.floor(Math.random() * 4)
  49. ],
  50. })),
  51. );
  52. return (
  53. <div className={styles["new-chat"]}>
  54. <div className={styles["mask-cards"]}>
  55. <div className={styles["mask-card"]}>
  56. <EmojiAvatar avatar="1f606" size={24} />
  57. </div>
  58. <div className={styles["mask-card"]}>
  59. <EmojiAvatar avatar="1f916" size={24} />
  60. </div>
  61. <div className={styles["mask-card"]}>
  62. <EmojiAvatar avatar="1f479" size={24} />
  63. </div>
  64. </div>
  65. <div className={styles["title"]}>挑选一个面具</div>
  66. <div className={styles["sub-title"]}>现在开始,与面具背后的思维碰撞</div>
  67. <input className={styles["search-bar"]} placeholder="搜索" type="text" />
  68. <div className={styles["masks"]}>
  69. {masks.map((masks, i) => (
  70. <div key={i} className={styles["mask-row"]}>
  71. {masks.map((mask, index) => (
  72. <Mask key={index} {...mask} />
  73. ))}
  74. </div>
  75. ))}
  76. </div>
  77. </div>
  78. );
  79. }