skip to Main Content

I have a this spinning wheel, what I am trying to do is when the wheel starts spinning the block which is currently in the center should have opacity 100% and the rest is lets say 50% so it will give that highlight effect.

Codepen link:

Code in link

Thanks in advance

Block in the center should be highlighted when spinning

4

Answers


  1. Have all the .card elements have opacity: 0.5. We shall apply the opacity: 1 on the active .card as needed. To try to keep it as performant as possible, we only listen for active positional change when the spinner is spinning. We use requestAnimationFrame() to time our checks to the display frame.

    const {
      start,
      stop,
      tick
    } = (() => {
      // Whether we should be actively listening for changes in the active item.
      let highlightListen = false;
      // The currently highlighted item.
      let active;
    
      // Do a check of which element should be highlighted.
      const tick = () => {
        // Get the x-coordinate of the middle of the screen.
        const middle = window.innerWidth / 2;
        const middleCard = document
          // Get all elements at the point in the document of x: middle, y: 50px.
          .elementsFromPoint(middle, 50)
          // Filter this list to `.card` elements.
          .filter((element) => element.matches('.card'))
          // Get the first item from this array.
          ?.[0];
    
        // If this middle card is different from the last-known active item.
        if (active !== middleCard) {
          // Remove the highlight opacity style that was on the previously
          // active item.
          if (active) {
            active.style.opacity = '';
          }
          // Add the highlight opacity style to the new middle card. Check
          // that it exists since we might have hit an instance where the
          // the middle of the screen is not on a card.
          if (middleCard) {
            middleCard.style.opacity = '1';
          }
          // Store the new middle card.
          active = middleCard;
        }
    
        // If we should be listening to positional changes, run this check
        // again on the next drawing frame.
        if (highlightListen) {
          requestAnimationFrame(tick);
        }
      };
    
      return {
        // Start listening for active changes.
        start() {
          highlightListen = true;
          tick();
        },
        // Stop listening for active changes.
        stop() {
          highlightListen = false;
        },
        // Do a single check.
        tick,
      };
    })();
    
    $(document).ready(function() {
      //setup multiple rows of colours, can also add and remove while spinning but overall this is easier.
      initWheel();
      // Once all the elements are set up, do a single check to mark the initial state.
      tick();
    
      $('button').on('click', function() {
        var outcome = parseInt($('input').val());
        spinWheel(outcome);
      });
    });
    
    function initWheel() {
      var $wheel = $('.roulette-wrapper .wheel'),
        row = "";
    
      row += "<div class='row'>";
      row += "  <div class='card red'>1</div>";
      row += "  <div class='card black'>14</div>";
      row += "  <div class='card red'>2</div>";
      row += "  <div class='card black'>13</div>";
      row += "  <div class='card red'>3</div>";
      row += "  <div class='card black'>12</div>";
      row += "  <div class='card red'>4</div>";
      row += "  <div class='card green'>0</div>";
      row += "  <div class='card black'>11</div>";
      row += "  <div class='card red'>5</div>";
      row += "  <div class='card black'>10</div>";
      row += "  <div class='card red'>6</div>";
      row += "  <div class='card black'>9</div>";
      row += "  <div class='card red'>7</div>";
      row += "  <div class='card black'>8</div>";
      row += "</div>";
    
      for (var x = 0; x < 29; x++) {
        $wheel.append(row);
      }
    }
    
    function spinWheel(roll) {
      var $wheel = $('.roulette-wrapper .wheel'),
        order = [0, 11, 5, 10, 6, 9, 7, 8, 1, 14, 2, 13, 3, 12, 4],
        position = order.indexOf(roll);
    
      //determine position where to land
      var rows = 12,
        card = 75 + 3 * 2,
        landingPosition = (rows * 15 * card) + (position * card);
    
      var randomize = Math.floor(Math.random() * 75) - (75 / 2);
    
      landingPosition = landingPosition + randomize;
    
      var object = {
        x: Math.floor(Math.random() * 50) / 100,
        y: Math.floor(Math.random() * 20) / 100
      };
    
      $wheel.css({
        'transition-timing-function': 'cubic-bezier(0,' + object.x + ',' + object.y + ',1)',
        'transition-duration': '6s',
        'transform': 'translate3d(-' + landingPosition + 'px, 0px, 0px)'
      });
    
      // Start active positional checking.
      start();
    
      setTimeout(function() {
        $wheel.css({
          'transition-timing-function': '',
          'transition-duration': '',
        });
    
        var resetTo = -(position * card + randomize);
        $wheel.css('transform', 'translate3d(' + resetTo + 'px, 0px, 0px)');
    
        // Stop active positional checking.
        stop();
      }, 6 * 1000);
    }
    body {
      font-family: 'Titillium Web', sans-serif;
      background: #191B28;
    }
    
    .roulette-wrapper {
      position: relative;
      display: flex;
      justify-content: center;
      width: 100%;
      margin: 0 auto;
      overflow: hidden;
    }
    
    .roulette-wrapper .selector {
      width: 3px;
      background: grey;
      left: 50%;
      height: 100%;
      transform: translate(-50%, 0%);
      position: absolute;
      z-index: 2;
    }
    
    .roulette-wrapper .wheel {
      display: flex;
    }
    
    .roulette-wrapper .wheel .row {
      display: flex;
    }
    
    .roulette-wrapper .wheel .row .card {
      height: 75px;
      width: 75px;
      margin: 3px;
      border-radius: 8px;
      border-bottom: 3px solid rgba(0, 0, 0, 0.2);
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-size: 1.5em;
      opacity: 0.5;
    }
    
    .card.red {
      background: #F95146;
    }
    
    .card.black {
      background: #2D3035;
    }
    
    .card.green {
      background: #00C74D;
    }
    
    * {
      box-sizing: border-box;
    }
    <link href="https://fonts.googleapis.com/css?family=Titillium+Web" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    
    <div class='roulette-wrapper'>
      <div class='selector'></div>
      <div class='wheel'></div>
    </div>
    
    <div>
      <input placeholder='outcome'>
      <button>
        Spin Wheel
      </button>
    </div>
    Login or Signup to reply.
  2. $(document).ready(function() {
      //setup multiple rows of colours, can also add and remove while spinning but overall this is easier.
      initWheel();
    
      $('button').on('click', function() {
        var outcome = parseInt($('input').val());
        spinWheel(outcome);
      });
    });
    
    function initWheel() {
      var $wheel = $('.roulette-wrapper .wheel'),
        row = "";
    
      row += "<div class='row'>";
      row += "  <div class='card red'>1</div>";
      row += "  <div class='card black'>14</div>";
      row += "  <div class='card red'>2</div>";
      row += "  <div class='card black'>13</div>";
      row += "  <div class='card red'>3</div>";
      row += "  <div class='card black'>12</div>";
      row += "  <div class='card red'>4</div>";
      row += "  <div class='card green'>0</div>";
      row += "  <div class='card black'>11</div>";
      row += "  <div class='card red'>5</div>";
      row += "  <div class='card black'>10</div>";
      row += "  <div class='card red'>6</div>";
      row += "  <div class='card black'>9</div>";
      row += "  <div class='card red'>7</div>";
      row += "  <div class='card black'>8</div>";
      row += "</div>";
    
      for (var x = 0; x < 29; x++) {
        $wheel.append(row);
      }
    }
    
    function spinWheel(roll) {
      var $wheel = $('.roulette-wrapper .wheel'),
        order = [0, 11, 5, 10, 6, 9, 7, 8, 1, 14, 2, 13, 3, 12, 4],
        position = order.indexOf(roll);
    
      //determine position where to land
      var rows = 12,
        card = 75 + 3 * 2,
        landingPosition = (rows * 15 * card) + (position * card);
    
      var randomize = Math.floor(Math.random() * 75) - (75 / 2);
    
      landingPosition = landingPosition + randomize;
    
      var object = {
        x: Math.floor(Math.random() * 50) / 100,
        y: Math.floor(Math.random() * 20) / 100
      };
    
      $wheel.css({
        'transition-timing-function': 'cubic-bezier(0,' + object.x + ',' + object.y + ',1)',
        'transition-duration': '6s',
        'transform': 'translate3d(-' + landingPosition + 'px, 0px, 0px)'
      });
    
      setTimeout(function() {
        $wheel.css({
          'transition-timing-function': '',
          'transition-duration': '',
        });
    
        var resetTo = -(position * card + randomize);
        $wheel.css('transform', 'translate3d(' + resetTo + 'px, 0px, 0px)');
      }, 6 * 1000);
    }
    body {
      font-family: 'Titillium Web', sans-serif;
      background: #191B28;
    }
    
    .roulette-wrapper {
      position: relative;
      display: flex;
      justify-content: center;
      width: 100%;
      margin: 0 auto;
      overflow: hidden;
    }
    
    .roulette-wrapper .selector {
      width: 3px;
      background: grey;
      left: 50%;
      height: 100%;
      transform: translate(-50%, 0%);
      position: absolute;
      z-index: 2;
    }
    
    /* What I added */
    .roulette-wrapper .selector:before,
    .roulette-wrapper .selector:after {
      content: '';
      position: absolute;
      height: 100%;
      width: calc(50vw - (75px / 2));
      background: #191B28;
      opacity: 50%
    }
    
    .roulette-wrapper .selector:before {
      right: 37px;
    }
    
    .roulette-wrapper .selector:after {
      left: 37px;
    }
    /****************/
    
    .roulette-wrapper .wheel {
      display: flex;
    }
    
    .roulette-wrapper .wheel .row {
      display: flex;
    }
    
    .roulette-wrapper .wheel .row .card {
      height: 75px;
      width: 75px;
      margin: 3px;
      border-radius: 8px;
      border-bottom: 3px solid rgba(0, 0, 0, 0.2);
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-size: 1.5em;
    }
    
    .card.red {
      background: #F95146;
    }
    
    .card.black {
      background: #2D3035;
    }
    
    .card.green {
      background: #00C74D;
    }
    
    * {
      box-sizing: border-box;
    }
    <link href="https://fonts.googleapis.com/css?family=Titillium+Web" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    
    <div class='roulette-wrapper'>
      <div class='selector'></div>
      <div class='wheel'></div>
    </div>
    
    <div>
      <input placeholder='outcome'>
      <button>
        Spin Wheel
      </button>
    </div>

    It’s not exactly what you wanted but it’s close and less heavy on the computing side

    Login or Signup to reply.
  3. How to check overlapping you can find here
    jQuery/JavaScript collision detection
    But I’m not sure that your solution is correct…

    Login or Signup to reply.
  4. A different approach would be to overlay the cards with a semi transparent grayish color, with the middle bit transparent. That way no extra calculations have to happen.

    Here’s a simple snippet – overlaying with a black, transparent, black linear-gradient. Obviously you can alter that to get the effect you want.

    <link href="https://fonts.googleapis.com/css?family=Titillium+Web" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <style>
      body {
        font-family: 'Titillium Web', sans-serif;
        background: #191B28;
      }
      
      .roulette-wrapper {
        position: relative;
        display: flex;
        justify-content: center;
        width: 100%;
        margin: 0 auto;
        overflow: hidden;
      }
      
      .roulette-wrapper::after {
        content: '';
        width: 100%;
        height: 100%;
        background-image: linear-gradient(to right, black, transparent calc(50% - (75px / 2)) calc(50% + (75px / 2)), black);
        top: 0;
        left: 0;
        position: absolute;
      }
      
      .roulette-wrapper .selector {
        width: 3px;
        background: grey;
        left: 50%;
        height: 100%;
        transform: translate(-50%, 0%);
        position: absolute;
        z-index: 2;
      }
      
      .roulette-wrapper .wheel {
        display: flex;
      }
      
      .roulette-wrapper .wheel .row {
        display: flex;
      }
      
      .roulette-wrapper .wheel .row .card {
        height: 75px;
        width: 75px;
        margin: 3px;
        border-radius: 8px;
        border-bottom: 3px solid rgba(0, 0, 0, 0.2);
        display: flex;
        align-items: center;
        justify-content: center;
        color: white;
        font-size: 1.5em;
      }
      
      .card.red {
        background: #F95146;
      }
      
      .card.black {
        background: #2D3035;
      }
      
      .card.green {
        background: #00C74D;
      }
      
      * {
        box-sizing: border-box;
      }
    </style>
    <div class='roulette-wrapper'>
      <div class='selector'></div>
      <div class='wheel'></div>
    </div>
    
    <div>
      <input placeholder='outcome'>
      <button>
        Spin Wheel
      </button>
    </div>
    <script>
      $(document).ready(function() {
        //setup multiple rows of colours, can also add and remove while spinning but overall this is easier.
        initWheel();
    
        $('button').on('click', function() {
          var outcome = parseInt($('input').val());
          spinWheel(outcome);
        });
      });
    
      function initWheel() {
        var $wheel = $('.roulette-wrapper .wheel'),
          row = "";
    
        row += "<div class='row'>";
        row += "  <div class='card red'>1</div>";
        row += "  <div class='card black'>14</div>";
        row += "  <div class='card red'>2</div>";
        row += "  <div class='card black'>13</div>";
        row += "  <div class='card red'>3</div>";
        row += "  <div class='card black'>12</div>";
        row += "  <div class='card red'>4</div>";
        row += "  <div class='card green'>0</div>";
        row += "  <div class='card black'>11</div>";
        row += "  <div class='card red'>5</div>";
        row += "  <div class='card black'>10</div>";
        row += "  <div class='card red'>6</div>";
        row += "  <div class='card black'>9</div>";
        row += "  <div class='card red'>7</div>";
        row += "  <div class='card black'>8</div>";
        row += "</div>";
    
        for (var x = 0; x < 29; x++) {
          $wheel.append(row);
        }
      }
    
      function spinWheel(roll) {
        var $wheel = $('.roulette-wrapper .wheel'),
          order = [0, 11, 5, 10, 6, 9, 7, 8, 1, 14, 2, 13, 3, 12, 4],
          position = order.indexOf(roll);
    
        //determine position where to land
        var rows = 12,
          card = 75 + 3 * 2,
          landingPosition = (rows * 15 * card) + (position * card);
    
        var randomize = Math.floor(Math.random() * 75) - (75 / 2);
    
        landingPosition = landingPosition + randomize;
    
        var object = {
          x: Math.floor(Math.random() * 50) / 100,
          y: Math.floor(Math.random() * 20) / 100
        };
    
        $wheel.css({
          'transition-timing-function': 'cubic-bezier(0,' + object.x + ',' + object.y + ',1)',
          'transition-duration': '6s',
          'transform': 'translate3d(-' + landingPosition + 'px, 0px, 0px)'
        });
    
        setTimeout(function() {
          $wheel.css({
            'transition-timing-function': '',
            'transition-duration': '',
          });
    
          var resetTo = -(position * card + randomize);
          $wheel.css('transform', 'translate3d(' + resetTo + 'px, 0px, 0px)');
        }, 6 * 1000);
      }
    </script>

    Note: the GPU usage on my laptop was 15% when this was running.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search