How I Created a Shot Chart Visualization

I’ve finally completed a first draft of an interactive shot chart visualization for NBA players, with the inclusion of a couple filters and metrics that allows a user to slice the data.  This wasn’t a small task. In fact, most of the heavy work occurred in the backend to get all the data in an analyze-able format.

But I’m some people might be interested in how to create their own shot charts.  Here’s how I did it, with an explanation of the choices I encountered and the technologies I utilized along the way.

Creating a visual

On a conceptual level, making a shot chart requires 3 distinct tasks:

  1. Drawing a basketball court
  2. Obtaining the x-y coordinates of shots
  3. Drawing the x-y coordinates on the basketball court.  Summarize to areas or zones if desired.

How you accomplish these 3 things are really up to you.


I chose SVG, or Scalable Vector Graphics, as my drawing technology.  SVG is an emerging web standard, and most modern browsers can interpret SVG natively.  This means if you want to distribute your shot chart over the internet, your users don’t have to download any plugins (unlike Flash or Java), and you don’t have to code in a separate, non-browser language.

Like its name implies, another great thing about SVG is the ability to scale graphics without getting fuzzy.  If you’ve ever tried to make a static image file larger, you’ll have noticed the image looking less crisp around the edges.  With SVG, you have the ability to scale up or down a graphic without sacrificing resolution.

If you’re unfamiliar with SVG, I’d encourage you to download a program called Inkscape, which is an open-source application similar to Adobe Illustrator that allows you to create SVG-based files.

Obtaining X-Y coordinates

As I mentioned earlier, this is the hardest part of the task.  This is out of the scope of knowing how to do a visualization, but if you’re interested in how I got this data, I basically created my own parsing codebase that not only allowed me to extract X-Y coordinates, but also combined that with the play-by-play data.

If you’re interested, you can find the code at  Honestly, it’s kind of a mess.  I’d rather you skip the hassle and pick up the final outputted data at

In terms of file format, I use JSON, because I find it more lightweight to traverse than CSV or XML.  Which brings me to my last technology…


With SVG, you can draw a basketball court pretty easily.  With a shot chart’s X-Y coordinates, you know where you need to place the shots on the court you just drew.  Now to programmatically place the shots on the court (which you wouldn’t want to do manually for tens or hundreds of shots), you’d need to use a scripting language.

On the web, the natural choice is Javascript.  And lucky for all of us, there are a couple libraries in particular that handle much of the heavy lifting for interacting with SVG in a browser environment.

Initially I used RaphaelJS to place shots on the basketball court.  But recently, I have switched over to using another library called d3.  Both are perfectly fine, but I found d3 to be more adept at manipulating SVG elements on-the-fly, which becomes very important when creating interactive visualizations.  If you want to create static shot charts, either library will suffice.

What I love about d3 is the simplicity of its API.  Though the syntax can be a little weird, its weirdness enables you to write succinct code, abstracting away all the coding mechanics of how things have to happen, and allowing you to focus more what you want to visualization to do and look like.


Those are the technologies I used to create the shot chart visualizations.  However, I wanted to take it a step further, and allow user interaction.  I think a lot of the shot chart visualizations out there are great, but I feel what’s missing is the ability for users to do their own explorations.

My choices of technologies all hinged upon my need to have user interaction.  All of these are web standards within the browser, and even in this world of mobile apps, I still believe the browser will continue to be the primary app for the interactive with the web.

To allow for filtering and in-browser slicing and dicing of shot data, I used another open source Javascript library from Mike Bostock, founder of d3: CrossFilter.  This nifty little tool basically allows you to mimic Excel’s Pivot Tables with Javascript, cutting the data by certain dimensions, and summarizing metrics based on those cuts.  It’s the tool that powers the zone visualizations in my application.

The Future

With this visualization as a foundation, I still have plans to allow even more exploration of shot chart data by implementing more data.  Here are some upcoming features I hope to accomplish:

  • Filtering by multiple games or periods (dependent on an update to the CrossFilter project)
  • Adding filters by shot type (i.e. jumpers vs. hook shots vs. bank shots)
  • Showing assisted vs. non-assisted shots
  • Zone FG % compared to player’s historical averages
  • Zone FG % compared to players at their position
  • Porting the visualization over to entire teams, and not just players… maybe even five-man units?

I’ve got a few other really fun ideas floating around in my mind, but if you have any yourself, please feel free to share with me below.

– Ken

6 thoughts on “How I Created a Shot Chart Visualization”

  1. This stuff looks great. I was wondering if you would be able to apply this to NCAA teams as well? I’m looking to do a story on the 2012-2013 Syracuse University Basketball team now and I’m having trouble figuring out the best way to compile and represent this data. Any suggestions/help would be much appreciated. E-mail me at

  2. Super helpful- was trying to do this all day yesterday and wish I found this at the beginning. Any plans to expand this with the now public sportvu data?

    1. Fairly certain SportVu does not publish the actual XY coordinates of each event. But if you can find such a source, I will find a way to incorporate it.

      1. Correct you are (unfortunately)- I was foolishly hoping for much more of the data than they have publicly released. I am, however working on trying to automate a way to get somewhat Cartesian plotting info using their live player tracking… Fingers crossed for now.

  3. Awesome setup. Do you think there would be any way to code this so that someone could input their own data somehow? Like for personalized zone visualizations.

    1. Glad you asked. Yes, I am working on a shot chart data entry tool. Still iterating on the prototype, but I will write a post or tweet when it’s ready for use. I’m thinking sometime in December.

Leave a Reply