72 lines
4.2 KiB
YAML
72 lines
4.2 KiB
YAML
date: 2017-09-05
|
|
tags:
|
|
- linux
|
|
- git
|
|
title: Visualizing Web Design Evolution Using Git
|
|
---
|
|
|
|
My website here, as of the time of writing this, is still based on a design I made back in 2010, and is rendered using my [static site generator](http://github.com/nickpegg/posty) that I haven't touched in nearly as long. The site's served its purpose pretty well, but it's kind of a mess; It's unreadable on mobile devices, the CSS causes some weird inconsistencies, and the static site generator is no where near my current standards. So since this is a personal project I have the liberty of throwing it all in the trash and starting over (and learning new things along the way!).
|
|
---
|
|
Since my weakest area is front-end (design, Javascript, CSS that doesn't look like it was written by a crazy person, etc.), I decided to jump in there, doing a couple of experiments. I ended up spending the better part of a weekend fiddling with HTML, playing with a couple of CSS frameworks to see what I liked, and incessantly bugging my friend [Brian](https://bokstuff.com) for help. Eventually I got something that I thought looked pretty good and got the 'final' version checked into git.
|
|
|
|
So you want to know the cool part about git? If you use it right, you have a bunch of commits containing the full history of what you're building! And with a bit of magic you can come up with something like this:
|
|
|
|
[](/media/img/design_vis/progress.gif)
|
|
|
|
(click on image to see the full size version)
|
|
|
|
Neat, huh? So how the heck did I manage to pull this off? With some shell scripting wizardry!
|
|
|
|
Since all of my design is in a single HTML file, `index.html`, it's easy to comb through the history with the `git log` command. And to get the commit hashes to iterate over them, just add in some `grep`, `awk`, and `tac` to reverse-sort them (from oldest to newest).
|
|
|
|
```
|
|
git log -- index.html | grep commit | grep -v initial | awk '{print $2}' | tac
|
|
```
|
|
|
|
Okay, cool, so now we can flip through the history of our `index.html`, now how do we make an animated GIF of it? Well, an animation is just a set of images, so we need to figure out how to turn our HTML into an image a bunch of times. This is where [wkhtmltopdf](https://wkhtmltopdf.org/) comes in handy! The name's kind of a mouthful, but it's a tool that uses WebKit to render HTML and output that to a PDF (or an image). It's super simple to use! Just give it a URL or file name, and then a file to output to, and it does the rest.
|
|
|
|
```
|
|
wkhtmltoimage --width 1920 --height 1080 index.html index${NUM}.png
|
|
```
|
|
|
|
Alright, now we've got a bunch of images, how do we string those together into a GIF? For things like this, I always turn to ImageMagick's `convert` tool, which is the swiss-army-knife of image manipulation. It turns out that if you pass it a bunch of still images and a filename that ends in `.gif`, it just knows to make a GIF! Incredible! Since we want it to slowly go through the changes so you can play spot-the-difference, we add in a `-delay 100` to the command to tell it to wait 100 tens of milliseconds between each frame.
|
|
|
|
```
|
|
convert -delay 100 index*.png progress.gif
|
|
```
|
|
|
|
Add in some hackery to remove duplicates (because the rendered page may not change if you change the HTML) and to add a pause of the last frame, and this is what I came up with:
|
|
|
|
```
|
|
#!/bin/bash
|
|
|
|
# requires that imagemagick and wkhtmltopdf are installed
|
|
|
|
mkdir -p progress
|
|
git checkout master
|
|
|
|
mkhtmltoimage --crop-w 1920 --crop-h 1080 https://nickpegg.com progress/0000.png
|
|
|
|
count=0
|
|
commits=$(git log | grep commit | grep -v initial | awk '{print $2}' | tac)
|
|
|
|
for commit in $(echo $commits | xargs); do
|
|
git checkout "$commit"
|
|
i=$((++count))
|
|
wkhtmltoimage --crop-w 1920 --crop-h 1080 index.html "progress/$(printf "%04d" "$count").png"
|
|
done
|
|
|
|
# Magical one-liner to remove duplicates
|
|
md5sum progress/* | \
|
|
sort | \
|
|
awk 'BEGIN{lasthash = ""} $1 == lasthash {print $2} {lasthash = $1}' | \
|
|
xargs rm
|
|
|
|
# Add an artificial pause by copying the last file a few times
|
|
for i in $(seq $((count+1)) $((count+5))); do
|
|
cp progress/$(printf "%04d" "$count").png progress/$(printf "%04d" "$i").png
|
|
done
|
|
|
|
convert -delay 100 progress/*png progress.gif
|
|
git checkout master
|
|
```
|