octocatstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              link(href='http://fonts.googleapis.com/css?family=Lato:300,400'
rel='stylesheet'
type='text/css')

mixin cubePart(x, y, z)
  div(class="cube-part-wrapper cube-part-wrapper-#{x}#{y}#{z}"
      data-x="#{x}"
      data-y="#{y}"
      data-z="#{z}")
    .axis.axis-part
      ul.cube-part
        li(class=z>1?"side top white" : "side top")
          .sticker
        li(class=z<1?"side bottom yellow" : "side bottom")
          .sticker
        li(class=y>1?"side right orange" : "side right")
          .sticker
        li(class=y<1?"side left red" : "side left")
          .sticker
        li(class=x>1?"side back green" : "side back")
          .sticker
        li(class=x<1?"side front blue" : "side front")
          .sticker

// --- @start control section
.controls
  // --- @start button-wrapper
  .button-wrapper

    div
      - each theme in ["flat", "realistic"]
        button(type="button"
               class=theme==="flat"?"themer selected" : "themer"
               data-theme="#{theme}") #{theme}  
      button(type="button"
             class="scrambler") Scramble
h1 RubiCCS cube
h2 drag anywhere to rotate
h2 drag cube to play
h3 The middle slice does not turn, just like a real Rubik's cube
// --- @start canvas
.canvas.theme-flat
  .cube-wrapper
    .cube
      .swiper.top(data-x="y"
                  data-y="x"
                  data-control="top")
      .swiper.bottom(data-x="y"
                     data-y="x"
                     data-control="bottom")
      .swiper.left(data-x="y"
                   data-y="z"
                   data-control="left")
      .swiper.right(data-x="y"
                    data-y="z"
                    data-control="right")
      .swiper.front(data-x="z"
                    data-y="x"
                    data-control="front")
      .swiper.back(data-x="z"
                   data-y="x"
                   data-control="back")
      // --- @start grip
      .grip
        .axis.axis-grip
      // --- @start parts
      - for (var x = 0; x < 3; x++)
        - for (var y = 0; y < 3; y++)
          - for (var z = 0; z < 3; z++)
            +cubePart(x, y, z)
            
            
            
          
!
            
              //  ██╗   ██╗ █████╗ ██████╗ ███████╗
//  ██║   ██║██╔══██╗██╔══██╗██╔════╝
//  ██║   ██║███████║██████╔╝███████╗
//  ╚██╗ ██╔╝██╔══██║██╔══██╗╚════██║
//   ╚████╔╝ ██║  ██║██║  ██║███████║
//    ╚═══╝  ╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝
//

@cube-size: 15rem;
@cube-part-count: 3;
@cube-part-size: @cube-size / @cube-part-count;
@border-width: 0.3rem;
@border-radius: @border-width * 2;
@cube-color: rgb(30, 30, 30);
@cube-hover-color: #f92672;
@fast: 200ms;
@medium: @fast * 2;
@slow: @medium * 2;
@base-mix-perc: 15%;
@hover-mix-perc: 35%;
@hover-base-mix-perc: 5%;
@button-color: #2b4746;
@base-font-size: 16px;
@rotater-size: 1.8rem;
@rotater-factor: 1;
@gutter-width: 1rem;
@radius: 0.1rem;
@arrow-size: @cube-part-size / 3;
@red: #c41e3a;
@green: #009e60;
@blue:  #0051ba;
@orange: #ff5800;
@yellow: #ffd500;
@white: #fff;
.for(@i, @n) {.-each(@i)}
.for(@n)     when (isnumber(@n)) {.for(1, @n)}
.for(@i, @n) when not (@i = @n)  {
  .for((@i + ((@n - @i) / abs(@n - @i))), @n);
}
.for(@array)   when (default()) {.for-impl_(length(@array))}
.for-impl_(@i) when (@i > 1)    {.for-impl_((@i - 1))}
.for-impl_(@i)                  {.-each(extract(@array, @i));}
/**  ██████╗  █████╗ ███████╗███████╗
  *  ██╔══██╗██╔══██╗██╔════╝██╔════╝
  *  ██████╔╝███████║███████╗█████╗
  *  ██╔══██╗██╔══██║╚════██║██╔══╝
  *  ██████╔╝██║  ██║███████║███████╗
  *  ╚═════╝ ╚═╝  ╚═╝╚══════╝╚══════╝
  */
*,
*:before,
*:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: inherit;
  line-height: inherit;
  font-weight: 300;
  user-select: none;
}
html {
  height: 100%;
  min-height: 100%;
  font-size: @base-font-size;
  font-family: 'Lato', sans-serif;
  line-height: 1.25;
  color: @white;
}
html,
body {
  overflow: hidden;
}
body {
  background: @button-color;
}
ul,
ol {
  list-style: none;
  li {
    list-style: inherit;
  }
}
h1 {
  font-size: 1.5em;
  margin: 0 @gutter-width 0.5em;
}
h2 {
  font-size: 1.3em;
  margin: 0 @gutter-width 0.5em;
}
h3 {
  font-size: 1.1em;
  margin: 0 @gutter-width 0.5em;
}
/**
 *  ███████╗██████╗  █████╗ ███╗   ███╗███████╗
 *  ██╔════╝██╔══██╗██╔══██╗████╗ ████║██╔════╝
 *  █████╗  ██████╔╝███████║██╔████╔██║█████╗
 *  ██╔══╝  ██╔══██╗██╔══██║██║╚██╔╝██║██╔══╝
 *  ██║     ██║  ██║██║  ██║██║ ╚═╝ ██║███████╗
 *  ╚═╝     ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝
 *
 */

body {
  cursor: grab;
  
  &:active {
    cursor: grabbing;
  }
}

.canvas {
  position: absolute;
  height: @cube-size * 1.5;
  width: @cube-size;
  overflow: visible;
  top: 14em; 
  left: 50%;
  margin-left: @cube-size/-2; 
  perspective: 700px;
  &:hover {
    cursor: grab;
  }
  &:active {
    cursor: grabbing;
  }
}
/**
 *  ███████╗ ██████╗ ██████╗ ███╗   ███╗███████╗
 *  ██╔════╝██╔═══██╗██╔══██╗████╗ ████║██╔════╝
 *  █████╗  ██║   ██║██████╔╝██╔████╔██║███████╗
 *  ██╔══╝  ██║   ██║██╔══██╗██║╚██╔╝██║╚════██║
 *  ██║     ╚██████╔╝██║  ██║██║ ╚═╝ ██║███████║
 *  ╚═╝      ╚═════╝ ╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝
 */
::-moz-focus-inner {
  outline: 0;
}
button {
  line-height: 1;
  &:focus {
    outline: 0;
  }
}
button {
  margin: 0 @gutter-width @gutter-width;
  padding: 1em;
  font-size: 0.6rem;
  background: @button-color;
  border: 0.1rem solid #fff;
  color: #fff;
  box-shadow: none;
  border-radius: @radius;
  cursor: pointer;
  font-variant: small-caps;
  &:focus, &:hover {
    color: darken(@button-color, 10%);
    background: #fff;
    border-color: darken(@button-color, 10%);
  }
  &:active {
    color: #fff;
    border-color: darken(@button-color, 10%);
    background-color: darken(@button-color, 10%);
  }
  &:focus {
    outline: 0;
  }
  &.selected {
    color: #fff;
    border-color: darken(@button-color, 10%);
    background-color: darken(@button-color, 10%);
  }
}
.controls {
  position: absolute;
  top: 0;
  right: 0;
  max-width: 20rem;
  z-index: 5;
  padding-left: @gutter-width;
  padding-top: @gutter-width;
  cursor: default;
}

/**
 *   ██████╗██╗   ██╗██████╗ ███████╗███████╗
 *  ██╔════╝██║   ██║██╔══██╗██╔════╝██╔════╝
 *  ██║     ██║   ██║██████╔╝█████╗  ███████╗
 *  ██║     ██║   ██║██╔══██╗██╔══╝  ╚════██║
 *  ╚██████╗╚██████╔╝██████╔╝███████╗███████║
 *   ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝
 */
.cube {
  position: absolute;
  top: 0;
  left: 0;
  height: inherit;
  width: inherit;
  transition: transform @medium linear;
  transform-style: preserve-3d;
  //backface-visibility: hidden;
  transform: rotate3d(0, 1, 0, -35deg) rotate3d(1, 0, 0, 35deg);
  
  .swiper {
    position: absolute;
    left: 0;
    top: 0;
    height: @cube-size;
    width: @cube-size;
    outline-offset: 10px;
    visibility: visible; 

    
    //&:hover {
    //  box-shadow: 0 0 5px 15px @cube-hover-color;
    //}
    
    &.top {
      transform: rotate3d(0,1,0,-180deg)
        translate3d(0,0,@cube-size/-1.9);
    }
    &.bottom {
      transform: translate3d(0,0,@cube-size/-1.9);
   }   
    &.left {
      transform: rotate3d(0,1,0,90deg) 
        translate3d(0,0,@cube-size/-1.9);
    }
    &.right {
      transform: rotate3d(0,0,1,-180deg) 
        rotate3d(0,1,0,90deg) 
        translate3d(0,0,@cube-size/-1.9);
    }
    &.front {
      transform: rotate3d(1,0,0,-180deg)
        rotate3d(1,0,0,-90deg)  
        translate3d(0,0,@cube-size/-1.9);
    }
    &.back {
      transform: rotate3d(0,1,0,-180deg)
        rotate3d(1,0,0,-90deg) 
        translate3d(0,0,@cube-size/-1.9);
    }
  }
}
.cube-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  height: @cube-size;
  width: @cube-size;
  transform: translate3d(0, 0, 0);
  transition-property: transform;
  transition-timing-function: ease-out;
  transition-duration: 0;
  transform-style: preserve-3d;
  visibility: hidden; 
}
.cube-part {
  height: inherit;
  width: inherit;
  .side {
    position: absolute;
    top: 0;
    left: 0;
    height: inherit;
    width: inherit;
    line-height: @cube-part-size;
    text-align: center;
    transform-style: preserve-3d;
    border-radius: @border-radius;
    
    &.white , 
    &.blue , 
    &.orange , 
    &.red , 
    &.green , 
    &.yellow  {      
      background: @cube-color;
      .sticker {
        transform-style: preserve-3d;
        visibility: visible; 
      }
    }
    
    &.front {
      transform: translate3d((@cube-part-size /-2), 0, 0)
                 rotate3d(0, 1, 0, -90deg) scale(1);
    }
    &.back {
      transform: translate3d((@cube-part-size / 2), 0, 0)
                 rotate3d(0, 1, 0, 90deg) scale(1);
    }
    &.right {
      transform: translate3d(0, (@cube-part-size / 2), 0)
                 rotate3d(1, 0, 0, -90deg) scale(1);
    }
    &.left {
      transform: translate3d(0, (@cube-part-size / -2), 0)
                 rotate3d(1, 0, 0, 90deg) scale(1);
    }
    &.top {
      transform: translate3d(0, 0, (@cube-part-size / 2))
                 rotate3d(1, 0, 0, 0) scale(1);
    }
    &.bottom {
      transform: translate3d(0, 0, (@cube-part-size / -2))
                 rotate3d(1, 0, 0, -180deg) scale(1);
    }
  }
}
.cube-part-wrapper {
  position: absolute;
  height: @cube-part-size;
  width: @cube-part-size;
  z-index: 0;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  transition-property: all;
  transition-duration: @slow;
  pointer-events: none;
  visibility: hidden;
 
  &[data-x="0"] {
    left: 0;
  }
  &[data-x="1"] {
    left: @cube-part-size;
  }
  &[data-x="2"] {
    left: @cube-part-size * 2;
  }
  &[data-y="0"] {
    top: 0;
  }
  &[data-y="1"] {
    top: @cube-part-size;
  }
  &[data-y="2"] {
    top: @cube-part-size * 2;
  }
  &[data-z="0"] {
    transform+_: translate3d(0, 0, (@cube-part-size / -1));
  }
  &[data-z="1"] {
    transform+_: translate3d(0, 0, 0);
  }
  &[data-z="2"] {
    transform+_: translate3d(0, 0, @cube-part-size);
  }
}
/**
 *   ██████╗ ██████╗ ██╗██████╗
 *  ██╔════╝ ██╔══██╗██║██╔══██╗
 *  ██║  ███╗██████╔╝██║██████╔╝
 *  ██║   ██║██╔══██╗██║██╔═══╝
 *  ╚██████╔╝██║  ██║██║██║
 *   ╚═════╝ ╚═╝  ╚═╝╚═╝╚═╝
 *
 */
.grip {
  position: absolute;
  top: 0;
  left: 0;
  height: inherit;
  width: inherit;
  pointer-events: none;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  pointer-events: none;

  .axis {
    &.manual {
      transition: none;
    }
    transition: transform @medium;
    &.fast {
    transition: transform @fast;
    }
  }
}
.axis {
  position: absolute;
  top: 0;
  left: 0;
  height: inherit;
  width: inherit;
  transform-style: preserve-3d;
  backface-visibility: hidden;
}
/**
 * ████████╗██╗  ██╗███████╗███╗   ███╗███████╗
 * ╚══██╔══╝██║  ██║██╔════╝████╗ ████║██╔════╝
 *    ██║   ███████║█████╗  ██╔████╔██║█████╗
 *    ██║   ██╔══██║██╔══╝  ██║╚██╔╝██║██╔══╝
 *    ██║   ██║  ██║███████╗██║ ╚═╝ ██║███████╗
 *    ╚═╝   ╚═╝  ╚═╝╚══════╝╚═╝     ╚═╝╚══════╝
 */
.theme-flat {
  @border-radius: @border-width;
  .cube-part-wrapper-112 {
    .cube-part .side.white .sticker {
      background-image: 
        url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/28359/rubik-logo.png');
      background-size: 100% auto;
    }
  }
  .cube-part {
    .side {
      //background: @cube-color; 
      background: none; 
      border-radius: 0;
    &.white, 
      &.blue, 
      &.orange, 
      &.red, 
      &.green, 
      &.yellow  { 
        .sticker {
          transform: translateZ(1px);       
          position: absolute;
          top: @border-width;
          left: @border-width;
          right: @border-width;
          bottom: @border-width;
          border-radius: @border-radius;
          z-index: 2;
          backface-visibility: hidden; 
       }
     }
      &.white .sticker {
        background-color: @white;
      }
      &.blue .sticker {
        background-color: @blue;
      }
      &.orange .sticker {
        background-color: @orange;
      }
      &.red .sticker {
        background-color: @red;
      }
      &.green .sticker {
        background-color: @green;
      }
      &.yellow .sticker {
        background-color: @yellow;
      }
    }
  }
}

/**
 * ████████╗██╗  ██╗███████╗███╗   ███╗███████╗
 * ╚══██╔══╝██║  ██║██╔════╝████╗ ████║██╔════╝
 *    ██║   ███████║█████╗  ██╔████╔██║█████╗
 *    ██║   ██╔══██║██╔══╝  ██║╚██╔╝██║██╔══╝
 *    ██║   ██║  ██║███████╗██║ ╚═╝ ██║███████╗
 *    ╚═╝   ╚═╝  ╚═╝╚══════╝╚═╝     ╚═╝╚══════╝
 */
.theme-realistic {
  
  .cube-part-wrapper-112 {
    .cube-part .side.white .sticker {
      background-image: 
        url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/28359/rubik-logo.png');
      background-size: 100% auto;
    }
  }
  .cube-part {
    .side {
       visibility: visible; 

      box-shadow: 
        0 0 2px 0 
          lighten(@cube-color, 13%) inset,
        0 0 0 @border-width 
          lighten(@cube-color, 5%) inset;
      border-radius: @border-radius;
         background-color: @cube-color;

      .sticker {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: @border-radius;
        z-index: 2;
        background-color: @cube-color;
         box-shadow: 
           0 0 2px 0 
             lighten(@cube-color, 13%) inset,
           0 0 0 @border-width 
              lighten(@cube-color, 5%) inset,
           0 0 1px (@border-width + 0.1) 
              rgba(255, 255, 255, 0.2) inset;
        background-image:
           radial-gradient(ellipse farthest-corner,
             rgba(255, 255, 255, 0.1) 0%,
             rgba(255, 255, 255, 0) 60%,
             rgba(255, 255, 255, 0));
      }
      
      &.white .sticker{
        background-color: @white;
      }
      &.blue .sticker{
        background-color: @blue;
      }
      &.orange .sticker{
        background-color: @orange;
      }
      &.red .sticker{
        background-color: @red;
      }
      &.green .sticker{
        background-color: @green;
      }
      &.yellow .sticker{
        background-color: @yellow;
      }

      &.white, 
      &.blue, 
      &.orange, 
      &.red, 
      &.green, 
      &.yellow  { 
        .sticker {
          transform: translateZ(1px);
        }
      }
    }
  }
}
            
          
!
            
              /* jshint sub: true */
(function($, window, document, undefined) {
  'use strict';
  var data = {};
  var allTurns = ['base', 'left', 'right'];
  var allAx = ['x', 'y', 'z'];
  for (var a = 0; a < allAx.length; a++) {
    data[allAx[a]] = {};
    for (var l = 0; l < allTurns.length; l++) {
      data[allAx[a]][allTurns[l]] = {};
    }
  }
  var makeData1 = function(m, n, o, i, dir) {
    var v = $.extend(true, [], data[m].base[i]);
    var w = $.extend(true, [], data[m].base[i]);
    data[m][dir][i] = v.sort(function(a, b) {
      if (a[o] > b[o]) {
        return 1;
      } else if (a[o] < b[o]) {
        return -1;
      } else {
        if (a[n] > b[n]) {
          return -1;
        } else {
          return 1;
        }
      }
    });

  };

  var makeData2 = function(m, n, o, i, dir) {
    var v = $.extend(true, [], data[m].base[i]);
    var w = $.extend(true, [], data[m].base[i]);
    data[m][dir][i] = w.sort(function(a, b) {
      if (a[o] > b[o]) {
        return -1;
      } else if (a[o] < b[o]) {
        return 1;
      } else {
        if (a[n] > b[n]) {
          return 1;
        } else {
          return -1;
        }
      }
    });
  };

  var makeData3 = function(m, n, o, i, dir) {
    var v = $.extend(true, [], data[m].base[i]);
    var w = $.extend(true, [], data[m].base[i]);
    data[m][dir][i] = v.sort(function(a, b) {
      if (a[o] > b[o]) {
        return 1;
      } else if (a[o] < b[o]) {
        return -1;
      } else {
        if (a[n] > b[n]) {
          return 1;
        } else {
          return -1;
        }
      }
    });
  };

  var makeData4 = function(m, n, o, i, dir) {
    var v = $.extend(true, [], data[m].base[i]);
    var w = $.extend(true, [], data[m].base[i]);
    data[m][dir][i] = w.sort(function(a, b) {
      if (a[o] > b[o]) {
        return -1;
      } else if (a[o] < b[o]) {
        return 1;
      } else {
        if (a[n] > b[n]) {
          return -1;
        } else {
          return 1;
        }
      }
    });
  };


  for (var i = 0; i < 3; i++) {
    data['x']['base'][i] = [{
      'x': i,
      'y': 0,
      'z': 0
    }, {
      'x': i,
      'y': 0,
      'z': 1
    }, {
      'x': i,
      'y': 0,
      'z': 2
    }, {
      'x': i,
      'y': 1,
      'z': 0
    }, {
      'x': i,
      'y': 1,
      'z': 1
    }, {
      'x': i,
      'y': 1,
      'z': 2
    }, {
      'x': i,
      'y': 2,
      'z': 0
    }, {
      'x': i,
      'y': 2,
      'z': 1
    }, {
      'x': i,
      'y': 2,
      'z': 2
    }];
    data['y']['base'][i] = [{
      'x': 0,
      'y': i,
      'z': 0
    }, {
      'x': 0,
      'y': i,
      'z': 1
    }, {
      'x': 0,
      'y': i,
      'z': 2
    }, {
      'x': 1,
      'y': i,
      'z': 0
    }, {
      'x': 1,
      'y': i,
      'z': 1
    }, {
      'x': 1,
      'y': i,
      'z': 2
    }, {
      'x': 2,
      'y': i,
      'z': 0
    }, {
      'x': 2,
      'y': i,
      'z': 1
    }, {
      'x': 2,
      'y': i,
      'z': 2
    }];
    data['z']['base'][i] = [{
      'x': 0,
      'y': 2,
      'z': i
    }, {
      'x': 1,
      'y': 2,
      'z': i
    }, {
      'x': 2,
      'y': 2,
      'z': i
    }, {
      'x': 0,
      'y': 1,
      'z': i
    }, {
      'x': 1,
      'y': 1,
      'z': i
    }, {
      'x': 2,
      'y': 1,
      'z': i
    }, {
      'x': 0,
      'y': 0,
      'z': i
    }, {
      'x': 1,
      'y': 0,
      'z': i
    }, {
      'x': 2,
      'y': 0,
      'z': i
    }];
    makeData1('x', 'y', 'z', i, 'left');
    makeData2('x', 'y', 'z', i, 'right');
    makeData2('y', 'x', 'z', i, 'left');
    makeData1('y', 'x', 'z', i, 'right');
    makeData3('z', 'y', 'x', i, 'left');
    makeData4('z', 'y', 'x', i, 'right');

  }
  var rotate3d = {
    'x': '1,0,0,',
    'y': '0,1,0,',
    'z': '0,0,1,'
  };
  var $gripAxis;
  var cubeRotationSpeed = 1.5;
  var cache = {};
  var canvas = {
    'threshold': 10,
    'block': false,
    'down': false,
    'axis': null,
    'css': '',
    'mouse': {
      'distance': 0,
      'time': 0
    }
  };
  var randomNumber = function(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  };
  var classWithPrefix = function(regex) {
    return function(index, classes) {
      return classes.split(/\s+/).filter(function(el) {
        return regex.test(el);
      }).join(' ');
    };
  };
  /**
   * @jsdoc function
   * @name rubics.clearHelpers
   * @description
   *   clear the grip after the rotation
   */
  var clearHelpers = function() {
    var $gripAxis = $('.grip .axis');
    $gripAxis.css({
      transition: 'none',
      transform: ''
    });
    setTimeout(function() {
      $gripAxis.css({
        transition: ''
      });
    }, 0);
  };
  /**
   * @jsdoc function
   * @name rubics.positionParts
   * @description
   *   puts the cubes in the new position
   */
  var positionParts = function(turnAxis, level, direction) {
    if (!turnAxis) {
      return false;
    }
    var axis = ['x', 'y', 'z'];
    var elements = [];
    var oppositeDirection = direction === 'right' ? 'left' : 'right';
    $.each(data[turnAxis]['base'][level], function(i, obj) {
      var selector3d = '[data-x="';
      selector3d += obj['x'];
      selector3d += '"][data-y="';
      selector3d += obj['y'];
      selector3d += '"][data-z="';
      selector3d += obj['z'] + '"]';
      elements.push($(selector3d));
    });
    $.each(elements, function(i, el) {
      $.each(axis, function(j, ax) {
        $(el).attr('data-' +
          ax, data[turnAxis][oppositeDirection][level][i][ax]);
      });
    });
  };
  /**
   * @jsdoc function
   * @name rubics.performTurn
   * @description
   *   performes the turn.
   *   allows a callback when the turn is done
   */
  var performTurn = function(rotate3d, turnAxis, direction, callback) {
    var degree = direction === 'right' ? 90 : -90;
    $('.grip').find('.axis-grip:first').css({
      transform: 'rotate3d(' +
        rotate3d[turnAxis] +
        degree +
        'deg)'
    }).one('transitionend', callback);
  };
  /**
   * @jsdoc function
   * @name rubics.rotateParts
   * @description
   *   rotates the parts
   */
  var rotateParts = function(rotate3d, turnAxis, direction) {
    $('.grip .cube-part-wrapper').each(function(i, el) {
      var degree = direction === 'right' ? 90 : -90;
      var css = $(el).find('.axis-part')[0].style.transform;
      css = css === 'none' ? '' : css;
      css = 'rotate3d(' +
        rotate3d[turnAxis] +
        degree +
        'deg) ' +
        css;
      $(el).find('.axis-part').css({
        transform: css
      });
    });
  };
  /**
   * @jsdoc function
   * @name rubics.attachParts
   * @description
   *   puts the parts back into the cube
   */
  var attachParts = function(turnAxis, level) {
    $('[data-' + turnAxis + '=' + level + ']')
      .appendTo('.cube');
  };
  /**
   * @jsdoc function
   * @name rubics.detachParts
   * @description
   *   puts the parts into the grip
   */
  var detachParts = function(turnAxis, level) {
    $('[data-' + turnAxis + '=' + level + ']')
      .appendTo('.grip .axis-grip');
  };

  /**
   * @jsdoc function
   * @name rubics.autoTurn
   * @description
   *   automatically turn
   */
  var autoTurn = function(turnAxis, level, direction) {
    if (!canvas.block) {
      canvas.block = true;
      turnAxis = turnAxis || 'x';
      level = level || 0;
      detachParts(turnAxis, level);
      performTurn(rotate3d, turnAxis, direction, function() {
        rotateParts(rotate3d, turnAxis, direction);
        attachParts(turnAxis, level);
        clearHelpers();
        positionParts(turnAxis, level, direction);
        window.setTimeout(function() {
          canvas.block = false;
        }, 2);
      });
    } else {
      return;
    }
  };

  /**
   * @jsdoc function
   * @name rubics.scrambleCube
   * @description
   *   scramble the cube
   */
  var scrambleCube = function(n) {
    var axis = ['x', 'y', 'z'];
    var direction = ['left', 'right'];

    $gripAxis.addClass('fast');
    var duration = $gripAxis.css('transition-duration');
    duration = (parseFloat(duration) + 0.1) * 1000;
    var play = setInterval(function() {
      var dir = direction[randomNumber(0, 1)];
      var axi = axis[randomNumber(0, 2)];
      var level = randomNumber(0, 2);


      dir = cache.dir === dir ? (dir === 'left' ? 'right' : 'left') : dir;
      axi = cache.axi === axi ? (axi === 'x' ? 'y' : 'z') : axi;
      axi = cache.axi === axi ? (axi === 'z' ? 'x' : 'y') : axi;
      axi = cache.axi === axi ? (axi === 'y' ? 'z' : 'x') : axi;
      level = level === 1 ? randomNumber(0, 2) : level;
      level = level === 1 ? 2 : level;
      level = cache.level === level ? (level === 0 ? 2 : 0) : level;
      level = cache.level === level ? (level === 2 ? 0 : 2) : level;

      cache = {
        dir: dir,
        axi: axi,
        level: level
      };
      autoTurn(axi, level, dir);
    }, duration);
    setTimeout(function() {
      $gripAxis.removeClass('fast');
      if (play) {
        clearTimeout(play);
      }
    }, duration * n);
  };


 
  /**
   * @jsdoc function
   * @name rubics.releaseSwiper
   * @description
   *   release the Swiper
   */
  var releaseSwiper = function(e) {
    if (canvas.swiper && canvas.swiper.play) {
      canvas.swiper.play = false;
      if (!canvas.swiper.move) {
        return false;
      }
      canvas.swiper.move = false;
      if (canvas.swiper.degree >= -30 && canvas.swiper.degree <= 30) {
        $gripAxis.removeClass('manual').css({
          transform: 'rotate3d(0,0,0,0deg)'
        }).one('transitionend', function() {
          attachParts(canvas.swiper.axis, canvas.swiper.level);
          clearHelpers();
        });
      } else {
        var direction = canvas.swiper.degree > 0 ? 'right' : 'left';
        $gripAxis.removeClass('manual').css({
          transform: 'rotate3d(' +
            rotate3d[canvas.swiper.axis] +
            (canvas.swiper.degree > 0 ? '90' : '-90') + 'deg)'
        }).one('transitionend', function() {
          rotateParts(rotate3d, canvas.swiper.axis, direction);
          attachParts(canvas.swiper.axis, canvas.swiper.level);
          clearHelpers();
          positionParts(canvas.swiper.axis, canvas.swiper.level, direction);
          canvas.swiper = false;
        });
      }
    }
  };
  /**
   * @jsdoc function
   * @name rubics.moveSwiper
   * @description
   *   movement on the the Swiper
   */
  var moveSwiper = function(e) {
    if (canvas.swiper && canvas.swiper.play) {
     e.preventDefault();
     canvas.swiper.move = {
        'x': e.offsetX || e.originalEvent.layerX,
        'y': e.offsetY || e.originalEvent.layerY
      };
      canvas.swiper.distance = {};
      canvas.swiper.distance.x = (canvas.swiper.start.x -
        canvas.swiper.move.x) /
        canvas.swiper.size.x * 90;
      canvas.swiper.distance.y = (canvas.swiper.start.y -
        canvas.swiper.move.y) /
        canvas.swiper.size.x * 90;

      if (!canvas.swiper.active &&
        (canvas.swiper.distance.x > canvas.threshold ||
          canvas.swiper.distance.x < -1 * canvas.threshold)) {
        canvas.swiper.axis = canvas.swiper.sides.x;
        canvas.swiper.degree = (canvas.swiper.start.x -
          canvas.swiper.move.x) /
          canvas.swiper.size.x * 90;
        canvas.swiper.side = 'y';
        canvas.swiper.turn = 'x';
        canvas.swiper.active = true;
      } else if (!canvas.swiper.active &&
        (canvas.swiper.distance.y > canvas.threshold ||
          canvas.swiper.distance.y < -1 * canvas.threshold)) {
        canvas.swiper.axis = canvas.swiper.sides.y;
        canvas.swiper.side = 'x';
        canvas.swiper.turn = 'y';
        canvas.swiper.active = true;
      }
      if (canvas.swiper.axis) {

        if (!canvas.swiper.init) {
          canvas.swiper.init = true;
          if (canvas.swiper.delta[canvas.swiper.side] < 1.5) {
            canvas.swiper.level = canvas.swiper.side === 'x' ? 0 : 2;
            canvas.swiper.level = canvas.swiper.side === 'y' &&
              canvas.swiper.control === 'right' ? 0 : canvas.swiper.level;
            canvas.swiper.level = canvas.swiper.side === 'x' &&
              canvas.swiper.control === 'front' ? 2 : canvas.swiper.level;
            canvas.swiper.level = canvas.swiper.side === 'x' &&
              canvas.swiper.control === 'bottom' ? 2 : canvas.swiper.level;

            canvas.swiper.level = canvas.swiper.controls === 'front' &&
              canvas.swiper.side === 'x' ? 0 : canvas.swiper.level;
          } else if (canvas.swiper.delta[canvas.swiper.side] < 3) {
            return false; // can't turn ceter slice
            canvas.swiper.level = 1;
          } else {
            canvas.swiper.level = canvas.swiper.side === 'x' ? 2 : 0;
            canvas.swiper.level = canvas.swiper.side === 'y' &&
              canvas.swiper.control === 'right' ? 2 : canvas.swiper.level;
            canvas.swiper.level = canvas.swiper.side === 'x' &&
              canvas.swiper.control === 'front' ? 0 : canvas.swiper.level;
            canvas.swiper.level = canvas.swiper.side === 'x' &&
              canvas.swiper.control === 'bottom' ? 0 : canvas.swiper.level;

          }
          detachParts(canvas.swiper.axis, canvas.swiper.level);
          $gripAxis
            .addClass('manual');
        }

        var factor = 1;
        factor = canvas.swiper.side === 'x' &&
          canvas.swiper.control === 'front' ? -1 : factor;
        factor = canvas.swiper.side === 'y' &&
          canvas.swiper.control === 'right' ? -1 : factor;
        factor = canvas.swiper.side === 'x' &&
          canvas.swiper.control === 'bottom' ? -1 : factor;
        canvas.swiper.degree = (canvas.swiper.start[canvas.swiper.turn] -
          canvas.swiper.move[canvas.swiper.turn]) /
          canvas.swiper.size[canvas.swiper.side] * 90 * factor;
        $gripAxis.css({
          transform: 'rotate3d(' +
            rotate3d[canvas.swiper.axis] +
            canvas.swiper.degree + 'deg)'
        });
      }
    }
  };

  /**
   * @jsdoc function
   * @name rubics.initSwiper
   * @description
   *   init the Swiper
   */
  var initSwiper = function(e) {

    canvas.swiper = {};
    canvas.swiper.control = $(this).data('control');
    canvas.swiper.play = true;
    canvas.swiper.sides = {
      'x': $(this).data('x'),
      'y': $(this).data('y')
    };
    canvas.swiper.size = {
      'x': e.target.clientWidth,
      'y': e.target.clientHeight
    };
    canvas.swiper.start = {
      'x': e.offsetX || e.originalEvent.layerX,
      'y': e.offsetY || e.originalEvent.layerY
    };
    canvas.swiper.delta = {
      'x': canvas.swiper.size.x / canvas.swiper.start.x,
      'y': canvas.swiper.size.y / canvas.swiper.start.y
    };

  };

  /**
   * @jsdoc function
   * @name rubics.moveCube
   * @description
   *   rotates the cube itself
   */
  var moveCube = function(e) {
    if (!canvas.down) {
      return false;
    }
    e.preventDefault();
    var x = (e.pageX - canvas['mouse']['x']) / 4;
    var y = (e.pageY - canvas['mouse']['y']) / -4;
    var transformation = '';
    if ((x > canvas.threshold ||
         x < -1 * canvas.threshold) &&
        canvas['axis'] !== 'x') {
      canvas['axis'] = 'y';
      transformation += 'rotate3d(0, 1, 0, ';
      transformation += x * cubeRotationSpeed;
      transformation += 'deg) ';
      transformation += canvas['css'];
      canvas['mouse']['distance'] = x;
      canvas.moved = true;
    } else if ((y > canvas.threshold ||
                y < -1 * canvas.threshold) &&
               canvas['axis'] !== 'y') {
      canvas['axis'] = 'x';
      transformation += 'rotate3d(1, 0, 0, ';
      transformation += y * cubeRotationSpeed;
      transformation += 'deg) ';
      transformation += canvas['css'];
      canvas['mouse']['distance'] = y;
      canvas.moved = true;

    } else {
      canvas.moved = false;
      return false;
    }
    if (canvas.moved) {
      $('.cube-wrapper').css({
        transform: transformation
      });
    }
  };

  /**
   * @jsdoc function
   * @name rubics.releaseCuber
   * @description
   *   release the Cube
   */
  var releaseCube = function(e) {
    if (canvas.down) {
      canvas.down = false;
      if (!canvas.moved) {
        return false;
      }
      canvas.moved = false;
      canvas['mouse']['end'] = +new Date();
      canvas['mouse']['time'] = canvas['mouse']['end'] - 
        canvas['mouse']['start'];
      canvas['mouse']['bouce'] = (canvas['mouse']['distance'] /
        canvas['mouse']['time']) *
        100;
      canvas['css'] = $('.cube-wrapper')[0].style.transform;
      canvas['mouse']['bouce'] = Math.abs(canvas['mouse']['bouce']) <= 
        5 ? 0 : canvas['mouse']['bouce'];
      $('.cube-wrapper').css({
        transitionDuration: Math.min(Math.abs(canvas['mouse']['bouce'] * 
          20), 300) +
          'ms',
        transform: 'rotate3d(' +
          rotate3d[canvas['axis']] +
          canvas['mouse']['bouce'] *
          cubeRotationSpeed +
          'deg) ' +
          canvas['css']
      }).one('transitionend', function() {
        $('.cube-wrapper').css({
          transitionDuration: ''
        });
      });
    }
  };

  /**
   * @jsdoc function
   * @name rubics.onMouseDown
   * @description
   *   check where we are then perform cubeRotation
   *   if not on buttons or cube
   */
  var onMouseDown = function(e) {
    e.preventDefault();
    if ($(e.target).is('.swiper') ||
        $(e.target).closest('.controls').length) {
      return false;
    }
    canvas.down = true;
    canvas['axis'] = false;
    canvas['mouse']['x'] = e.pageX;
    canvas['mouse']['y'] = e.pageY;
    canvas['css'] = $('.cube-wrapper')[0].style.transform;
    canvas['mouse']['start'] = +new Date();
  };

  $(function() {
    var $themer = $('.themer');
    var $canvas = $('.canvas');
    $gripAxis = $('.grip').find('.axis-grip:first');

    $(document)
      .on('mousedown', onMouseDown)
      .on('mouseup', releaseCube)
      .on('mousemove', moveCube);

    $('.swiper')
      .on('mousedown', initSwiper)
      .on('mouseleave mouseup', releaseSwiper)
      .on('mousemove', moveSwiper);

    $('.themer')
      .on('click', function() {
        var theme = $(this).data('theme');
        $canvas.removeClass(classWithPrefix(/^theme-/));
        $themer.removeClass('selected');
        $canvas.addClass('theme-' + theme);
        $(this).addClass('selected');
      });

    $('.scrambler')
      .on('click', function() {
        scrambleCube(30);
      });

  });
})(window.jQuery, window, document);

            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console