hookehuyr

fix(PointsCollector): 优化积分点位置计算确保不超出屏幕边界

改进半径计算和安全区域逻辑,防止积分点在不同屏幕尺寸下超出边界。增加安全边距和二次边界检查,并在无法找到合适位置时使用默认安全位置。
...@@ -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 }
......