diff --git a/mini/pages/wish-tree/wish-tree.js b/mini/pages/wish-tree/wish-tree.js index 8b53e4f..d45a80c 100644 --- a/mini/pages/wish-tree/wish-tree.js +++ b/mini/pages/wish-tree/wish-tree.js @@ -75,6 +75,21 @@ Page({ this.loadProducts(); }, + onUnload() { + this.stopDanmakuScheduler(); + }, + + onHide() { + this.stopDanmakuScheduler(); + }, + + onShow() { + // 从后台/下一页返回时,若已有弹幕数据则恢复调度 + if (this.danmakuRows && this.danmakuRows.length && !(this.danmakuTimers && this.danmakuTimers.length)) { + this.startDanmakuScheduler(this.danmakuRows); + } + }, + onPullDownRefresh() { const { currentTreeIndex, trees } = this.data; const tree = trees[currentTreeIndex]; @@ -224,16 +239,75 @@ Page({ this.setData({ [`trees[${index}].hangWishes`]: cache.hangWishes, topWishes: cache.top, - currentDanmaku: cache.danmaku, + }); + // 启动弹幕调度:每行一条完毕后再出下一条 + this.startDanmakuScheduler(cache.danmaku); + }, + + // 启动弹幕调度:每行同一时刻只播一条,前一条飘完再出下一条(循环) + startDanmakuScheduler(rows) { + this.stopDanmakuScheduler(); + this.danmakuRows = rows || []; + this.danmakuTimers = []; + + if (!this.danmakuRows.length) { + this.setData({ currentDanmaku: [] }); + return; + } + + const GAP = 1.5; // 同一行前一条飘完后,间隔再出下一条(秒) + + // 每行独立调度:row 行的第 idx 条播完后,隔 GAP 秒播第 idx+1 条 + const playRow = (row, idx) => { + const rowData = this.danmakuRows[row]; + if (!rowData) return; + const item = rowData.list[idx % rowData.list.length]; + // 更新该行当前弹幕(用行号作为 key 保证 setData 局部刷新) + this.setData({ + [`currentDanmaku[${row}]`]: { + key: `${row}-${idx % rowData.list.length}-${Date.now()}`, + id: item.id, + content: item.content, + author: item.author, + type: item.type, + top: rowData.top, + duration: rowData.duration, + }, + }); + // 前一条飘完 + 间隔后,播下一条 + const timer = setTimeout(() => { + playRow(row, idx + 1); + }, (rowData.duration + GAP) * 1000); + this.danmakuTimers[row] = timer; + }; + + // 初始化 currentDanmaku 数组长度,并启动每行 + this.setData({ currentDanmaku: new Array(this.danmakuRows.length).fill(null) }); + this.danmakuRows.forEach((_, row) => { + // 各行错开启动,避免 4 行同时从右侧涌出 + const startTimer = setTimeout(() => playRow(row, 0), row * 1200); + this.danmakuTimers.push(startTimer); }); }, + // 停止弹幕调度 + stopDanmakuScheduler() { + if (this.danmakuTimers) { + this.danmakuTimers.forEach((t) => clearTimeout(t)); + this.danmakuTimers = []; + } + }, + // 构建弹幕:共 4 行(行 0-2 树桩处三行,行 3 顶部置顶轮播下方) - // 同行统一慢速,按条数均匀错开起始位置,避免互相盖住 + // 按行分组返回,由 JS 定时器控制:同一行一条完毕后再出下一条,不重叠 buildDanmaku(list) { - const DURATION_BOTTOM = 32; // 树桩处一行飘完全屏的秒数(慢速) - const DURATION_TOP = 26; // 顶部行稍快一点 - const ROW_TOPS = [64, 71, 78, 16]; // 前三行靠近树桩,第四行在顶部 + const DURATION_BOTTOM = 30; // 树桩处一条飘完全屏的秒数(慢速) + const DURATION_TOP = 24; // 顶部行稍快一点 + // 行位置(屏幕百分比): + // - 行3 顶部行紧贴置顶轮播下方(稍有空隙) + // - 行0-2 树桩处三行,第一条68%,三行紧凑(间隔5%) + const ROW_TOPS = [68, 73, 78, 12]; + const ROW_DURATIONS = [DURATION_BOTTOM, DURATION_BOTTOM, DURATION_BOTTOM, DURATION_TOP]; // 轮流分配到 4 行 const rows = [[], [], [], []]; @@ -241,24 +315,17 @@ Page({ rows[i % 4].push(w); }); - const items = []; - rows.forEach((rowList, row) => { - if (rowList.length === 0) return; - const duration = row === 3 ? DURATION_TOP : DURATION_BOTTOM; - rowList.forEach((w, idx) => { - items.push({ - id: w.id, - content: w.content, - author: w.author || '匿名', - type: w.type, - top: ROW_TOPS[row], - duration, - // 均匀间隔:同屏内前后错开,不会盖住其他弹幕 - delay: -(idx * duration / rowList.length), - }); - }); - }); - return items; + // 每行存该行的所有弹幕(带位置/时长),供定时器轮流播放 + return rows.map((rowList, row) => ({ + top: ROW_TOPS[row], + duration: ROW_DURATIONS[row], + list: rowList.map((w) => ({ + id: w.id, + content: w.content, + author: w.author || '匿名', + type: w.type, + })), + })).filter((r) => r.list.length > 0); }, // 格式化许愿 @@ -482,4 +549,10 @@ Page({ path: '/pages/wish-tree/wish-tree', }; }, + + onShareTimeline() { + return { + title: '快来许愿树许下你的愿望吧!' + }; + } }); diff --git a/mini/pages/wish-tree/wish-tree.wxml b/mini/pages/wish-tree/wish-tree.wxml index 07e6092..dcb2cae 100644 --- a/mini/pages/wish-tree/wish-tree.wxml +++ b/mini/pages/wish-tree/wish-tree.wxml @@ -45,14 +45,14 @@ - + - {{item.content}} · {{item.author}} + + {{item.content}} · {{item.author}} + diff --git a/mini/pages/wish-tree/wish-tree.wxss b/mini/pages/wish-tree/wish-tree.wxss index df8360b..4f78071 100644 --- a/mini/pages/wish-tree/wish-tree.wxss +++ b/mini/pages/wish-tree/wish-tree.wxss @@ -142,7 +142,8 @@ text-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.6); animation-name: danmaku; animation-timing-function: linear; - animation-iteration-count: infinite; + animation-iteration-count: 1; + animation-fill-mode: both; will-change: transform; } @@ -608,7 +609,7 @@ } } -/* 弹幕:从屏幕右侧飘到左侧 */ +/* 弹幕:从屏幕右侧飘到左侧。每条只播一次,由 JS 控制一行一条排队出现。 */ @keyframes danmaku { 0% { transform: translateX(100vw);