Hex Kaleidoscope #1



Hex Kaleidoscope #1




 <div class='info'>
  <hgroup class='about'>
    <h1>Kaleidoscope</h1>
    <h2>Canvas kaleidoscope implementation with drag & drop</h2>
    <h3>Drop an image</h3>
  </hgroup>
</div>                    
                  
                



 @charset "UTF-8";
@import url(http://fonts.googleapis.com/css?family=Quantico);
html, body {
  background: #ffffff;
}

/* Info */
@keyframes show-info {
  0% {
    transform: rotateY(120deg);
  }
  100% {
    transform: rotateY(0deg);
  }
}
.info {
  transition: all 180ms ease-out;
  transform-style: preserve-3d;
  transform: perspective(800px);
  font-family: "Quantico", sans-serif;
  position: absolute;
  font-size: 12px;
  opacity: 0.8;
  color: #fff;
  width: 240px;
  left: 0px;
  top: 20px;
}
.info:hover {
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.05);
  opacity: 1;
}
.info h1, .info h2, .info h3 {
  line-height: 1;
  margin: 5px 0;
}
.info a {
  transition: all 200ms ease-out;
  border-bottom: 1px dotted rgba(255, 255, 255, 0.4);
  text-decoration: none;
  opacity: 0.6;
  color: #fff;
}
.info a:hover {
  opacity: 0.99;
}
.info .about,
.info .more {
  transform-origin: 0% 50%;
  transform: rotateY(120deg);
  margin-bottom: 1px;
  background: rgba(0, 0, 0, 0.8);
  padding: 12px 15px 12px 20px;
}
.info .about {
  animation: show-info 500ms cubic-bezier(0.23, 1, 0.32, 1) 600ms 1 normal forwards;
  padding-bottom: 15px;
}
.info .about a {
  opacity: 0.9;
}
.info .about h1 {
  letter-spacing: -1px;
  font-weight: 300;
  font-size: 19px;
  opacity: 0.95;
}
.info .about h2 {
  font-weight: 300;
  font-size: 13px;
  opacity: 0.8;
}
.info .about h3 {
  text-transform: uppercase;
  margin-top: 10px;
  font-size: 11px;
}
.info .about h3:before {
  margin-right: 2px;
  font-size: 14px;
  content: "›";
}
.info .more {
  animation: show-info 500ms cubic-bezier(0.23, 1, 0.32, 1) 500ms 1 normal forwards;
  padding: 5px 15px 10px 20px;
}
.info .more a {
  text-transform: uppercase;
  margin-right: 10px;
  font-size: 10px;
}
                
              



