fix(PointsCollector): 优化积分点位置计算确保不超出屏幕边界
改进半径计算和安全区域逻辑,防止积分点在不同屏幕尺寸下超出边界。增加安全边距和二次边界检查,并在无法找到合适位置时使用默认安全位置。
Showing
1 changed file
with
32 additions
and
10 deletions
| ... | @@ -111,25 +111,47 @@ const generatePointsData = () => { | ... | @@ -111,25 +111,47 @@ const generatePointsData = () => { |
| 111 | // 计算项目大小和半径 | 111 | // 计算项目大小和半径 |
| 112 | const sizeRatio = item.points / maxValue; | 112 | const sizeRatio = item.points / maxValue; |
| 113 | const size = baseSize + (sizeRatio * 40); // rpx | 113 | const size = baseSize + (sizeRatio * 40); // rpx |
| 114 | - const radiusXPercent = (size / 750) * 100 / 2 * (windowWidth / windowHeight) ; // 归一化为高度的百分比 | ||
| 115 | 114 | ||
| 116 | - // 定义安全区域 | 115 | + // 优化半径计算,确保在不同屏幕尺寸下都能正确计算边界 |
| 117 | - const minX = radiusXPercent; | 116 | + // 将rpx转换为百分比,考虑屏幕宽度和高度的比例 |
| 118 | - const maxX = 100 - radiusXPercent; | 117 | + const sizeInVw = (size / 750) * 100; // 转换为vw单位的百分比 |
| 119 | - const minY = radiusXPercent + 5; | 118 | + const aspectRatio = windowWidth / windowHeight; |
| 120 | - const maxY = 60; // 限制在视图的顶部60% | 119 | + const radiusPercent = (sizeInVw / 2) / aspectRatio; // 转换为高度百分比的半径 |
| 120 | + | ||
| 121 | + // 定义更严格的安全区域,确保积分不会跑出屏幕 | ||
| 122 | + const safeMargin = Math.max(radiusPercent * 1.2, 8); // 至少8%的安全边距 | ||
| 123 | + const minX = safeMargin; | ||
| 124 | + const maxX = 100 - safeMargin; | ||
| 125 | + const minY = safeMargin + 5; // 顶部额外5%边距 | ||
| 126 | + const maxY = Math.min(60, 100 - safeMargin); // 限制在视图的顶部60%或安全区域内 | ||
| 127 | + | ||
| 128 | + // 确保安全区域有效 | ||
| 129 | + if (minX >= maxX || minY >= maxY) { | ||
| 130 | + console.warn('安全区域过小,使用默认位置'); | ||
| 131 | + x = 20 + Math.random() * 60; // 20%-80%范围 | ||
| 132 | + y = 15 + Math.random() * 40; // 15%-55%范围 | ||
| 133 | + positionedItems.push({ ...item, x, y, radiusPercent }); | ||
| 134 | + return { ...item, x, y }; | ||
| 135 | + } | ||
| 121 | 136 | ||
| 122 | do { | 137 | do { |
| 123 | attempts++; | 138 | attempts++; |
| 124 | if (attempts > maxAttempts) { | 139 | if (attempts > maxAttempts) { |
| 125 | - console.warn('无法为项目找到不重叠的位置:', item); | 140 | + console.warn('无法为项目找到不重叠的位置,使用安全位置:', item); |
| 126 | - break; // 超过尝试次数,接受当前位置 | 141 | + // 使用安全的默认位置 |
| 142 | + x = minX + Math.random() * (maxX - minX); | ||
| 143 | + y = minY + Math.random() * (maxY - minY); | ||
| 144 | + break; | ||
| 127 | } | 145 | } |
| 128 | 146 | ||
| 129 | // 在计算出的边界内生成位置 | 147 | // 在计算出的边界内生成位置 |
| 130 | x = Math.random() * (maxX - minX) + minX; | 148 | x = Math.random() * (maxX - minX) + minX; |
| 131 | y = Math.random() * (maxY - minY) + minY; | 149 | y = Math.random() * (maxY - minY) + minY; |
| 132 | 150 | ||
| 151 | + // 二次检查边界,确保不会超出屏幕 | ||
| 152 | + x = Math.max(safeMargin, Math.min(100 - safeMargin, x)); | ||
| 153 | + y = Math.max(safeMargin, Math.min(maxY, y)); | ||
| 154 | + | ||
| 133 | // 检查与中心禁飞区的距离 | 155 | // 检查与中心禁飞区的距离 |
| 134 | const dxCenter = x - 50; | 156 | const dxCenter = x - 50; |
| 135 | const dyCenter = y - 75; // 中心点在75% | 157 | const dyCenter = y - 75; // 中心点在75% |
| ... | @@ -145,7 +167,7 @@ const generatePointsData = () => { | ... | @@ -145,7 +167,7 @@ const generatePointsData = () => { |
| 145 | const dx = x - pItem.x; | 167 | const dx = x - pItem.x; |
| 146 | const dy = y - pItem.y; | 168 | const dy = y - pItem.y; |
| 147 | const distance = Math.sqrt(dx * dx + dy * dy); | 169 | const distance = Math.sqrt(dx * dx + dy * dy); |
| 148 | - const combinedRadius = radiusXPercent + pItem.radiusXPercent; | 170 | + const combinedRadius = radiusPercent + pItem.radiusPercent + 2; // 增加2%的缓冲区 |
| 149 | 171 | ||
| 150 | if (distance < combinedRadius) { | 172 | if (distance < combinedRadius) { |
| 151 | hasCollision = true; | 173 | hasCollision = true; |
| ... | @@ -154,7 +176,7 @@ const generatePointsData = () => { | ... | @@ -154,7 +176,7 @@ const generatePointsData = () => { |
| 154 | } | 176 | } |
| 155 | } while (hasCollision); | 177 | } while (hasCollision); |
| 156 | 178 | ||
| 157 | - positionedItems.push({ ...item, x, y, radiusXPercent }); | 179 | + positionedItems.push({ ...item, x, y, radiusPercent }); |
| 158 | return { ...item, x, y }; | 180 | return { ...item, x, y }; |
| 159 | }); | 181 | }); |
| 160 | } | 182 | } | ... | ... |
-
Please register or login to post a comment