One-Armed Bandit in CSS

CSS Slots

The Endless Hack has begun and what a start it has been! I’m currently writing this tutorial on a Buquebus timezone crossing Rio de la Plata, the Silver River, from Argentina to Uruguay. We chose Buenos Aires as our first destination because we didn’t know anyone or what to expect and our first hack, Who the ****s in Town?, assisted us in making some contacts by indexing our Twitter social graph geographically.

In order to accomplish that, we pass each of our followers' profile location through a geocoder to improve search results. This takes a bit of time so I created a slot machine which users can play while waiting for each query. I was inspired by Tweetie’s slot machine announcement when Twitter bought their iPhone app and made it the official client “back” in 2010.

While Three.js was a tempting path to take, I decided to merge two tutorials I found on Google, CSS3 3d Primitives and CSS3 Slot Machine, into a simplified app using CSS3, HAML, Sass, Compass, CoffeeScript, and Symbolset.

Before I go into that let’s discuss the slot machine.

History

Original slot machines had 5 physical reels but simpler, 3 reel machines became the standard due to their reliability. The only inherent problem with 3 reel machines is that the combinations are cubic. So, if you have 10 symbols on each reel there would only be 10³ or 1000 combinations. Meaning the manufacture could only offer jackpots 1000 times the original bet, knowing that it should only happen 0.1% of the time. On the other hand, virtual reels can have any number of stops per reel and their combinations and jackpots can be in the millions. However, we’ll be basing our simple app around the classic 3 reel physical design as we won’t be offering any jackpots.

HTML

Using Roman’s tutorial on cylinder construction, we can create the reels. First we create an array of Symbolset objects which we will use to define what symbols are displayed on each face on the reel. I chose symbols that represent networking with people like a city, briefcase, and yes: beer. Then we have to create three sets of divs which each include the ten symbol faces in addition to placement and transformation divs:

#slots
  - symbols = [...]
  - 3.times do |i|
    .reel-outer
      .reel
        .reel-inner
          .reel-faces
            - 10.times do |i|
              .reel-outer-face
                .reel-face
                  %div{ :class => "ss-#{ symbols[i] } }
%a.spin(href="#") SPIN

CSS3

Each of our reels are 10 sided cylinders created completely in CSS3. Rather than go through every line of my code, let’s look at some of the key points and I’ll include a link to the source at the end. One thing to note, is that each line of my code below has a + pretended to it because that identifies the related cross-browser Compass mixin.

First, our HTML contains multiple container divs that relate to how each transformation is presented so let’s begin by preserving that in 3D and hiding the backs of each div.

*
  +backface-visibility(hidden)
  +transform-style(preserve-3d)

Our .reel div will be doing the actual rotating, so let’s make sure it’s set to transition at a timing which looks slot machine like.

.reel
  +transition(all)
  +transition-timing-function(cubic-bezier(0.57, -0.03, 0.57, 1.1))

Next, we’ll set the center of rotation for each .reel-face-outer and use a Sass @while loop to rotate each 36deg on its X axis creating the spokes of our slot machine.

.reel-face-outer
  +transform-origin(0, 100%)

  $i: 0
  @while $i < 10
    &:nth-child(#{ $i + 1 })
      +rotateX(#{ $i * 36 }deg)
   $i: $i + 1

Finally, we center the transform of each .reel-face and rotate each 72 deg from the spoke to create our cylinder surfaces. Each should also be given a line-height equal to its defined height so that Symbolset symbols appear centered.

JS

Once that’s all setup, spinning the wheel itself is pretty trivial with one tiny caveat: progressing the rotation value. Since we’re doing all of this in CSS3, we can’t really say: spin 360° and then spin 360° again, we have to say spin 360° and now spin 720°, adding to the total rotation with each spin. I’ll break down the CoffeeScript in the comments below:

$ ->
  result = []
  count  = 0

  # Loop through each reel
  $('.reel-outer'). each ->
    $this    = $(this)
    index    = $this.index()
    spinPlus = 0

    # When the spin link is clicked...
    $('.spin').click ->

      # Choose a random symbol between 1 and 10         
      type     = parseInt((Math.random() * 9), 10) + 1

      # Define a spin duration between 1 and 10000
      duration = parseInt((Math.random() * 10000), 10)

      # Increment the total spin value
      spinPlus += 3600

      # Multiply type by 36 (degrees) and add to the total
      spin     = type * 36 + spinPlus

      # Apply the transition duration and rotation
      $this.find('.reel').css
        WebkitTransitionDuration: "#{ duration }ms"
        WebkitTransform: "rotateX(-#{ spin }deg)"

      # Add the reel result type to array
      result.push(type)

      # Increment the spin counter
      count++

      # Once the counter reaches 3...
      if count is 3

        # And all transitions are ended, display results
        $this.on "webkitTransitionEnd transitionend", () ->
          console.log result

        count  = 0
        result = []

Jackpot Party!

Anyway, it was a fun hack and goes to show just how much you can accomplish with CSS these days. Check out the full source on Gist and follow The Endless Hack for more world-wide hacking goodness.

And as always, let me know if you have any questions or suggestions on Twitter. Thanks for reading!

 
273
Kudos
 
273
Kudos

Read this next

Free Instagram Printer

Please note this blog represents a working concept, but I cannot offer any support towards the creation of an app. Thanks for reading! A tutorial, an app, and a cause. By Lee Martin. A few weeks back I launched the In Rock We Trust... Continue →