bakusan

  • /*
     * @title bakusan
     * @description ウェブページをクリックで爆散する #RAC7889
     * @include http://*
     * @license MIT License
     * @require JSDeferred
     */
    
    // from
    // http://reblogadventcalender7889.tumblr.com/kakusan
    
    const delta_t = 50;
    document.title += ' #クリックお願いします';
    
    var treeWalker = document.createTreeWalker(
        document.body,
        NodeFilter.SHOW_ALL,
        { acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } },
        false
    );
    var nodes = [];
    while(treeWalker.nextNode()) nodes.push(treeWalker.currentNode);
    
    nodes.forEach(function(e){
      if (e.nodeName !== 'BODY')
        e.addEventListener('click', bakusan, true);
    });
    
    Array.prototype.slice.call(document.getElementsByTagName('a')).forEach(function(a){
      var color = getStyle(a, 'color');
      var textDecoration = getStyle(a, 'text-decoration');
      a.removeAttribute('href');
      a.style.color = color;
      a.style.textDecoration = textDecoration;
    });
    
    Array.prototype.slice.call(document.getElementsByTagName('input')).forEach(function(input){
      if (input.getAttribute('type') !== 'hidden')
        input.removeAttribute('type');
    });
    
    function bakusan(evt) {
      evt.cancelBubble = true;
      var tgt = evt.target;
      var txt = tgt.textContent || tgt.value || tgt.alt || tgt.title || tgt.name || tgt.className || tgt.id  || tgt.src || tgt.nodeName;
      if (txt.length > 50) txt = txt.match(/(.{50})/)[0] || txt;
      var fontSize = Number(getStyle(tgt, 'font-size').replace('px', '')) + 10;
      var fontFamily = getStyle(tgt, 'font-family');
      var fontWeight = getStyle(tgt, 'font-weight');
      var color = getStyle(tgt, 'color');
      var delta_theta = 2 * Math.PI / txt.length;
      var c = function() {;
        var rgb = ['#'];
        for (var i = 0; i < 3; i++) {
          rgb.push(Number(255*Math.random().toFixed(0)).toString(16)
            .replace(/^(\d)$/, '0$1'));
        }
        return rgb.join('');
      }
      var colors = [c(), c(), c()];
      var x = [];
      var y = [];
      txt.split('').forEach(function(t, n){
        var p = document.createElement('p');
        p.innerHTML = t;
        p.className = 'bakusan-letter';
        p.style.position = 'absolute';
        p.style.fontSize = fontSize + 'px';
        var theta_0 = 2 * Math.PI * Math.random();
        var r_0 = 6 * fontSize * (Math.random() - 0.5);
        var x_0 = Number(((evt.pageX - 10) + (r_0 * Math.cos(theta_0))).toFixed(0));
        var y_0 = Number(((evt.pageY - 20) + (r_0 * Math.sin(theta_0))).toFixed(0));
        p.style.left = x_0 + 'px';
        p.style.top = y_0 + 'px';
        var theta_n = (delta_theta * n) + ((delta_theta / 10) * (Math.random() - 0.5));
        var v_x = eval((4.5 * Math.cos(theta_n)).toPrecision(1)); //4.5 [pixel/msec]
        var v_y = eval((4.5 * Math.sin(theta_n)).toPrecision(1));
        var rgb = color.match(/rgb\((\d+), (\d+), (\d+)\)/);
        if (rgb && rgb[1] == rgb[2] && rgb[2] == rgb[3])
          p.style.color = colors[Math.floor(3 * Math.random())];
        else
          p.style.color = color;
        p.style.fontFamily = fontFamily;
        p.style.fontWeight = fontWeight;
        p.style.zIndex = '10000';
    
        x[n] = [];
        y[n] = [];
        for (var t_i = 0; t_i < 5; t_i++) {
          x[n].push([x_0 + v_x * t_i * delta_t, 'px'].join(''));
          y[n].push([y_0 + v_y * t_i * delta_t, 'px'].join(''));
        }
    
        D().Deferred.loop(5, function(t_i) {
          p.style.left = x[n][t_i];
          p.style.top = y[n][t_i];
          if (t_i == 4) p.parentNode.removeChild(p);
          return Deferred.wait(0.05);
        });
    
        document.getElementsByTagName('body')[0].appendChild(p);
      });
      tgt.parentNode.removeChild(tgt);
    }
    
    function getStyle(el,styleProp) {
      var camelize = function (str) {
        return str.replace(/\-(\w)/g, function(str, letter){
          return letter.toUpperCase();
        });
      };
      if (el.currentStyle) {
        return el.currentStyle[camelize(styleProp)];
      } else if (document.defaultView && document.defaultView.getComputedStyle) {
        return document.defaultView.getComputedStyle(el,null)
                                   .getPropertyValue(styleProp);
      } else {
        return el.style[camelize(styleProp)]; 
      }
    }
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2012/12/22 02:47:05 - 2012-12-22
  2. 2012/12/20 05:28:14 - 2012-12-20