|
152 | 152 | } |
153 | 153 |
|
154 | 154 | const CX = 210, CY = 210, R_OUTER = 165, R_INNER = 65; |
155 | | - const PHOTO_R = 55; |
156 | 155 |
|
157 | 156 | // 6 zones (exclude Backcourt) |
158 | 157 | const ZONES = [ |
|
177 | 176 | .range(['#2166ac', '#C9082A']) |
178 | 177 | .clamp(true); |
179 | 178 |
|
180 | | - // ── Defs: clip for player photo ─────────────────────────────────────────── |
181 | | - svg.append('defs').append('clipPath').attr('id', 'fp-photo-clip') |
182 | | - .append('circle').attr('cx', CX).attr('cy', CY).attr('r', PHOTO_R); |
183 | | - |
184 | 179 | // ── Background rings + radial frequency ticks ───────────────────────────── |
185 | 180 | const FREQ_TICKS = [0, 0.25, 0.5, 0.75, 1]; |
186 | 181 |
|
|
285 | 280 |
|
286 | 281 | // ── Bars group ──────────────────────────────────────────────────────────── |
287 | 282 | const barsG = svg.append('g'); |
288 | | - const photoEl = svg.append('image') |
289 | | - .attr('clip-path', 'url(#fp-photo-clip)') |
290 | | - .attr('preserveAspectRatio', 'xMidYMin slice'); |
291 | 283 |
|
292 | 284 | // Centre ring (covers inner part) |
293 | 285 | svg.append('circle') |
294 | 286 | .attr('cx', CX).attr('cy', CY).attr('r', R_INNER) |
295 | 287 | .attr('fill', '#090910'); |
296 | 288 |
|
297 | | - // Centre text elements (player name + total) |
| 289 | + // Centre text (player name + total) |
298 | 290 | const nameEl = svg.append('text') |
299 | | - .attr('x', CX).attr('y', CY + PHOTO_R + 14) |
| 291 | + .attr('x', CX).attr('y', CY - 6) |
300 | 292 | .attr('text-anchor', 'middle') |
| 293 | + .attr('dominant-baseline', 'middle') |
301 | 294 | .attr('fill', '#e8e8f0') |
302 | 295 | .attr('font-size', '11px') |
303 | 296 | .attr('font-weight', '600') |
304 | 297 | .attr('font-family', 'Inter, sans-serif'); |
305 | 298 | const shotsEl = svg.append('text') |
306 | | - .attr('x', CX).attr('y', CY + PHOTO_R + 28) |
| 299 | + .attr('x', CX).attr('y', CY + 10) |
307 | 300 | .attr('text-anchor', 'middle') |
| 301 | + .attr('dominant-baseline', 'middle') |
308 | 302 | .attr('fill', '#7070a0') |
309 | 303 | .attr('font-size', '9px') |
310 | 304 | .attr('font-family', 'Inter, sans-serif'); |
|
367 | 361 | ); |
368 | 362 | hitG.raise(); |
369 | 363 |
|
370 | | - // Photo |
371 | | - const pid = p.player_id; |
372 | | - photoEl |
373 | | - .attr('href', `https://cdn.nba.com/headshots/nba/latest/1040x760/${pid}.png`) |
374 | | - .attr('x', CX - PHOTO_R).attr('y', CY - PHOTO_R) |
375 | | - .attr('width', PHOTO_R * 2).attr('height', PHOTO_R * 2); |
376 | | - |
377 | 364 | nameEl.text(playerName.split(' ').slice(-1)[0]); // last name |
378 | 365 | shotsEl.text(`${p.total_shots.toLocaleString()} shots`); |
379 | 366 |
|
|
0 commit comments