3D spin with controls

The clean interface of Sirv Spin is achieved partly by the minimal use of user interface controls. The only button shown by default is the fullscreen button in the top right.

Instead, you can add all kinds of button configurations or form controls to control a spin.

Buttons under the spin

This example adds 9 buttons underneath a 3D spin. Click the buttons to interact with the spin:

<div class="spin-container">
  <div class="viewer" style="margin-bottom: 0">
    <div
      id="smv"
      class="Sirv spin2"
      data-options="fullscreen.native:true;"
    >
      <div
        data-src="https://sirv.sirv.com/website/demos/green-car/green-car.spin?profile=green-car"
      ></div>
    </div>
    <div class="spin-buttons">
      <div id="buttonLeft" class="button flaticon-keyboard54"></div>
      <div
        id="buttonPlay"
        class="button flaticon-play106"
        style="display: none"
      ></div>
      <div
        id="buttonPause"
        class="button flaticon-pause44"
        style="display: inline"
      ></div>
      <div id="buttonRight" class="button flaticon-keyboard53"></div>
      <div id="buttonUp" class="button flaticon-expand39"></div>
      <div id="buttonDown" class="button flaticon-expand38"></div>
      <div id="buttonZoomIn" class="button flaticon-round57"></div>
      <div id="buttonZoomOut" class="button flaticon-round56"></div>
      <div id="buttonFullScreen" class="button flaticon-move26"></div>
      <div id="buttonInfo" class="button flaticon-round52"></div>
      <div id="info" style="display: none"></div>
    </div>
  </div>
</div>
<script src="https://scripts.sirv.com/sirvjs/v3/sirv.js"></script>
<link
  rel="stylesheet"
  href="https://demo.sirv.com/sirv-controls/sirv-controls.css"
/>
<script src="https://demo.sirv.com/sirv-controls/sirv-controls-v3.js"></script>
<script>
  const spinIndex = 0;
  const spinContainer = document.querySelector(".spin-container");
  const smv = spinContainer.querySelector(".smv");
  const buttonPlay = spinContainer.querySelector("#buttonPlay");
  const buttonPause = spinContainer.querySelector("#buttonPause");
  const buttonLeft = spinContainer.querySelector("#buttonLeft");
  const buttonRight = spinContainer.querySelector("#buttonRight");
  const buttonUp = spinContainer.querySelector("#buttonUp");
  const buttonDown = spinContainer.querySelector("#buttonDown");
  const buttonZoomIn = spinContainer.querySelector("#buttonZoomIn");
  const buttonZoomOut = spinContainer.querySelector("#buttonZoomOut");
  const buttonFullScreen = spinContainer.querySelector("#buttonFullScreen");
  const buttonInfo = spinContainer.querySelector("#buttonInfo");
  const infoFrame = spinContainer.querySelector("#info");

  let isPlay = true;
  const canPlay = () => {
    if (isPlay === false) {
      return;
    }
    buttonPause.click();
  };
  const playOrPause = () => {
    if (isPlay) {
      Sirv.getInstance("#smv").child(spinIndex).spin.pause();
      buttonPause.style.display = "none";
      buttonPlay.style.display = "inline";
      isPlay = false;
    } else {
      Sirv.getInstance("#smv").child(spinIndex).spin.play();
      buttonPause.style.display = "inline";
      buttonPlay.style.display = "none";
      isPlay = "true";
    }
  };
  buttonPlay.addEventListener("click", playOrPause);
  buttonPause.addEventListener("click", playOrPause);
  buttonLeft.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateX(-1);
  });
  buttonRight.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateX(1);
  });
  buttonUp.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateY(-1);
  });
  buttonDown.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateY(1);
  });
  buttonZoomIn.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.zoomIn();
  });
  buttonZoomOut.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.zoomOut();
  });
  buttonFullScreen.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").fullscreen();
  });
  buttonInfo.addEventListener("click", () => {
    const frame = Sirv.getInstance("#smv").child(spinIndex).spin.currentFrame();
    const content = `Row: ${frame.row}, Col: ${frame.column}`;
    infoFrame.textContent = content;
    infoFrame.style.display = "flex";
    setTimeout(() => {
      infoFrame.style.display = "none";
    }, 2000);
  });
