Search code examples
jquery-uidrag-and-dropz-index

Drag and drop, inheriting css property, and creating a clone helper


I've tried to make a cube game and have a couple of issues. I can't seem to make the blocks in front cover up the ones behind. Is there a way I can inherit a z-index css property from the object the cube is dropped on?

The other problem is that I can't make the helper: clone, function to work in my situation. The clone doesn't snap to the grid and just returns to it's position.

css:

/*gameResources*/

.drop_zone {
  height: 350px;
  width: 650px;
  background-image: url("/wordpress/wp-content/themes/tadek/img/one_game.svg");
  margin: 0 auto;
  position: relative;
}

.drop_zone * {
  height: 55px;
  width: 108px;
  background-color: red;
  position: absolute;
  transform: translate(-50%, -50%);
}

.drop_block_1 {
  top:  50px;
  left: 325px;
}

.drop_block_2 {
  top: 90px;
  left: 255px;
}

.drop_block_3 {
  top: 90px;
  left: 395px;
}

.drop_block_4 {
  top: 130px;
  left: 185px;
}

.drop_block_5 {
  top: 130px;
  left: 325px;
}

.drop_block_6 {
  top: 130px;
  left: 465px;
}

.drop_block_7 {
  top: 175px;
  left: 115px;
}

.drop_block_8 {
  top: 175px;
  left: 255px;
}

.drop_block_9 {
  top: 175px;
  left: 395px;
}

.drop_block_10 {
  top: 175px;
  left: 535px;
}

.drop_block_11 {
  top: 215px;
  left: 185px;
}

.drop_block_12 {
  top: 215px;
  left: 325px;
}

.drop_block_13 {
  top: 215px;
  left: 465px;
}

.drop_block_14 {
  top: 255px;
  left: 255px;
}

.drop_block_15 {
  top: 255px;
  left: 395px;
}

.drop_block_16 {
  top: 295px;
  left: 325px;
}


#gameFull {
  margin: 0 auto;
    width: 650px;
  padding: 10px 0 0 0;
}

.gameRow1 {
  text-align: center;
  margin: 50px;
}

.gameRow2 {
    text-align: center;
  margin: 50px;
}
.gameRow3 {
    text-align: center;
  margin:50px;
}

.gameCell {
  display: inline-block;
  width: 146px;
  height: 170px;
  margin: 0 -0.15%;
}

 .singleCube {
   cursor: move;
   cursor: grab;
   height: 170px;
   width: 146px;
 }

 .cubic_one_game {
   display: flex;
   flex-direction: row;
   flex-wrap: wrap;
   justify-content: space-around;
   align-items: center;
   max-width: 800px;
   margin: 0 auto;
   text-align: center;
   font-size: 14pt;
   letter-spacing: 2pt;
 }

javascript, jQueryUI, javasript and html:

<script type="text/javascript">

$( init0 );

function init0() {
  $( ".makeMeDroppable1" ).droppable({
    accept: "#makeMeDraggable1, #makeMeDraggable2, #makeMeDraggable3",
    drop: function(event, ui) {
       var $this = $(this);
       ui.draggable.position({
         my: "center",
         at: "center",
         of: $this,
         using: function(pos) {
           $(this).animate(pos, 200, "linear");
         }
       });
     }
  });

}


$( init1 );

function init1() {
  $('#makeMeDraggable1').draggable( {
    containment: '#gameFull',
    cursor: 'move',
    revert: "invalid",
    appendTo: ".makeMeDroppable1"
  } );


}

$( init2 );

function init2() {
  $('#makeMeDraggable2').draggable( {
    containment: '#gameFull',
    cursor: 'move',
    revert: "invalid",
    appendTo: ".makeMeDroppable1"
  } );
}

$( init3 );

function init3() {
  $('#makeMeDraggable3').draggable( {
    containment: '#gameFull',
    cursor: 'move',
    revert: "invalid",
    appendTo: ".makeMeDroppable1"
  } );
}

</script>
<div id="gameFull">
<div class="drop_zone">
  <div class="drop_block_1 makeMeDroppable1"></div>
  <div class="drop_block_2 makeMeDroppable1"></div><div class="drop_block_3 makeMeDroppable1"></div>
  <div class="drop_block_4 makeMeDroppable1"></div><div class="drop_block_5 makeMeDroppable1"></div><div class="drop_block_6 makeMeDroppable1"></div>
  <div class="drop_block_7 makeMeDroppable1"></div><div class="drop_block_8 makeMeDroppable1"></div><div class="drop_block_9 makeMeDroppable1"></div><div class="drop_block_10 makeMeDroppable1"></div>
  <div class="drop_block_11 makeMeDroppable1"></div><div class="drop_block_12 makeMeDroppable1"></div><div class="drop_block_13 makeMeDroppable1"></div>
  <div class="drop_block_14 makeMeDroppable1"></div><div class="drop_block_15 makeMeDroppable1"></div>
  <div class="drop_block_16 makeMeDroppable1"></div>

</div>

  <div class="cubic_one_game">
    <div>
      <img id="makeMeDraggable1" class="singleCube" src="../wordpress/wp-content/themes/tadek/img/cube_one_game-01.svg">
      <p>moduł kuchenny</p>
    </div>
    <div>
      <img id="makeMeDraggable2" class="singleCube" src="../wordpress/wp-content/themes/tadek/img/cube_one_game-02.svg">
      <p>moduł sypialniany</p>
    </div>
    <div>
      <img id="makeMeDraggable3" class="singleCube" src="../wordpress/wp-content/themes/tadek/img/cube_one_game-03.svg">
      <p>moduł łazienkowy</p>
    </div>
  </div>
</div>

game example:

http://cubichouse.eu/game/


