Home > database >  css 3d transform rotate (x y) using mouse drag
css 3d transform rotate (x y) using mouse drag

Time:11-24

i was recently diving into the world of css transform and wanted to rotate a div (x and y axis), i was able to do it with 2 sliders with 0 to 360 degree range but now looking forward to do it with dragging the mouse, i have made a very sloppy effort on that looking for suggestion to fix it:

jsfiddle link to test

"use strict";

let elContainer = $('#container');
let elBox = $('#box');

$(document).ready(function() {
  $('.slider-rotate').on('input', function() {
    sliderRotate();
  });

  elContainer.mousedown(function(e) {
    initDragRotate(e);
  });

  elContainer.mousemove(function(e) {
    dragRotate(e);
  });

  elContainer.mouseup(function(e) {
    endDragRotate();
  });

});

let dragging = false;
let delta = {};

function initDragRotate(e) {
  dragging = true;
  delta = {
    x: e.pageX,
    y: e.pageY,
  };
}

function dragRotate(e) {
  if (!dragging) {
    return;
  }

  delta.x = e.pageX - delta.x;
  delta.y = e.pageY - delta.y;

  let rotateParam = '';
  rotateParam  = ' rotate'   'Y'   '('   delta.x   'deg)';
  rotateParam  = ' rotate'   'X'   '('   delta.y   'deg)';
  elBox.css('transform', rotateParam);
}

function endDragRotate() {
  if (!dragging) {
    return;
  }

  dragging = false;
}


function sliderRotate() {
  let rotateParam = '';
  $('.slider-rotate').each(function() {
    rotateParam  = ' '   getRotateParamString($(this));
  });
  elBox.css('transform', rotateParam);
}

function getRotateParamString(elClass) {
  let val = elClass.val();
  let rotateType = elClass.data('rotateType');
  let rotateParam = 'rotate'   rotateType   '('   val   'deg)';

  return rotateParam;
}
#container {
  background: #ccc;
  padding: 10vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

#box {
  width: 30vh;
  height: 30vh;
  border: 5px solid #000;
  position: relative;
  transform-style: preserve-3d;
}

#box>div {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
  <div id="box">
    <div style="background: #f00;"></div>
    <div style="background: #0f0;"></div>
  </div>
</div>

<div id="control">
  <br>
  <label>
    x
    <input type="range" class="slider-rotate" data-rotate-type="X" min="0" max="360" value="0">
  </label>
  <br>
  <label>
    y
    <input type="range" class="slider-rotate" data-rotate-type="Y" min="0" max="360" value="0">
  </label>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

also, there's 2 div on top and bottom (green and red) with transform-style preserve-3d property, hoping that it's show the other color when flipped but no luck! please suggest, thanks!

CodePudding user response:

The calulation for how much to rotate is a little odd.

I believe what you need is to have the amount of rotation dependent on the amount the mouse is placed across and down the screen. To make this proportional to the screen size you need to divide it by the screen size and then multiply it by 360 to get the full range from pageX/Y being 0 to being at the right/bottom of the screen.

"use strict";

let elContainer = $('#container');
let elBox = $('#box');

$(document).ready(function() {
  $('.slider-rotate').on('input', function() {
    sliderRotate();
  });

  elContainer.mousedown(function(e) {
    initDragRotate(e);
  });

  elContainer.mousemove(function(e) {
    dragRotate(e);
  });

  elContainer.mouseup(function(e) {
    endDragRotate();
  });

});

let dragging = false;
let delta = {};

function initDragRotate(e) {
  dragging = true;
  delta = {
    x: e.pageX,
    y: e.pageY,
  };
}

function dragRotate(e) {
  if (!dragging) {
    return;
  }
  // THIS IS THE CALCULATION THAT HAS CHANGED
  delta.x = e.pageX / window.innerWidth * 360; //- delta.x;
  delta.y = e.pageY / window.innerHeight * 360; // - delta.y;

  let rotateParam = '';
  rotateParam  = ' rotate'   'Y'   '('   delta.x   'deg)';
  rotateParam  = ' rotate'   'X'   '('   delta.y   'deg)';
  elBox.css('transform', rotateParam);
}

function endDragRotate() {
  if (!dragging) {
    return;
  }

  dragging = false;
}


function sliderRotate() {
  let rotateParam = '';
  $('.slider-rotate').each(function() {
    rotateParam  = ' '   getRotateParamString($(this));
  });
  elBox.css('transform', rotateParam);
}

function getRotateParamString(elClass) {
  let val = elClass.val();
  let rotateType = elClass.data('rotateType');
  let rotateParam = 'rotate'   rotateType   '('   val   'deg)';

  return rotateParam;
}
#container {
  background: #ccc;
  padding: 10vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

#box {
  width: 30vh;
  height: 30vh;
  border: 5px solid #000;
  position: relative;
  transform-style: preserve-3d;
}

#box>div {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
  <div id="box">
    <div style="background: #f00;"></div>
    <div style="background: #0f0;"></div>
  </div>
</div>

<div id="control">
  <br>
  <label>
    x
    <input type="range" class="slider-rotate" data-rotate-type="X" min="0" max="360" value="0">
  </label>
  <br>
  <label>
    y
    <input type="range" class="slider-rotate" data-rotate-type="Y" min="0" max="360" value="0">
  </label>
</div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related