</script>
<style>
  .smv-h .smv-arrow {
    position: relative;
    transition: opacity 0.2s ease;
    opacity: 0.000001;
  }
  .smv-h .smv-arrow::before,
  .smv-h .smv-arrow::after {
    display: block;
    content: "";
    position: absolute;
    background-color: transparent;
    border: 3px solid transparent;
    border-radius: 5px 5px 0 0;
    height: 22%;
    top: 50%;
    right: 20%;
    transform: translate(-50%, -99.2%) skewX(40deg);
    width: 4px;
    z-index: 1;
    box-sizing: content-box !important;
  }
  .smv-h .smv-arrow::before {
    border-bottom: none;
  }
  .smv-h .smv-arrow::after {
    border-top: none;
    transform: translate(-50%, -0.8%) skewX(-40deg);
    border-radius: 0 0 5px 5px;
  }
  .smv-arrow .smv-icon {
    -webkit-mask-repeat: none !important;
    mask-repeat: none !important;
    -webkit-mask-position: none !important;
    mask-position: none !important;
    -webkit-mask-size: none !important;
    -webkit-mask-image: none !important;
    background: transparent !important;
    z-index: 2;
    position: static !important;
  }
  .smv-arrow .smv-icon::before,
  .smv-arrow .smv-icon::after {
    display: block;
    content: "";
    position: absolute;
    background: #999;
    border-radius: 5px 5px 0 0;
    height: 22%;
    top: 50%;
    right: 20%;
    transform: translate(-50%, -99.2%) skewX(40deg);
    width: 5px;
    z-index: 2;
    margin: 0 4px;
  }
  .smv-arrow .smv-icon::before {
    border-bottom: none;
  }
  .smv-arrow .smv-icon::after {
    border-top: none;
    transform: translate(-50%, -0.8%) skewX(-40deg);
    border-radius: 0 0 5px 5px;
  }
  .smv-h .smv-arrow-prev .smv-icon {
    transform: none !important;
  }
  .smv-h .smv-arrow-prev.smv-arrow {
    transform: scaleX(-1) !important;
  }
  .smv-h .smv-arrow.smv-arrow-thumbnails {
    opacity: 1;
  }
  .smv-h .smv-arrow.smv-arrow-thumbnails::before,
  .smv-h .smv-arrow.smv-arrow-thumbnails::after {
    display: none;
  }
  .smv-h .smv-arrow.smv-arrow-thumbnails .smv-icon::before,
  .smv-h .smv-arrow.smv-arrow-thumbnails .smv-icon::after {
    right: 2px;
  }
  .smv-arrow .smv-icon {
    opacity: 1 !important;
  }
  .smv-slides-box:hover .smv-arrow {
    opacity: 0.4 !important;
  }
  .smv-slides-box:hover .smv-arrow:hover {
    opacity: 1 !important;
  }
  @media screen and (max-width: 768px) {
    .smv-h .smv-arrow {
      opacity: 1 !important;
    }
    .smv-slides-box:hover .smv-arrow {
      opacity: 1 !important;
    }
  }
  @import url(https://demo.sirv.com/sirv-controls/sirv-controls.css);

  .viewer {
    position: relative;
    margin-bottom: 80px;
  }
  .spin-buttons {
    position: relative;
    width: 100%;
    bottom: 0;
    min-height: 80px;
    z-index: 2;
    background-color: rgba(255, 255, 255, 0.6);
    display: flex;
    align-items: center;
    justify-content: space-evenly;
  }
  .spin-buttons > div {
    cursor: pointer;
  }
  .spin-buttons > div,
  .spin-buttons > div::before {
    font-size: 30px;
    color: rgba(51, 51, 51, 1);
  }
  #info {
    position: absolute;
    right: 0;
    top: -40px;
    max-width: 150px;
    width: 100%;
    min-height: 40px;
    background-color: rgba(244, 244, 244, 1);
    color: rgba(51, 51, 51, 1);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: "Source Sans Pro", sans-serif;
    font-size: 16px;
  }
  .sirv-container {
    max-width: 100% !important;
  }
  .sirv-controls {
    justify-content: space-evenly !important;
  }
  .spin-container:not(.spin-hide) .smv-button-fullscreen-open {
    display: none;
  }
</style>

The button icons are PNG images with transparency, from the Flaticon icon set. Size and style is fully customizable. Choose between many popular icons sets or design your own, for a truly custom experience.

Each button uses a script to call the Sirv Spin API via a JavaScript callback. It’s easy to configure – click to view the code for each demo, to see how it was created.

Buttons on the spin

Buttons can be overlaid over the spin images, instead of below:

<div class="spin-container sirv-container overlay" style="min-height: 226px">
  <div class="ihint spin-2"></div>

  <div class="viewer" style="margin-bottom: 0">
    <div
      id="smv"
      class="Sirv"
      data-options="fullscreen.native:true;"
    >
      <div
        data-src="https://sirv.sirv.com/website/demos/green-car/green-car-2.spin?profile=green-car"
      ></div>
    </div>
    <div class="spin-buttons sirv-controls">
      <div id="buttonLeft" class="button flaticon-keyboard54"></div>
      <div
        id="buttonPlay"
        class="button flaticon-play106"
        style="display: none"
      ></div>
      <div
        id="buttonPause"
        class="button flaticon-pause44"
        style="display: inline"
      ></div>
      <div id="buttonRight" class="button flaticon-keyboard53"></div>
      <div id="buttonUp" class="button flaticon-expand39"></div>
      <div id="buttonDown" class="button flaticon-expand38"></div>
      <div id="buttonZoomIn" class="button flaticon-round57"></div>
      <div id="buttonZoomOut" class="button flaticon-round56"></div>
      <div id="buttonFullScreen" class="button flaticon-move26"></div>
      <div id="buttonInfo" class="button flaticon-round52"></div>
      <div id="info" style="display: none"></div>
    </div>
  </div>
</div>
<script src="https://scripts.sirv.com/sirvjs/v3/sirv.js"></script>
<link
  rel="stylesheet"
  href="https://demo.sirv.com/sirv-controls/sirv-controls.css"
/>
<script src="https://demo.sirv.com/sirv-controls/sirv-controls-v3.js"></script>
<script>
  const spinIndex = 0;
  const spinContainer = document.querySelector(".spin-container");
  const smv = spinContainer.querySelector(".smv");
  const buttonPlay = spinContainer.querySelector("#buttonPlay");
  const buttonPause = spinContainer.querySelector("#buttonPause");
  const buttonLeft = spinContainer.querySelector("#buttonLeft");
  const buttonRight = spinContainer.querySelector("#buttonRight");
  const buttonUp = spinContainer.querySelector("#buttonUp");
  const buttonDown = spinContainer.querySelector("#buttonDown");
  const buttonZoomIn = spinContainer.querySelector("#buttonZoomIn");
  const buttonZoomOut = spinContainer.querySelector("#buttonZoomOut");
  const buttonFullScreen = spinContainer.querySelector("#buttonFullScreen");
  const buttonInfo = spinContainer.querySelector("#buttonInfo");
  const infoFrame = spinContainer.querySelector("#info");

  let isPlay = true;
  const canPlay = () => {
    if (isPlay === false) {
      return;
    }
    buttonPause.click();
  };
  const playOrPause = () => {
    if (isPlay) {
      Sirv.getInstance("#smv").child(spinIndex).spin.pause();
      buttonPause.style.display = "none";
      buttonPlay.style.display = "inline";
      isPlay = false;
    } else {
      Sirv.getInstance("#smv").child(spinIndex).spin.play();
      buttonPause.style.display = "inline";
      buttonPlay.style.display = "none";
      isPlay = "true";
    }
  };
  buttonPlay.addEventListener("click", playOrPause);
  buttonPause.addEventListener("click", playOrPause);
  buttonLeft.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateX(-1);
  });
  buttonRight.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateX(1);
  });
  buttonUp.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateY(-1);
  });
  buttonDown.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.rotateY(1);
  });
  buttonZoomIn.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.zoomIn();
  });
  buttonZoomOut.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").child(spinIndex).spin.zoomOut();
  });
  buttonFullScreen.addEventListener("click", () => {
    canPlay();
    Sirv.getInstance("#smv").fullscreen();
  });
  buttonInfo.addEventListener("click", () => {
    const frame = Sirv.getInstance("#smv").child(spinIndex).spin.currentFrame();
    const content = `Row: ${frame.row}, Col: ${frame.column}`;
    infoFrame.textContent = content;
    infoFrame.style.display = "flex";
    setTimeout(() => {
      infoFrame.style.display = "none";
    }, 2000);
  });
</script>
<style>
  .smv-h .smv-arrow {
    position: relative;
    transition: opacity 0.2s ease;
    opacity: 0.000001;
  }
  .smv-h .smv-arrow::before,
  .smv-h .smv-arrow::after {
    display: block;
    content: "";
    position: absolute;
    background-color: transparent;
    border: 3px solid transparent;
    border-radius: 5px 5px 0 0;
    height: 22%;
    top: 50%;
    right: 20%;
    transform: translate(-50%, -99.2%) skewX(40deg);
    width: 4px;
    z-index: 1;
    box-sizing: content-box !important;
  }
  .smv-h .smv-arrow::before {
    border-bottom: none;
  }
  .smv-h .smv-arrow::after {
    border-top: none;
    transform: translate(-50%, -0.8%) skewX(-40deg);
    border-radius: 0 0 5px 5px;
  }
  .smv-arrow .smv-icon {
    -webkit-mask-repeat: none !important;
    mask-repeat: none !important;
    -webkit-mask-position: none !important;
    mask-position: none !important;
    -webkit-mask-size: none !important;
    -webkit-mask-image: none !important;
    background: transparent !important;
    z-index: 2;
    position: static !important;
  }
  .smv-arrow .smv-icon::before,
  .smv-arrow .smv-icon::after {
    display: block;
    content: "";
    position: absolute;
    background: #999;
    border-radius: 5px 5px 0 0;
    height: 22%;
    top: 50%;
    right: 20%;
    transform: translate(-50%, -99.2%) skewX(40deg);
    width: 5px;
    z-index: 2;
    margin: 0 4px;
  }
  .smv-arrow .smv-icon::before {
    border-bottom: none;
  }
  .smv-arrow .smv-icon::after {
    border-top: none;
    transform: translate(-50%, -0.8%) skewX(-40deg);
    border-radius: 0 0 5px 5px;
  }
  .smv-h .smv-arrow-prev .smv-icon {
    transform: none !important;
  }
  .smv-h .smv-arrow-prev.smv-arrow {
    transform: scaleX(-1) !important;
  }
  .smv-h .smv-arrow.smv-arrow-thumbnails {
    opacity: 1;
  }
  .smv-h .smv-arrow.smv-arrow-thumbnails::before,
  .smv-h .smv-arrow.smv-arrow-thumbnails::after {
    display: none;
  }
  .smv-h .smv-arrow.smv-arrow-thumbnails .smv-icon::before,
  .smv-h .smv-arrow.smv-arrow-thumbnails .smv-icon::after {
    right: 2px;
  }
  .smv-arrow .smv-icon {
    opacity: 1 !important;
  }
  .smv-slides-box:hover .smv-arrow {
    opacity: 0.4 !important;
  }
  .smv-slides-box:hover .smv-arrow:hover {
    opacity: 1 !important;
  }
  @media screen and (max-width: 768px) {
    .smv-h .smv-arrow {
      opacity: 1 !important;
    }
    .smv-slides-box:hover .smv-arrow {
      opacity: 1 !important;
    }
  }
  @import url(https://demo.sirv.com/sirv-controls/sirv-controls.css);

  .viewer {
    position: relative;
    margin-bottom: 80px;
  }
  .spin-buttons {
    position: relative;
    width: 100%;
    bottom: 0;
    min-height: 80px;
    z-index: 2;
    background-color: rgba(255, 255, 255, 0.6);
    display: flex;
    align-items: center;
    justify-content: space-evenly;
  }
  .spin-buttons > div {
    cursor: pointer;
  }
  .spin-buttons > div,
  .spin-buttons > div::before {
    font-size: 30px;
    color: rgba(51, 51, 51, 1);
  }
  #info {
    position: absolute;
    right: 0;
    top: -40px;
    max-width: 150px;
    width: 100%;
    min-height: 40px;
    background-color: rgba(244, 244, 244, 1);
    color: rgba(51, 51, 51, 1);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: "Source Sans Pro", sans-serif;
    font-size: 16px;
  }
  .sirv-container {
    max-width: 100% !important;
  }
  .spin-container:not(.spin-hide) .smv-button-fullscreen-open {
    display: none;
  }
