Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is Google's buckyball doodle implemented?

I've had a look at the markup it creates, namely a bunch of atom images for the atoms, and a big background image, which is used rather strangely to create the bonds.

There are some things that I can't work out:

  1. Where the javascript is
  2. What makes the bonds at the rear narrower
  3. Why the atoms also have the bond background applied

Here's what the google doodle looked like, for those who are interested:

doodle

like image 404
Eric Avatar asked Sep 04 '10 11:09

Eric


2 Answers

Ok, here's the javascript, after having run it through jsBeautifier:

(function () {
    var a = true,
        c = false;
    try {
        if (!google.doodle) google.doodle = {};
        var aa = -1 / 14,
            ba = Math.PI / 180,
            d = (1 + Math.sqrt(5)) / 2,
            e = 1 / 3,
            k = 2 / 3,
            l = d / 3,
            n = 2 * l,
            o = [
                [-k, -e - n, -l],
                [-e, -k - l, -n],
                [e, -k - l, -n],
                [k, -e - n, -l],
                [e, -d, 0],
                [-e, -d, 0],
                [-l, -k, -e - n],
                [-n, -e, -k - l],
                [-e - n, -l, -k],
                [-k - l, -n, -e],
                [-k, -e - n, l],
                [-e, -k - l, n],
                [e, -k - l, n],
                [k, -e - n, l],
                [-l, -k, e + n],
                [-n, -e, k + l],
                [-e - n, -l, k],
                [-k - l, -n, e],
                [-d, 0, -e],
                [-d, 0, e],
                [-k, e + n, -l],
                [-e, k + l, -n],
                [e, k + l, -n],
                [k, e + n, -l],
                [e, d, 0],
                [-e, d, 0],
                [-l, k, -e - n],
                [-n, e, -k - l],
                [-e - n, l, -k],
                [-k - l, n, -e],
                [-k, e + n, l],
                [-e, k + l, n],
                [e, k + l, n],
                [k, e + n, l],
                [-l, k, e + n],
                [-n, e, k + l],
                [-e - n, l, k],
                [-k - l, n, e],
                [0, -e, -d],
                [0, e, -d],
                [l, k, -e - n],
                [n, e, -k - l],
                [n, -e, -k - l],
                [l, -k, -e - n],
                [k + l, -n, -e],
                [e + n, -l, -k],
                [0, -e, d],
                [0, e, d],
                [l, k, e + n],
                [n, e, k + l],
                [n, -e, k + l],
                [l, -k, e + n],
                [k + l, -n, e],
                [e + n, -l, k],
                [k + l, n, -e],
                [e + n, l, -k],
                [k + l, n, e],
                [e + n, l, k],
                [d, 0, -e],
                [d, 0, e]
            ],
            q = [
                [0, 1],
                [0, 5],
                [0, 9],
                [1, 2],
                [1, 6],
                [2, 3],
                [2, 43],
                [3, 4],
                [3, 44],
                [4, 5],
                [4, 13],
                [5, 10],
                [6, 7],
                [6, 38],
                [7, 8],
                [7, 27],
                [8, 9],
                [8, 18],
                [9, 17],
                [10, 11],
                [10, 17],
                [11, 12],
                [11, 14],
                [12, 13],
                [12, 51],
                [13, 52],
                [14, 15],
                [14, 46],
                [15, 16],
                [15, 35],
                [16, 17],
                [16, 19],
                [18, 19],
                [18, 28],
                [19, 36],
                [20, 21],
                [20, 25],
                [20, 29],
                [21, 22],
                [21, 26],
                [22, 23],
                [22, 40],
                [23, 24],
                [23, 54],
                [24, 25],
                [24, 33],
                [25, 30],
                [26, 27],
                [26, 39],
                [27, 28],
                [28, 29],
                [29, 37],
                [30, 31],
                [30, 37],
                [31, 32],
                [31, 34],
                [32, 33],
                [32, 48],
                [33, 56],
                [34, 35],
                [34, 47],
                [35, 36],
                [36, 37],
                [38, 39],
                [38, 43],
                [39, 40],
                [40, 41],
                [41, 42],
                [41, 55],
                [42, 43],
                [42, 45],
                [44, 45],
                [44, 52],
                [45, 58],
                [46, 47],
                [46, 51],
                [47, 48],
                [48, 49],
                [49, 50],
                [49, 57],
                [50, 51],
                [50, 53],
                [52, 53],
                [53, 59],
                [54, 55],
                [54, 56],
                [55, 58],
                [56, 57],
                [57, 59],
                [58, 59]
            ],
            r, s, t, u, v, z, A, B, da = 0,
            C = 0,
            D = [],
            E = [],
            F = [],
            G = 0,
            H = 0,
            I, J = 0,
            K = 0,
            L = 0,
            M = 0,
            N = 0,
            O = 0,
            P = 0,
            Q = 0,
            R, S = c,
            T = c,
            U = a,
            V, W, ea, fa, ha = function () {
                if (S) {
                    var b = C - 20;
                    if (Math.abs(b) > 0.01) {
                        H += -0.5 * b;
                        H *= 0.6;
                        C += H;
                        if (C < 0) C = 0
                    } else C = 20;
                    var f = J - L,
                        g = K - M;
                    if (b = I && Math.sqrt(J * J + K * K) < 35) {
                        N += f;
                        O += g
                    } else {
                        if (R) {
                            Q = Math.min(20, Math.sqrt(f * f + g * g));
                            P = Math.atan2(g, f)
                        }
                        N += Math.cos(P) * Q;
                        O += Math.sin(P) * Q;
                        Q = Math.max(1, Q * 0.97)
                    }
                    var h = N * 0.4;
                    g = O * 0.4;
                    N -= h;
                    O -= g;
                    f = o;
                    var i = Math.sqrt(h * h + g * g);
                    if (i == 0) o = f;
                    else {
                        g = g / i;
                        h = -h / i;
                        i = i * ba;
                        var w = 1 - Math.cos(i),
                            x = Math.sin(i),
                            j = g * h;
                        i = 1 + w * (g * g - 1);
                        j = w * j;
                        var m = h * x,
                            y = j,
                            ka = 1 + w * (h * h - 1),
                            la = -g * x,
                            ma = -h * x;
                        x = g * x;
                        w = 1 + w * -1;
                        for (var ca = [], na = 0, p; p = f[na++];) {
                            g = p[0];
                            h = p[1];
                            p = p[2];
                            ca.push([i * g + j * h + m * p, y * g + ka * h + la * p, ma * g + x * h + w * p])
                        }
                        o = ca
                    }
                    L = J;
                    M = K;
                    R = b;
                    b = o;
                    f = [];
                    for (g = 0; h = b[g++];) {
                        i = 3.8 / (3.8 + h[2]);
                        f.push([h[0] * i, h[1] * i, i])
                    }
                    b = f;
                    for (f = 0; i = b[f]; ++f) {
                        g = i[0] * C;
                        h = i[1] * C;
                        j = i[2] * 4;
                        m = D[f];
                        m.width = j;
                        m.height = j;
                        m.style.left = 143 + g - j / 2 + "px";
                        m.style.top = 70 + h - j / 2 + "px";
                        m.style.zIndex = i[2] > 1 ? "4" : "1";
                        ga(m, i[2]);
                        T && r.appendChild(m)
                    }
                    T = c;
                    for (f = 0; g = q[f]; ++f) {
                        i = b[g[0]];
                        j = b[g[1]];
                        if (i && j) {
                            g = (i[0] + j[0]) / 2 * C;
                            h = (i[1] + j[1]) / 2 * C;
                            m = (i[2] + j[2]) / 2;
                            y = E[f];
                            y.l((i[0] - j[0]) * C, (i[1] - j[1]) * C);
                            y.position(g, h);
                            y.a.style.zIndex = m > 1 ? "3" : "0";
                            ga(y.a, m)
                        }
                    }
                } else {
                    f = da++ * aa;
                    b = 143 + Math.sin(f) * 20;
                    f = 70 + Math.cos(f) * 20;
                    B.style.left = b + "px";
                    B.style.top = f + "px";
                    if (U && A) {
                        r.appendChild(B);
                        U = c
                    }
                    F[G].m(b + Math.random() * 2, f + Math.random() * 2);
                    G = modulo(++G, F.length);
                    for (b = 0; f = F[b++];) f.i()
                }
            },
            X = function () {
                if (!S) {
                    T = S = a;
                    google.dom.remove(B);
                    for (var b = 0, f; f = F[b++];) f.h();
                    Q = Math.random() * 20;
                    P = Math.random() * Math.PI
                }
            },
            Y = function () {
                this.d = this.e = 35;
                this.c = c;
                this.a = document.createElement("div");
                this.a.className = "logo-bond";
                this.a.style.background = "url(" + s.src + ")"
            };
        Y.prototype.position = function (b, f) {
            this.a.style.left = 143 + b - this.e / 2 + "px";
            this.a.style.top = 70 + f - this.d / 2 + "px";
            if (!this.c) {
                r.appendChild(this.a);
                this.c = a
            }
        };
        Y.prototype.l = function (b, f) {
            var g = modulo(-Math.atan2(f, b), Math.PI),
                h = Math.PI / 90;
            h = Math.round(g / h) * 35;
            g = 0 - (35 - this.e) / 2;
            h = h - (35 - this.d) / 2;
            this.a.style.backgroundPosition = g + "px " + h + "px";
            this.e = Math.max(5, Math.abs(b));
            this.d = Math.max(5, Math.abs(f));
            this.a.style.width = this.e + "px";
            this.a.style.height = this.d + "px"
        };
        var Z = function () {
            this.c = this.g = c;
            this.a = document.createElement("div");
            this.a.className = "logo-dust"
        };
        Z.prototype.m = function (b, f) {
            this.g = a;
            this.a.style.top = f + "px";
            this.a.style.left = b + "px";
            this.opacity = 1;
            if (!this.c) {
                r.appendChild(this.a);
                this.c = a
            }
        };
        Z.prototype.i = function () {
            if (this.g) {
                this.opacity -= 0.02;
                this.opacity <= 0 ? this.h() : ia(this.a, this.opacity, c)
            }
        };
        Z.prototype.h = function () {
            this.a.style.display = "none";
            google.dom.remove(this.a);
            this.g = c
        };
        var ja = function (b) {
            I = a;
            J = (b.clientX || b.pageX || 0) - r.offsetLeft - 143;
            K = (b.clientY || b.pageY || 0) - r.offsetTop - 70;
            t && I && Math.sqrt(J * J + K * K) < 30 && X()
        };
        eval("function modulo(a,n){return a" + "%%".charAt(0) + "n;}");
        var oa = function () {
            var b = document.createElement("img");
            b.src = z.src;
            b.border = 0;
            b.style.position = "absolute";
            return b
        },
            ia = function (b, f, g) {
                b.style.opacity = f;
                if (W) if (f < 0.6) {
                    b.style.filter = "alpha(opacity=" + f * 100 + ")";
                    if (g) b.style.backgroundImage = "url(" + u.src + ")"
                } else {
                    b.style.filter = "";
                    if (g) b.style.backgroundImage = "url(" + s.src + ")"
                }
            },
            ga = function (b, f) {
                var g = f > 1 ? 1 : Math.pow(f, 4);
                ia(b, g, a)
            };
        google.doodle.init = function () {
            if (window.location.href.indexOf("#") == -1) if (r = document.getElementById("hplogo")) if (!fa) {
                fa = a;
                google.j && google.j.en && $(100, pa, function () {
                    return google.rein && google.dstr
                });
                $(100, qa, function () {
                    return google.listen && google.browser && google.dom
                })
            }
        };
        var $ = function (b, f, g) {
            if (g()) f();
            else b < 200 && window.setTimeout(function () {
                $(b + 1, f, g)
            }, b)
        },
            pa = function () {
                if (!google.doodle.k) {
                    google.doodle.k = a;
                    google.rein.push(google.doodle.init);
                    google.dstr.push(ra)
                }
            },
            qa = function () {
                W = google.browser.engine.IE;
                sa();
                google.listen(document, "mousemove", ja);
                for (var b = 0; o[b++];) D.push(oa());
                for (b = 0; q[b++];) E.push(new Y);
                for (; F.length < 40;) F.push(new Z);
                B = oa();
                B.width = B.height = 7;
                V = window.setInterval(ha, 30);
                ea = window.setTimeout(ta, 5E3)
            },
            ta = function () {
                if (t) X();
                else v = a
            },
            sa = function () {
                z = new Image;
                z.onload = function () {
                    A = a
                };
                z.src = "/logos/2010/buckyball10-hp-atom.png";
                if (W) {
                    u = new Image;
                    u.onload = function () {};
                    u.src = "/logos/2010/buckyball10-hp-bond-ie.png"
                }
                s = new Image;
                s.onload = function () {
                    t = a;
                    v && X()
                };
                s.src = "/logos/2010/buckyball10-hp-bond.png"
            },
            ra = function () {
                google.unlisten(document, "mousemove", ja);
                window.clearInterval(V);
                window.clearTimeout(ea)
            }
    } catch (ua) {
        google.ml(ua, c, {
            _sn: "BKY"
        })
    };
})();
google.doodle.init()

Ain't that pretty?

like image 23
Eric Avatar answered Oct 23 '22 11:10

Eric


If you take a look at the markup, it is just a bunch of images and divs with position attributes, forming them into a sort of grid. This file: http://www.google.com/logos/2010/buckyball10-hp-bond.png is a sprite containing every bond, in every direction. This image is the atom: http://www.google.com/logos/2010/buckyball10-hp-atom.png. The JavaScript they use animates these elements by changing the positions of them.

The JavaScript is in a Script element right after the Google logo and doodle markup. The rear bonds appear narrower because their opacity is changed to be slightly transparent. Finally, it doesn't look like the atoms have the bond background. They have their own sprite (cited above.)

like image 171
Chris Laplante Avatar answered Oct 23 '22 10:10

Chris Laplante