(function() {
  var DragDrop, Kaleidoscope, c, dragger, gui, i, image, kaleidoscope, len, onChange, onMouseMoved, options, ref, tr, tx, ty, update,
    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

  Kaleidoscope = (function() {
    Kaleidoscope.prototype.HALF_PI = Math.PI / 2;

    Kaleidoscope.prototype.TWO_PI = Math.PI * 2;

    function Kaleidoscope(options1) {
      var key, ref, ref1, val;
      this.options = options1 != null ? options1 : {};
      this.defaults = {
        offsetRotation: 0.0,
        offsetScale: 1.0,
        offsetX: 0.0,
        offsetY: 0.0,
        radius: 500,
        slices: 5,
        zoom: 1.0
      };
      ref = this.defaults;
      for (key in ref) {
        val = ref[key];
        this[key] = val;
      }
      ref1 = this.options;
      for (key in ref1) {
        val = ref1[key];
        this[key] = val;
      }
      if (this.domElement == null) {
        this.domElement = document.createElement('canvas');
      }
      if (this.context == null) {
        this.context = this.domElement.getContext('2d');
      }
      if (this.image == null) {
        this.image = document.createElement('img');
      }
    }

    Kaleidoscope.prototype.draw = function() {
      var cx, i, index, ref, results, scale, step;
      this.domElement.width = this.domElement.height = this.radius * 2;
      this.context.fillStyle = this.context.createPattern(this.image, 'repeat');
      scale = this.zoom * (this.radius / Math.min(this.image.width, this.image.height));
      step = this.TWO_PI / this.slices;
      cx = this.image.width / 2;
      results = [];
      for (index = i = 0, ref = this.slices; 0 <= ref ? i <= ref : i >= ref; index = 0 <= ref ? ++i : --i) {
        this.context.save();
        this.context.translate(this.radius, this.radius);
        this.context.rotate(index * step);
        this.context.beginPath();
        this.context.moveTo(-0.5, -0.5);
        this.context.arc(0, 0, this.radius, step * -0.51, step * 0.51);
        this.context.lineTo(0.5, 0.5);
        this.context.closePath();
        this.context.rotate(this.HALF_PI);
        this.context.scale(scale, scale);
        this.context.scale([-1, 1][index % 2], 1);
        this.context.translate(this.offsetX - cx, this.offsetY);
        this.context.rotate(this.offsetRotation);
        this.context.scale(this.offsetScale, this.offsetScale);
        this.context.fill();
        results.push(this.context.restore());
      }
      return results;
    };

    return Kaleidoscope;

  })();

  DragDrop = (function() {
    function DragDrop(callback, context, filter) {
      var disable;
      this.callback = callback;
      this.context = context != null ? context : document;
      this.filter = filter != null ? filter : /^image/i;
      this.onDrop = bind(this.onDrop, this);
      disable = function(event) {
        event.stopPropagation();
        return event.preventDefault();
      };
      this.context.addEventListener('dragleave', disable);
      this.context.addEventListener('dragenter', disable);
      this.context.addEventListener('dragover', disable);
      this.context.addEventListener('drop', this.onDrop, false);
    }

    DragDrop.prototype.onDrop = function(event) {
      var file, reader;
      event.stopPropagation();
      event.preventDefault();
      file = event.dataTransfer.files[0];
      if (this.filter.test(file.type)) {
        reader = new FileReader;
        reader.onload = (function(_this) {
          return function(event) {
            return typeof _this.callback === "function" ? _this.callback(event.target.result) : void 0;
          };
        })(this);
        return reader.readAsDataURL(file);
      }
    };

    return DragDrop;

  })();

  image = new Image;

  image.onload = (function(_this) {
    return function() {
      return kaleidoscope.draw();
    };
  })(this);

  image.src = 'https://40.media.tumblr.com/a5ec5aa4d800cbcf895ec473c06b57ec/tumblr_nnlc1jOBDr1qzgaw0o1_500.png';

  kaleidoscope = new Kaleidoscope({
    image: image,
    slices: 10
  });

  kaleidoscope.domElement.style.position = 'absolute';

  kaleidoscope.domElement.style.marginLeft = -kaleidoscope.radius + 'px';

  kaleidoscope.domElement.style.marginTop = -kaleidoscope.radius + 'px';

  kaleidoscope.domElement.style.left = '50%';

  kaleidoscope.domElement.style.top = '50%';

  document.body.appendChild(kaleidoscope.domElement);

  dragger = new DragDrop(function(data) {
    return kaleidoscope.image.src = data;
  });

  tx = kaleidoscope.offsetX;

  ty = kaleidoscope.offsetY;

  tr = kaleidoscope.offsetRotation;

  onMouseMoved = (function(_this) {
    return function(event) {
      var cx, cy, dx, dy, hx, hy;
      cx = window.innerWidth / 2;
      cy = window.innerHeight / 2;
      dx = event.pageX / window.innerWidth;
      dy = event.pageY / window.innerHeight;
      hx = dx - 0.5;
      hy = dy - 0.5;
      tx = hx * kaleidoscope.radius * -2;
      ty = hy * kaleidoscope.radius * 2;
      return tr = Math.atan2(hy, hx);
    };
  })(this);

  window.addEventListener('mousemove', onMouseMoved, false);

  options = {
    interactive: true,
    ease: 0.1
  };

  (update = (function(_this) {
    return function() {
      var delta, theta;
      if (options.interactive) {
        delta = tr - kaleidoscope.offsetRotation;
        theta = Math.atan2(Math.sin(delta), Math.cos(delta));
        kaleidoscope.offsetX += (tx - kaleidoscope.offsetX) * options.ease;
        kaleidoscope.offsetY += (ty - kaleidoscope.offsetY) * options.ease;
        kaleidoscope.offsetRotation += (theta - kaleidoscope.offsetRotation) * options.ease;
        kaleidoscope.draw();
      }
      return setTimeout(update, 1000 / 60);
    };
  })(this))();

  gui = new dat.GUI;

  gui.add(kaleidoscope, 'zoom').min(0.25).max(2.0);

  gui.add(kaleidoscope, 'slices').min(6).max(32).step(2);

  gui.add(kaleidoscope, 'radius').min(200).max(500);

  gui.add(kaleidoscope, 'offsetX').min(-kaleidoscope.radius).max(kaleidoscope.radius).listen();

  gui.add(kaleidoscope, 'offsetY').min(-kaleidoscope.radius).max(kaleidoscope.radius).listen();

  gui.add(kaleidoscope, 'offsetRotation').min(-Math.PI).max(Math.PI).listen();

  gui.add(kaleidoscope, 'offsetScale').min(0.5).max(4.0);

  gui.add(options, 'interactive').listen();

  gui.close();

  onChange = (function(_this) {
    return function() {
      kaleidoscope.domElement.style.marginLeft = -kaleidoscope.radius + 'px';
      kaleidoscope.domElement.style.marginTop = -kaleidoscope.radius + 'px';
      options.interactive = false;
      return kaleidoscope.draw();
    };
  })(this);

  ref = gui.__controllers;
  for (i = 0, len = ref.length; i < len; i++) {
    c = ref[i];
    if (c.property !== 'interactive') {
      c.onChange(onChange);
    }
  }

}).call(this);