</style>

Separate button/link

The API can be used to open spins in fullscreen via a link on your page.

<style>
  .spin-hide {
    height: 0;
  }

  .spin-hide .smv {
    height: 0 !important;
  }

  .btn {
    border-radius: 40px;
    border: 1px solid transparent;
    box-shadow: none;
    color: inherit;
    cursor: pointer;
    display: inline-block;
    font-family: inherit;
    font-size: 22px;
    letter-spacing: 1px;
    line-height: 36px;
    padding: 10px 40px;
    text-align: center;
    transition:
      background-color 0.3s ease,
      color 0.3s ease,
      border-color 0.3s ease,
      box-shadow 0.3s ease;
    font-weight: 600;
  }

  .btn--primary {
    background-color: #067be0;
    border-color: #067be0;
    color: #fff;
  }
  .btn--sm {
    font-size: 20px;
    line-height: 32px;
  }
  .btn--white {
    background-color: #fff;
    border-color: #067be0;
    color: #067be0;
  }

  .btn--white:hover {
    box-shadow: 0 0 0 2px #0562b3;
    color: #0562b3;
    background-color: #fff;
  }
</style>

<div class="spin-container spin-hide">
    <div class="Sirv spin-dark-theme" id="spin-3" data-src="https://demo.sirv.com/spins/test123/Duplo/duplo-zoo.spin" data-options="fullscreen.native:true;fullscreen.always:true"></div>
</div>
<button onclick="Sirv.getInstance('#spin-3').fullscreen();" class="btn btn--white btn--sm">Launch full-screen spin</button>
<script src="https://scripts.sirv.com/sirvjs/v3/sirv.js"></script>

Spin with a slider

The Sirv Spin API gives you creative freedom to design buttons and links to go anywhere on your page. Use it to provide rich user experiences, giving your visitors control over your animations in new ways.

This example spins the image via a slider. Drag the slider backwards and forwards:

<style>
  /* Left side of slider */
  .ui-widget-content {
      background: linear-gradient(to bottom,#fff 40%,#327bba 40%,#327bba 60%,#fff 60%);
  }
  /* Right side of slider */
  .ui-widget-header {
      background: linear-gradient(to bottom,#fff 40%,#999 40%,#666 60%,#fff 60%);
  }
  /* Slider handler */
  .ui-state-default {
      background: #999;
  }
  #rotator {
      margin: 10px 0;
  }
</style>
<script src="https://scripts.sirv.com/sirvjs/v3/sirv.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script>
     (function($){
           $(document).ready(function(){
                 frame = 0;
                 $("#rotator").slider({
                        range: "max",
                        min: 1,
                        max: 72, //Number of frames
                        value: 1,
                        slide: function( event, ui ) {
                              Sirv.getInstance('#spin-rotator').child(0).spin.jumpCols(frame);
                              frame = ui.value;
                        }
                 });
           });
     })(jQuery);
</script>

<div id="rotator"></div>
<div class="Sirv" id="spin-rotator" data-options="fullscreen.native: true;spin.hint.onStart.effect:none; spin.hint.onVisible.effect:none; spin.hint.onInactive.effect:none" data-src="https://demo.sirv.com/spins/ybemastudios/flashlight/flashlight-black.spin"></div>

Expert help

If you’re custom designing an interface and would like professional assistance, please contact our team with your requirements and one of our product representatives will assist you.

Find a 360 product photography expert near you

Don’t have 360 product photography? We’ve launched a Sirv Experts directory with the best 360 product photography experts near you.

← Previous Next →

Create your Sirv account now

Get started for free
Powered by Ukrainian determination and British ingenuity