July 5, 2018

Custom Viewer loading spinner

We all love Forge! Let's express it by showing a heart beating while our model loads. 

The Viewer spinner shows three dots and it's basically a div with class spinner and three divs inside it. We can replace this div content with anything and/or change the built-in class, but needs to be super-fast (so a GIF is probably not fast enough to load).

What about a pure CSS loader? Luckily there are several out there and, for this post, I have selected loading.io (CC0 license). First let's copy their heart beating CSS source code and make some basic adjustments, as shown below.

.lds-heart {
    /* added */
    margin: auto;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    visibility: visible;
    text-align: center;

    /* modified */
    display: inline-block;
    width: 64px;
    height: 64px;
    transform: rotate(45deg);
    transform-origin: 32px 32px;
.lds-heart div {
    top: 23px;
    left: 19px;
    position: absolute;
    width: 26px;
    height: 26px;
    background: #fff;
    animation: lds-heart 1.2s infinite cubic-bezier(0.215, 0.61, 0.355, 1);
.lds-heart div:after, .lds-heart div:before {
    content: " ";
    position: absolute;
    display: block;
    width: 26px;
    height: 26px;
    background: #fff;
.lds-heart div:before {
    left: -17px;
    border-radius: 50% 0 0 50%;
.lds-heart div:after {
    top: -17px;
    border-radius: 50% 50% 0 0;
@keyframes lds-heart {
    0% {
        transform: scale(0.95);
    5% {
        transform: scale(1.1);
    39% {
        transform: scale(0.85);
    45% {
        transform: scale(1);
    60% {
        transform: scale(0.95);
    100% {
        transform: scale(0.9);

Now we need to modify the built-in spinner div, let's use the following function. Note I'm using pure JavaScript DOM to get the element (by class name), replace its class and replace its content (the original contains 3 divs, we need 1 for this sample).

function replaceSpinner() {
  var spinners = document.getElementsByClassName("spinner");
  if (spinners.length == 0) return;
  var spinner = spinners[0];
  spinner.innerHTML = '<div></div>';

Last, run this function right after you call .selectItem from the document. Assuming you have a code similar to Basic Application, it should look like:

viewerApp.selectItem(viewables[0].data, onItemLoadSuccess, onItemLoadFail); // this line is already there
replaceSpinner(); // this is our function


Related Posts