Solution

  • For this, I would first advise separating your class and id attributes. This will make things more explicit in CSS and make your code easier to assign.

    Here is what I suggest:

    HTML

    <div id="gameFull">
      <div class="drop_zone">
        <div class="drop_block" id="block_1" data-row="1"></div>
        <div class="drop_block" id="block_2" data-row="2"></div>
        <div class="drop_block" id="block_3" data-row="2"></div>
        <div class="drop_block" id="block_4" data-row="3"></div>
        <div class="drop_block" id="block_5" data-row="3"></div>
        <div class="drop_block" id="block_6" data-row="3"></div>
        <div class="drop_block" id="block_7" data-row="4"></div>
        <div class="drop_block" id="block_8" data-row="4"></div>
        <div class="drop_block" id="block_9" data-row="4"></div>
        <div class="drop_block" id="block_10" data-row="4"></div>
        <div class="drop_block" id="block_11" data-row="5"></div>
        <div class="drop_block" id="block_12" data-row="5"></div>
        <div class="drop_block" id="block_13" data-row="5"></div>
        <div class="drop_block" id="block_14" data-row="6"></div>
        <div class="drop_block" id="block_15" data-row="6"></div>
        <div class="drop_block" id="block_16" data-row="7"></div>
      </div>
      <div class="cubic_one_game">
        <div>
          <img id="cube_1" class="singleCube" src="http://cubichouse.eu/wp-content/themes/cubic/img/cube_one_game-01.svg">
          <p>moduł kuchenny</p>
        </div>
        <div>
          <img id="cube_2" class="singleCube" src="http://cubichouse.eu/wp-content/themes/cubic/img/cube_one_game-02.svg">
          <p>moduł sypialniany</p>
        </div>
        <div>
          <img id="cube_3" class="singleCube" src="http://cubichouse.eu/wp-content/themes/cubic/img/cube_one_game-03.svg">
          <p>moduł łazienkowy</p>
        </div>
      </div>
    </div>
    

    CSS

    /*gameResources*/
    
    .drop_zone {
      height: 350px;
      width: 650px;
      background-image: url("http://cubichouse.eu/wp-content/themes/cubic/img/one_game.svg");
      margin: 0 auto;
      position: relative;
    }
    
    .drop_zone .drop_block {
      height: 55px;
      width: 108px;
      // background-color: red;
      position: absolute;
      transform: translate(-50%, -50%);
      z-index: 999;
    }
    
    #block_1 {
      top: 50px;
      left: 325px;
    }
    
    #block_2 {
      top: 90px;
      left: 255px;
    }
    
    #block_3 {
      top: 90px;
      left: 395px;
    }
    
    #block_4 {
      top: 130px;
      left: 185px;
    }
    
    #block_5 {
      top: 130px;
      left: 325px;
    }
    
    #block_6 {
      top: 130px;
      left: 465px;
    }
    
    #block_7 {
      top: 175px;
      left: 115px;
    }
    
    #block_8 {
      top: 175px;
      left: 255px;
    }
    
    #block_9 {
      top: 175px;
      left: 395px;
    }
    
    #block_10 {
      top: 175px;
      left: 535px;
    }
    
    #block_11 {
      top: 215px;
      left: 185px;
    }
    
    #block_12 {
      top: 215px;
      left: 325px;
    }
    
    #block_13 {
      top: 215px;
      left: 465px;
    }
    
    #block_14 {
      top: 255px;
      left: 255px;
    }
    
    #block_15 {
      top: 255px;
      left: 395px;
    }
    
    #block_16 {
      top: 295px;
      left: 325px;
    }
    
    #gameFull {
      margin: 0 auto;
      width: 650px;
      padding: 10px 0 0 0;
    }
    
    .gameRow1 {
      text-align: center;
      margin: 50px;
    }
    
    .gameRow2 {
      text-align: center;
      margin: 50px;
    }
    
    .gameRow3 {
      text-align: center;
      margin: 50px;
    }
    
    .gameCell {
      display: inline-block;
      width: 146px;
      height: 170px;
      margin: 0 -0.15%;
    }
    
    .singleCube {
      cursor: move;
      cursor: grab;
      height: 170px;
      width: 146px;
      z-index: 1000;
    }
    
    .cubic_one_game {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      justify-content: space-around;
      align-items: center;
      max-width: 800px;
      margin: 0 auto;
      text-align: center;
      font-size: 14pt;
      letter-spacing: 2pt;
    }
    
    .cubic_one_game img {
      height: 346px;
    }
    

    JavaScript

    $(function() {
      $(".drop_block").droppable({
        accept: ".singleCube",
        drop: function(e, ui) {
          var $this = $(this);
          ui.draggable.position({
            my: "center",
            at: "center",
            of: $this,
            using: function(pos) {
              $(this).animate(pos, 200, "linear");
            }
          });
          ui.draggable.css({
            "z-index": 1000 + $(this).data("row")
          });
        }
      });
    
      $('.singleCube').draggable({
        containment: '#gameFull',
        cursor: 'move',
        revert: "invalid"
      });
    });
    

    It may seem like a bit of work at first, yet it's a really helpful practice for some cases. Now we can easily manage many items or individual items as needed.

    For the perspective effect, the element that appears closest to the user should have the highest z-index. I added data-row attribute to each drop_box for easier management. When an item is dropped, it is then assigned a new z-index based on it's row. This ensures the proper perspective.

    You may want to consider when dragging an item, to force it's z-index to an even higher value so that it will appear above the other elements. Moving an item from a "back" row forward, has the effect of passing behind "closer" elements. Simple to do in CSS:

    .singleCube.ui-draggable-dragging {
      z-index: 2000;
    }
    

    Working Example: https://jsfiddle.net/Twisty/4nj4fqkk/3/

    Hope that helps.