Skip to content

Pitch location visualization#54

Draft
presentt wants to merge 9 commits intopaaatrick:mainfrom
presentt:pitch-location-viz
Draft

Pitch location visualization#54
presentt wants to merge 9 commits intopaaatrick:mainfrom
presentt:pitch-location-viz

Conversation

@presentt
Copy link
Copy Markdown

Hey @paaatrick I tried to add pitch location visualization on a strike zone like in MLB Gameday-- hope that's cool with you! Love your program.

So far:

  • Strike zone visualization: 29×15 character grid with 3×3 interior divisions using Unicode box-drawing characters
  • Pitch markers: Numbered pitches color-coded by result [I want to link this to your AtBat component, too]
  • Pitcher handedness indicator: Shows LHP/RHP after pitcher name in matchup display
  • Release point trajectory: Dotted line from pitcher release point to most recent pitch location [the projection seems off, but it still is cool to see]
  • Scrollable pitch list: had to finangle the AtBat component with panel focus switching (left/right arrows, maybe tab would be better?)

I tested with several of the playoff games so far-- check it out:
image

API Data Sources:

  • Pitch coordinates: pitchData.coordinates.pX, pZ (feet from home plate center)
  • Release point: pitchData.coordinates.x0, z0 (release position)
  • Strike zone: Batter-specific strikeZoneTop/Bottom from API
  • Pitcher handedness: gameData.players[ID].pitchHand.code

Files Modified:

  • src/components/PitchPlot.jsx - New component for pitch visualization
  • src/components/LiveGame.jsx - Integration into live game layout
  • src/components/Matchup.jsx - Added pitcher handedness display
  • src/components/AtBat.jsx - Added scrolling support
  • src/components/AllPlays.jsx - Added focus management
  • src/features/games.js - Added selectPlayers selector

I feel like I should let you know that I used claude AI heavily, but was hands on and kept track of what was happening, and it all seemed reasonable and straightforward. It's been pretty helpful in figuring where components were in your code, and figuring out the MLB API.

Would love to know what you think!

Implements text-based strike zone plot showing pitch locations
using data from MLB Stats API (pitchData.coordinates.pX/pZ).

- New component: PitchPlot.jsx with 21x13 grid strike zone
- Uses Unicode box-drawing characters for clean visualization
- Color-coded pitches: balls (green), strikes (red), in-play (blue)
- Pitches numbered chronologically 1-9
- Integrated into LiveGame.jsx below Matchup component

Tested with live BOS @ NYY game - pitches rendering in approximately
correct positions. Ready for further refinement.
- Increase grid from 21x13 to 29x15 for better granularity
- Enlarge strike zone from 9x9 to 16x11 with proper aspect ratio
  (compensates for terminal character height/width to look realistic)
- Allow pitches to overlay borders/corners (fixes missing pitches)
- Center plot horizontally in left panel
- Adjust layout spacing in LiveGame component
- Add scrolling support to AtBat component (pitch-by-pitch list)
  - Mouse scrolling, keyboard navigation, vi-style keys (j/k)
  - Matches AllPlays scrolling functionality
- Implement panel focus switching in LiveGame
  - Left/Right arrow keys (or h/l) toggle between panels
  - Only focused panel responds to scroll commands
  - Help bar shows arrow key shortcuts
- Modify AllPlays to accept focused prop (was always focused)
- Optimize layout spacing for better vertical balance
  - Reduced PitchPlot height from 18 to 15 lines
  - Gives AtBat more visible space for pitch descriptions
- Add selectPlayers selector to games.js
- Display LHP/RHP after pitcher name in Matchup component
- Add Bresenham line algorithm for drawing trajectory lines
- Draw white dotted line from release point to most recent pitch
- Only render for most recent pitch
@paaatrick
Copy link
Copy Markdown
Owner

Overall I like the idea!

I tested it out during one of yesterday's games and I had a few thoughts:

  • It seemed to me like the vertical placement of pitch numbers within the strike zone was a bit off. Pitches that were reported right at the top of the zone on the official Gameday website were being rendered closer to the top-third line.
  • The pitch trajectory line is an interesting idea, but I think I found it a little distracting after a while.
  • It would probably be good to include the colored pitch numbers in the in AtBat component, as well, so that it's easier to correlate what's in the pitch list with what's in the plot.
  • I guess if two pitches end up in the same position, only the last number is rendered? That's probably fine, but I might mull over if there are other options in that case.

I haven't had time to really look at the code changes in detail. What I'm kind of thinking at this point is that I might bring this into main after the season ends and iterate on it in the offseason.

- Add projectToCatcherView() function to convert 3D release coordinates to 2D catcher's viewpoint
- Apply scale factor based on mound-plate distance (y0 distance): ~50 feet release scales to ~9% offset
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants