Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I achieve a slot machine spinning effect with CSS3 & jQuery?

I am creating a demo application that randomly selects a venue when a button is clicked. Once the button is clicked I want to have the venues scroll through with a slot machine spinning animation using CSS3 and jQuery before a venue is selected.

I thought about using -webkit-keyframes and changing the background position, but it's not the ideal animation I would like.

@-webkit-keyframes spin{  
  0% {  
        background-position: 0, 0 0;
        -webkit-transform: rotateX(0deg);
     }
  100% { 
        background-position: 0, 0 -640px;
        -webkit-transform: rotateX(360deg);
     }
}

.rotating{
    -webkit-animation: spin .5s infinite linear;
    -webkit-transition: background-position .7s;
}

Can anyone give any insight on how this can be achieved? Here is what I have so far. Any help is appreciated.

Thank You

like image 778
Austin M Avatar asked Sep 19 '11 03:09

Austin M


4 Answers

After much research plagiarizing I've come up with this. Hopefully it helps in some shape or form.

const POSTERS_PER_ROW = 12;
const RING_RADIUS = 200;

function setup_posters(row) {
  var posterAngle = 360 / POSTERS_PER_ROW;
  for (var i = 0; i < POSTERS_PER_ROW; i++) {
    var poster = document.createElement('div');
    poster.className = 'poster';
    // compute and assign the transform for this poster
    var transform = 'rotateY(' + (posterAngle * i) + 'deg) translateZ(' + RING_RADIUS + 'px)';
    poster.style.webkitTransform = transform;
    // setup the number to show inside the poster
    var content = poster.appendChild(document.createElement('p'));
    content.textContent = i;
    // add the poster to the row
    //row.appendChild(poster);
  }

}

function init() {
  setup_posters(document.getElementById('ring-1'));
  setup_posters(document.getElementById('ring-2'));
  setup_posters(document.getElementById('ring-3'));
}

// call init once the document is fully loaded
window.addEventListener('load', init, false);
body {
  font-family: 'Lucida Grande', Verdana, Arial;
  font-size: 12px;
}
#stage {
  margin: 150px auto;
  width: 600px;
  height: 400px;
  /*
        
        Setting the perspective of the contents of the stage
        but not the stage itself
        
        */
  -webkit-perspective: 800;
}
#rotate {
  margin: 0 auto;
  width: 600px;
  height: 400px;
  /* Ensure that we're in 3D space */
  -webkit-transform-style: preserve-3d;
  /*
        Make the whole set of rows use the x-axis spin animation
        for a duration of 7 seconds, running infinitely and linearly
        */
  /* -webkit-animation-name: x-spin;
        -webkit-animation-duration: 7s;
        -webkit-animation-iteration-count: infinite;
        -webkit-animation-timing-function: linear;*/
}
.ring {
  margin: 0 auto;
  height: 110px;
  width: 600px;
  -webkit-transform-style: preserve-3d;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: linear;
}
.ring >:nth-child(odd) {
  background-color: #995C7F;
}
.ring >:nth-child(even) {
  background-color: #835A99;
}
.poster {
  position: absolute;
  left: 250px;
  width: 100px;
  height: 100px;
  opacity: 0.7;
  color: rgba(0, 0, 0, 0.9);
  -webkit-border-radius: 10px;
}
.poster > p {
  font-family: 'Georgia', serif;
  font-size: 36px;
  font-weight: bold;
  text-align: center;
  margin-top: 28px;
}
/*
      Set up each row to have a different animation duration
      and alternating y-axis rotation directions.
      */

#ring-1 {
  -webkit-animation-name: x-spin;
  -webkit-animation-duration: 2s;
}
/*
      #ring-2 {
        -webkit-animation-name: back-y-spin;
        -webkit-animation-duration: 4s;
      }

      #ring-3 {
        -webkit-animation-name: y-spin;
        -webkit-animation-duration: 3s;
      }*/

/*

      Here we define each of the three individual animations that
      we will be using to have our 3D rotation effect. The first
      animation will perform a full rotation on the x-axis, we'll
      use that on the whole set of objects. The second and third
      animations will perform a full rotation on the y-axis in
      opposite directions, alternating directions between rows.
    
      Note that you currently have to specify an intermediate step
      for rotations even when you are using individual transformation
      constructs.

      */

@-webkit-keyframes x-spin {
  0% {
    -webkit-transform: rotateX(0deg);
  }
  50% {
    -webkit-transform: rotateX(180deg);
  }
  100% {
    -webkit-transform: rotateX(360deg);
  }
}
@-webkit-keyframes y-spin {
  0% {
    -webkit-transform: rotateY(0deg);
  }
  50% {
    -webkit-transform: rotateY(180deg);
  }
  100% {
    -webkit-transform: rotateY(360deg);
  }
}
@-webkit-keyframes back-y-spin {
  0% {
    -webkit-transform: rotateY(360deg);
  }
  50% {
    -webkit-transform: rotateY(180deg);
  }
  100% {
    -webkit-transform: rotateY(0deg);
  }
}
<h1>//BOTCHED Poster Circle</h1>
<strike>
    <p>//This is a simple example of how to use CSS transformation and animations to get interesting-looking behavior.</p>
    <p>The three rings are constructed using a simple JavaScript function that creates elements and assigns them a transform
      that describes their position in the ring. CSS animations are then used to rotate each ring, and to spin the containing
      element around too.</p>
    <p>Note that you can still select the numbers on the ring; everything remains clickable.</p>
    
    </strike>
<p>Taken from <a href="http://www.webkit.org/blog-files/3d-transforms/poster-circle.html">HERE</a> 
</p>
<div id="stage">
  <div id="rotate">
    <div id="ring-1" class="ring">
      <div class="poster" style="-webkit-transform: rotateX(0deg) translateZ(200px); ">
        <p>0</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(30deg) translateZ(200px); ">
        <p>1</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(60deg) translateZ(200px); ">
        <p>2</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(90deg) translateZ(200px); ">
        <p>3</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(120deg) translateZ(200px); ">
        <p>4</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(150deg) translateZ(200px); ">
        <p>5</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(180deg) translateZ(200px); ">
        <p>6</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(210deg) translateZ(200px); ">
        <p>7</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(240deg) translateZ(200px); ">
        <p>8</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(270deg) translateZ(200px); ">
        <p>9</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(300deg) translateZ(200px); ">
        <p>10</p>
      </div>
      <div class="poster" style="-webkit-transform: rotateX(330deg) translateZ(200px); ">
        <p>11</p>
      </div>
    </div>
  </div>
</div>

View on JSFiddle

like image 97
MrJD Avatar answered Nov 04 '22 11:11

MrJD


how about http://odhyan.com/slot/ which uses the http://odhyan.com/slot/ plugin.

I am not sure if your keyframe approach with rotation will create the desired effect. The slot machine display rotates, but since it has large diameter, it looks more like a continues scroll. You will need to distort the top and bottom of the images, in order to make them look realistic.

If you blurry the top and bottom (transparent gif or css3 indented shadow), you might get close to the desired effect. See a video of a real slot machine

like image 32
Emil Avatar answered Nov 04 '22 11:11

Emil


In my opinion, javascript + trigonometry is your best bet. Check out this dynamic carousel and toggle the axis, I think that is the effect you're looking for.

like image 1
Jason Barry Avatar answered Nov 04 '22 11:11

Jason Barry


If you're not happy with some of the other answers here, I would consider taking a different (hopefully simpler) approach.

  • Create a vertical strip of images (or divs), with the top-most image being the one you want to stop on.
  • Use jquery's .animate() method to move them vertically inside a smaller container div, who's overflow property is set to hidden. The effect will be that you only see one at a time, 'spinning' by. If you do it quickly I think it'll look fine.
  • Play around with animation timing until you get something that looks realistic. If you need to make it look cooler, you can add some gradient png overlays to the container to simulate the 3d depth.

It's not a super-modern CSS3 solution, but it'll look nice. I couldn't find a js example, but this Flash one uses the same idea. There's no 3d here; just vertically moving images. It has a little blur but it'll still look cool w/o it. PS I hate flash.

like image 1
Chazbot Avatar answered Nov 04 '22 12:11

Chazbot