This commit is contained in:
eric
2025-08-04 14:13:30 +08:00
parent e37edd16b5
commit 79568c0ea1
2 changed files with 284 additions and 106 deletions

View File

@@ -3,22 +3,123 @@ import Taro from "@tarojs/taro";
import { View, Text, Image, Button, Audio } from "@tarojs/components";
import "./index.scss";
import React, { useCallback, useEffect, useState } from "react";
import { AtList, AtListItem, AtNavBar, AtTag, AtMessage } from "taro-ui";
import {
AtList,
AtListItem,
AtNavBar,
AtTag,
AtMessage,
AtCurtain,
} from "taro-ui";
import gif11 from "../../images/11.gif";
import gif22 from "../../images/22.gif";
import doro11 from "../../images/doro11.gif";
import baby from "../../images/baby.mp3";
import confetti from "canvas-confetti";
import { AtToast } from "taro-ui";
const Index = () => {
// ws://(或者 wss:// 对于 HTTPS 环境
const [message, setMessage] = useState("");
const [status, setStatus] = useState("0"); //0无状态,1是小新
const [userInfoArr, setuserInfoArr] = useState([]); // 用户信息
const [giftUser, setGiftUser] = useState({}); // 用户信息
const [giftOpen, setGiftOpen] = useState(false); // 用户信息
const [messageArr, setMessageArr] = useState([]);
// useEffect(() => {
// const intervalId = setInterval(() => {
// speak(`欢迎进入直播间`);
// }, 3000);
// return () => {
// clearInterval(intervalId);
// };
// }, []);
const confettiSvg = () => {
var scalar = 2;
var pineapple = confetti.shapeFromText({ text: "🍍", scalar });
confetti({
shapes: [pineapple],
scalar,
});
};
const stars = () => {
// note: you CAN only use a path for confetti.shapeFrompath(), but for
// performance reasons it is best to use it once in development and save
// the result to avoid the performance penalty at runtime
// pumpkin shape from https://thenounproject.com/icon/pumpkin-5253388/
var pumpkin = confetti.shapeFromPath({
path: "M449.4 142c-5 0-10 .3-15 1a183 183 0 0 0-66.9-19.1V87.5a17.5 17.5 0 1 0-35 0v36.4a183 183 0 0 0-67 19c-4.9-.6-9.9-1-14.8-1C170.3 142 105 219.6 105 315s65.3 173 145.7 173c5 0 10-.3 14.8-1a184.7 184.7 0 0 0 169 0c4.9.7 9.9 1 14.9 1 80.3 0 145.6-77.6 145.6-173s-65.3-173-145.7-173zm-220 138 27.4-40.4a11.6 11.6 0 0 1 16.4-2.7l54.7 40.3a11.3 11.3 0 0 1-7 20.3H239a11.3 11.3 0 0 1-9.6-17.5zM444 383.8l-43.7 17.5a17.7 17.7 0 0 1-13 0l-37.3-15-37.2 15a17.8 17.8 0 0 1-13 0L256 383.8a17.5 17.5 0 0 1 13-32.6l37.3 15 37.2-15c4.2-1.6 8.8-1.6 13 0l37.3 15 37.2-15a17.5 17.5 0 0 1 13 32.6zm17-86.3h-82a11.3 11.3 0 0 1-6.9-20.4l54.7-40.3a11.6 11.6 0 0 1 16.4 2.8l27.4 40.4a11.3 11.3 0 0 1-9.6 17.5z",
matrix: [
0.020491803278688523, 0, 0, 0.020491803278688523, -7.172131147540983,
-5.9016393442622945,
],
});
// tree shape from https://thenounproject.com/icon/pine-tree-1471679/
var tree = confetti.shapeFromPath({
path: "M120 240c-41,14 -91,18 -120,1 29,-10 57,-22 81,-40 -18,2 -37,3 -55,-3 25,-14 48,-30 66,-51 -11,5 -26,8 -45,7 20,-14 40,-30 57,-49 -13,1 -26,2 -38,-1 18,-11 35,-25 51,-43 -13,3 -24,5 -35,6 21,-19 40,-41 53,-67 14,26 32,48 54,67 -11,-1 -23,-3 -35,-6 15,18 32,32 51,43 -13,3 -26,2 -38,1 17,19 36,35 56,49 -19,1 -33,-2 -45,-7 19,21 42,37 67,51 -19,6 -37,5 -56,3 25,18 53,30 82,40 -30,17 -79,13 -120,-1l0 41 -31 0 0 -41z",
matrix: [
0.03597122302158273, 0, 0, 0.03597122302158273, -4.856115107913669,
-5.071942446043165,
],
});
// heart shape from https://thenounproject.com/icon/heart-1545381/
var heart = confetti.shapeFromPath({
path: "M167 72c19,-38 37,-56 75,-56 42,0 76,33 76,75 0,76 -76,151 -151,227 -76,-76 -151,-151 -151,-227 0,-42 33,-75 75,-75 38,0 57,18 76,56z",
matrix: [
0.03333333333333333, 0, 0, 0.03333333333333333, -5.566666666666666,
-5.533333333333333,
],
});
var defaults = {
scalar: 2,
spread: 180,
particleCount: 30,
origin: { y: -0.1 },
startVelocity: -35,
};
confetti({
...defaults,
shapes: [pumpkin],
colors: ["#ff9a00", "#ff7400", "#ff4d00"],
});
confetti({
...defaults,
shapes: [tree],
colors: ["#8d960f", "#be0f10", "#445404"],
});
confetti({
...defaults,
shapes: [heart],
colors: ["#f93963", "#a10864", "#ee0b93"],
});
};
useEffect(() => {
// var myCanvas = document.createElement("canvas");
// document.body.appendChild(myCanvas);
// var myConfetti = confetti.create(myCanvas, {
// resize: true,
// useWorker: true,
// });
// myConfetti({
// particleCount: 100,
// spread: 160,
// // any other options from the global
// // confetti function
// });
}, []);
useEffect(() => {
// 创建 WebSocket 连接
const socket = new WebSocket("ws://192.168.31.222:8888"); // 注意使用 ws://
@@ -33,20 +134,42 @@ const Index = () => {
socket.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log("data.type---", data.type);
if (data.type === "join") {
const user = data.data; // 就是你后端推送的 user_data 字典
// const user = data.data; // 就是你后端推送的 user_data 字典
const user = {
...data.data,
animate: true,
uid: Date.now() + Math.random(), // 确保唯一
};
console.log("✅ 新观众进场:", user);
// let newuserInfoArr = userInfoArr
// newuserInfoArr.push(user);
// console.log('newuserInfoArr---',newuserInfoArr)
// setuserInfoArr(newuserInfoArr);
setuserInfoArr((prev) => [user, ...prev]);
setTimeout(() => {
setuserInfoArr((prev) =>
prev.map((u) =>
u.uid === user.uid ? { ...u, animate: false } : u
)
);
}, 1000);
// ✅ 举例使用
speak(`${user?.nick_name} 进入了直播间`);
// speak(`欢迎${user?.nick_name} 进入直播间`);
} else if (data.type === "like") {
const user = data.data;
// 粒子特效
// confettiSvg();
stars();
} else if (data.type === "gift") {
stars();
const user = data.data;
// console.log("✅ 送礼:", user);
// speak(`谢谢${user?.nick_name} 送小星星`);
//特殊特效
setGiftUser(user);
setGiftOpen(true);
setTimeout(() => {
setGiftOpen(false);
}, 2000);
}
} catch (e) {
console.log("❌ 非 JSON 消息:", event.data);
@@ -182,23 +305,19 @@ const Index = () => {
return (
<View className="index">
{/* <View>
扣 <span style={{ color: "green" }}>11</span> 变小新
<View
className="giftKey"
style={{ color: "white", marginBottom: "20px", marginTop: "100px" }}
>
{/* <View>
👍 <span style={{ fontSize: "10px" }}>{`点赞`} </span>&nbsp; {" "}
<span style={{ fontSize: "12px" }}>看烟花</span>
</View> */}
<View>
🩷 <span style={{ fontSize: "16px" }}>小星星</span> {" "}
<span style={{ fontSize: "16px" }}>看烟花</span>
</View>
</View>
<View>
扣 <span style={{ color: "green" }}>22</span> 娜娜子
</View> */}
{/* <View className="messageArr">
{messageArr?.slice(0, 5)?.map((item, index) => (
<View
key={index}
className={index === 0 ? "message_item_first" : "message_item"}
>
{item}
</View>
))}
</View> */}
<View className="userInfoArr">
{/* .slice(0, 5) */}
@@ -207,11 +326,18 @@ const Index = () => {
key={index}
className={index === 0 ? "message_item_first" : "message_item"}
>
<span style={{color:'white'}}>{item?.nick_name}</span>
<View className="gifImg1">
<span style={{ color: "white", marginTop: "20px" }}>
{/* ${item?.gender === "1" ? "👨" : "👩"} */}
{`${item?.nick_name}`}
</span>
<View
className={`avatar_box ${
item.animate ? "animate__animated animate__tada" : ""
}`}
>
<Image
className="index_gif"
mode={"scaleToFill"}
className="avatar_thumb"
mode="scaleToFill"
src={item?.avatar_thumb.url_list_list?.[0]}
/>
</View>
@@ -219,6 +345,33 @@ const Index = () => {
))}
</View>
{/* <AtToast
className="AtToastDouyin"
isOpened={giftOpen}
text={giftUser?.nick_name ? `谢谢 ${giftUser?.nick_name} 送出礼物` : "11"}
icon={giftUser?.avatar_thumb?.url_list_list?.[0]}
></AtToast> */}
<AtCurtain
isOpened={giftOpen}
onClose={() => setGiftOpen(false)}
closeBtnPosition={"top"}
>
<div className="giftCurtain">
<span style={{ color: "yellow", fontSize: "20px" }}>
谢谢{" "}
<span style={{ color: "white", fontSize: "30px" }}>
{giftUser?.nick_name}
</span>{" "}
🩷🩷🩷🩷🩷
</span>
<Image
style="width:200px;height:200px"
src={giftUser?.avatar_thumb?.url_list_list?.[0]}
/>
</div>
</AtCurtain>
{/* 添加doro的gif组合场景 */}
{/* <View className="gifImg">
@@ -228,7 +381,7 @@ const Index = () => {
// src={status === "1" ? gif11 : status === "2" ? gif22 : doro11}
src={doro11}
/>
</View> */}
</View> */}
{/* <View className="index_backImg">
<Image className="index_backImg_bg" mode={"scaleToFill"} src={iphone} />

View File

@@ -1,87 +1,97 @@
.index {
width: 100vw;
height: 100vh;
// overflow: hidden; // 防止溢出
display: flex;
flex-direction: column;
align-items: center;
background-color: black;
// justify-content: center;
// background-image: url('../../images/iphone.jpg');
// background-size: cover; // 拉伸铺满容器
// background-position: center; // 居中
// background-repeat: no-repeat; // 不重复
.messageArr {
padding: 40px;
font-size: 30px;
@media (max-width: 1000px) {
.index {
width: 100vw;
height: 100vh;
// overflow: hidden; // 防止溢出
display: flex;
flex-direction: column;
align-items: center;
background-color: black;
// justify-content: center;
// background-image: url('../../images/iphone.jpg');
// background-size: cover; // 拉伸铺满容器
// background-position: center; // 居中
// background-repeat: no-repeat; // 不重复
.message_item_first {
color: red;
.messageArr {
padding: 40px;
font-size: 30px;
display: flex;
flex-direction: column;
.message_item_first {
color: red;
}
.message_item {
}
}
.message_item {}
}
.index_backImg {
width: 100%;
height: 100%;
background-color: yellowgreen;
.index_backImg_bg {
.index_backImg {
width: 100%;
height: 100%;
background-color: yellowgreen;
.index_backImg_bg {
width: 100%;
height: 100%;
}
}
}
.index_video {
position: absolute;
top: 0px;
width: 400px;
height: 200px;
// display: flex;
// flex-direction: column;
// align-items: center;
// justify-content: center;
background-color: aqua;
.video_js {
.index_video {
position: absolute;
top: 0px;
width: 400px;
height: 200px;
// display: flex;
// flex-direction: column;
// align-items: center;
// justify-content: center;
background-color: aqua;
.video_js {
width: 400px;
height: 200px;
}
}
.gifImg {
position: absolute;
bottom: 0;
}
}
.gifImg{
position: absolute;
bottom: 0;
}
}
// PC 浏览器下旋转
@media (min-width: 1600px) {
@media (min-width: 1000px) {
html,
body,
#root,
#app {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: black;
box-sizing: border-box;
}
.index {
// position: absolute;
// top: 0;
// left: 0;
// width: 750px; // 根据标准宽度调整
// height: 1334px; // 保持竖屏比例
width: 100vw; // 使容器宽度始终填满视口
height: 100vh; // 使容器高度始终填满视口
// transform: rotate(-90deg) translate(-100vh, 0);
position: absolute;
top: 0;
left: 0;
width: 750px; // 根据标准宽度调整
height: 1334px; // 保持竖屏比例
background-color: black;
// width: 100vw; // 使容器宽度始终填满视口
// height: 100vh; // 使容器高度始终填满视口
transform: rotate(-90deg) translate(-100vh, 0);
transform-origin: top left;
display: flex;
flex-direction: column;
align-items: center;
// justify-content: center;
// background-image: url('../../images/iphone.jpg');
@@ -103,10 +113,10 @@
color: red;
}
.message_item {}
.message_item {
}
}
.index_backImg {
width: 100%;
height: 100%;
@@ -121,19 +131,34 @@
}
}
.index_video {
position: absolute;
top: 0px;
width: 400px;
height: 200px;
.video_js {
width: 400px;
height: 200px;
}
.AtToastDouyin {
z-index: 999;
}
.giftCurtain {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: white;
font-size: 20px;
width: 100%;
height: 100%;
}
.at-curtain__btn-close {
display: none !important;
}
// .index_video {
// position: absolute;
// top: 0px;
// width: 400px;
// height: 200px;
// .video_js {
// width: 400px;
// height: 200px;
// }
// }
}
}
}