I’m sure most of the people that read this know of GitHub and Reddit. As an avid user of both, I wanted to recreate GitHub’s heat map/contribution graph using Reddit’s data to both learn about its implementation as well as see my Reddit activity in a neat visualization. I used , javascript library for building graphics, , super handy for DOM manipulation, and B , great for developers with poor design skills. d3.js jQuery ootstrap First, I’ll discuss the UI component and how d3 was used in this. I had a lot of help with the UI from this . For GitHub’s use case and this use case, the graph is always a year’s length which makes it simpler because the graph will always be the same length. example The entire graph is a SVG element which contains sub-elements which are also SVGs. Each square which represents a day will contain an tag in the format of so something like . The squares are first rendered with the same color, . id %Y-%m-%d 2017-01-06 #eee The square’s position is determined by its day and week. The position is determined by the week number, . x %U The week 1 of YYYY starts with a Sunday (according to %U). The days in the year before the first week are in week 0. The y position is determined by the day of the week. Sundays are first and Saturdays are last, it doesn’t make a difference if it is 0-indexed or 1-indexed. This would look something like d3.select('.js-heatmap').enter().append('svg').enter().append('rect').attr('width', CELL_SIZE).attr('height', CELL_SIZE).attr('x', (d) => d3.timeFormat('%U')(d) * CELL_SIZE).attr('y', (d) => d.getDay() * CELL_SIZE) For the square/grid coloring, each grid needs a ranking or score to determine its color. At this point, let’s assume each grid already has a score. (I’ll discuss how I calculated the score with Reddit’s API below this). Determining a grid’s color depends on a few factors: number of colors, grid ranking and ranking extremes (min and max). Basically, the score will be projected onto a scale based on the number of colors. In this case, I’m using 7 colors so the score with the highest ranking will receive color #7, the ranking with a score near the mean has color #3 and so on. Using d3’s API, this would look like. d3.scaleQuantize().domain([MIN, MAX]).range(d3.range(NUMBER_OF_COLORS).map((d) => `color${d}`)); // Assign the grid the css class. I categorized the colors into a certain css class like the following. .color0 { fill: #d6e685 }.color1 { fill: #44a340 }.color2 { fill: #28752d }.color3 { fill: #1e6823 }.color4 { fill: #365e2f }.color5 { fill: #144e12 } Onto how I used to pull data on a specific user. I used Reddit’s different types of contribution to calculate the total amount of activity in a day. For example, the number of submitted posts, comments, upvotes and downvotes in a day translates to its total score. Thankfully, the endpoints for these objects are public so when a user enters a username. Therefore, I can easily make a GET request or multiple to pull the data. Once all the data is fetched, it is then used to render the heat map. Reddit’s API The source code for this is at and the tool is live at . https://github.com/vinnyoodles/reddit-heatmap https://vinnyoodles.github.io/reddit-heatmap/ I’m a Computer Science student at Virginia Tech that loves to write code and lift weights 💪. LinkedIn Github
Share Your Thoughts