在drag&amp ;;上旋转javascript多维数据集滚动

时间:2017-10-30 14:55:17

标签: javascript jquery scroll 3d rotation

这是我的问题: 我一直在努力做这个CSS立方体打开滚动。我做到了!以下是它的工作原理:https://codepen.io/vaninoo/pen/BmyYQd

我很开心。但在与朋友测试之后,似乎他们中的许多人想要“拖动”立方体以使其旋转。所以我决定添加这个功能。这是我最接近的:https://codepen.io/vaninoo/pen/jaEZBx

立方体可以在拖动时旋转,拖动后我可以通过滚动旋转它。但是:

  1. 每当我滚动时,我都希望它转动,即使之前没有点击过。
  2. 当我移动它时,我无法弄清楚如何移除“跳跃”。它需要保持多维数据集在内存中的位置,但我非常努力,只是无法做到。
  3. 以下是我可以在笔上找到的代码(“我最接近”):

    // START OF UNSURE PART
    
    $('document').ready(function() {
    	var lastScrollTop = 0;
    	$(window).scroll(function trucenscroll(event) {
    	   var st = $(this).scrollTop();
    	   var sl = $(this).scrollLeft();
    	   if (st > lastScrollTop) {
    	       
    	       //Le cube tourne
    		    var p1,angle,i,tmp;
    			
    			p1	= {'x': sl - p0.x,	'y': st - p0.y }, 
    			angle	= {'x': -p1.y * unit,		'y': p1.x * unit};
    		  
    			for(i = 0; i < faces.length; i++) 
    			{
    				tmp = 'rotateX(' + angle.x + 'deg)' + ' rotateY(' + angle.y + 'deg)' + styles[i];
    				faces[i].style.transform = p + tmp;
    				faces[i].style['-webkit-transform'] = p + tmp;
    			}
    	   }
    	   else if(st == lastScrollTop) {
    	     //do nothing 
    	     //In IE this is an important condition because there seems to be some instances where the last scrollTop is equal to the new one
    	   }
    	   else {
    	   		var p1,angle,i,tmp;
    			p1	= {'x': sl - p0.x,	'y': st - p0.y }, 
    			angle	= {'x': -p1.y * unit,		'y': p1.x * unit};
    		  
    			for(i = 0; i < faces.length; i++) 
    			{
    				tmp = 'rotateX(' + angle.x + 'deg)' + ' rotateY(' + angle.y + 'deg)' + styles[i];
    				faces[i].style.transform = p + tmp;
    				faces[i].style['-webkit-transform'] = p + tmp;
    			}
    	   }
    	   lastScrollTop = st;
    	});
    });
    
    
    // END OF UNSURE PART
    
    
    
    
    
    
    
    
    init();		
    //===========================================================
    //			onMouseMove
    //===========================================================
    function onMouseMove(e) 
    {
    	var p1,angle,i,tmp;
    
    	if (! dragging) return;
    
    	p1	= {'x': e.clientX - p0.x,	'y': e.clientY - p0.y }, 
    	angle	= {'x': -p1.y * unit,		'y': p1.x * unit};
      
    	for(i = 0; i < faces.length; i++) 
    	{
    		tmp = 'rotateX(' + angle.x + 'deg)' + ' rotateY(' + angle.y + 'deg)' + styles[i];
    		faces[i].style.transform = p + tmp;
    		faces[i].style['-webkit-transform'] = p + tmp;
    	}
    }
    //===========================================================
    //			onMouseDown
    //===========================================================
    function onMouseDown(e)
    {
    	var element;
    
    	onMouseUp();	// disable if dragging
    
    	element = e.target;
    	//if (! element.classList.contains('face')) return false;
    
    	e.preventDefault();
    	window.p0	= { 'x': e.clientX, 'y': e.clientY };
    	dragging	= true;
    	return false;
    }
    //===========================================================
    //			onMouseUp
    //===========================================================
    function onMouseUp(e)
    {
    	var i,tmp,style;
    
    	if (! dragging) return;
    	dragging = false; 
    
    	for ( i = 0; i < faces.length; i++) 
    	{
    		style = faces[i].style;
    		tmp = style.transform || style['-webkit-transform'];
    		styles[i] = tmp.replace('perspective(32em) ', '');
    	}
      
    }
    //=====================================================================
    //			initializeCube
    //=====================================================================
    function initializeCube()
    {
    	var i,tmp;
    
    	for (i = 0; i < faces.length; i++)
    	{
    		if (i  < 4) tmp = 'rotateY(' + i*90 + 'deg)';
    		if (i >= 4) tmp = 'rotateX(' + Math.pow(-1, i) * 90 + 'deg)';
    		tmp += ' translateZ(' + side/2 + 'px)';
    	
    		faces[i].style.transform = p + tmp;
    		faces[i].style['-webkit-transform'] = p + tmp;
    		styles.push(tmp);
    	}
    }
    //=====================================================================
    //			init
    //=====================================================================
    function init()
    {
    	window.addEventListener('mousedown', onMouseDown, false);
    	window.addEventListener('mouseup',   onMouseUp,   false);
    	window.addEventListener('mousemove', onMouseMove, false);
    
    	window.faces 		= document.querySelectorAll('.face');
    	window.styles 		= new Array();
    	window.style 		= getComputedStyle(faces[0]);
    	window.factor 		= 3;
    	window.side 		= parseInt(style.width.split('px')[0], 10);
    	window.max_amount 	= factor * side; 
    	window.unit 		= 360 / max_amount;
    	window.dragging 	= false;
    	window.scrolling 	= false;
    	window.p 		= 'perspective(32em)';
    
    	initializeCube();
    }
    body {
    	position: relative;
    	height:5000px;
    }
    
    .cube, .cube * 
    {
      position: absolute;
      top: 25vh;
      left: 50%;
    }
      
    .cube 
    {
      user-select: none;
      cursor: move;
    }
    .cube div span
    {
    	position: relative;
    	top: 60px;
    	left: -5px;
    	font-size: 8em;
    }
    
    .face 
    {
    	box-sizing: border-box;
    	border: solid 1px;
    	margin: -8em;
    	width: 16em;
    	height: 16em;
    	box-shadow: inset 0 0 15px rgba(0,0,255,0.6);
    	text-align: center;
    	/** backface-visibility: hidden; /**/
    }
    .face:nth-child(1) { 
    	background: rgba(255,   0,   0, 0.2); 
    }
    .face:nth-child(2) { background: rgba(255, 255,   0, 0.2); }
    .face:nth-child(3) { background: rgba(  0, 255,   0, 0.2); }
    .face:nth-child(4) { background: rgba(  0, 255, 255, 0.2); }
    .face:nth-child(5) { background: rgba(  0,   0, 255, 0.2); }
    .face:nth-child(6) { background: rgba(255,   0, 255, 0.2); }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <body translate="no" onload="init()">
    <div class='cube' id="cubo">
      <div class='face'><span>1</span></div>
      <div class='face'><span>2</span></div>
      <div class='face'><span>3</span></div>
      <div class='face'><span>4</span></div>
      <div class='face'><span>5</span></div>
      <div class='face'><span>6</span></div>
    </div>
    </body>

1 个答案:

答案 0 :(得分:2)

我认为这应该是你想要的行为。您未能在代码中初始化p0变量,因此当您尝试立即滚动而不单击它会导致错误。此外,您看到的跳转是因为在p0函数中设置onMouseDown后,您从未将其设置回初始状态(我刚设置为{x:0, y:0}),因此滚动将基于您的鼠标设置的p0值开始。

详细介绍。在$(document).ready()中,我将p0变量的初始状态设置为window.p0={'x':0,'y':0}。然后我还重置了onMouseUp函数中的p0变量,以确保如果停止拖动并再次开始滚动,则会正确设置。

另外,我修改了滚动功能以包括存储立方体面的样式的状态。我相信,因为$(window).scroll函数没有存储它正在应用的样式状态,所以拖动基本上“丢失”了立方体的最后状态,这导致了你注意到的跳跃。请注意,此更改可能会导致一些过载,因为它会不断附加到以快速速率应用于立方体面的样式。

// START OF UNSURE PART

$('document').ready(function() {
  var lastScrollTop = 0;
  //Set the initial state of window.p0 so that scrolling works without clicking
  window.p0 = {
    'x': 0,
    'y': 0
  };
  $(window).scroll(function trucenscroll(event) {
    var st = $(this).scrollTop();
    var sl = $(this).scrollLeft();
    if (st > lastScrollTop) {

      //Le cube tourne
      var p1, angle, i, tmp;

      p1 = {
          'x': sl - p0.x,
          'y': st - p0.y
        },
        angle = {
          'x': -p1.y * unit,
          'y': p1.x * unit
        };
      for (i = 0; i < faces.length; i++) {
        tmp = 'rotateX(' + angle.x + 'deg)' + ' rotateY(' + angle.y + 'deg)' + styles[i];
        faces[i].style.transform = p + tmp;
        faces[i].style['-webkit-transform'] = p + tmp;
        //Save the state of the style of the cube faces. This ensures that if you switch to dragging, then there will be no jumps because all of the transforms will still be correctly applied.
        style = faces[i].style;
        var tmpStyle = style.transform || style['-webkit-transform'];
        styles[i] = tmpStyle.replace('perspective(32em) ', '');
      }
    } else if (st == lastScrollTop) {
      //do nothing 
      //In IE this is an important condition because there seems to be some instances where the last scrollTop is equal to the new one
    } else {
      var p1, angle, i, tmp;
      p1 = {
          'x': sl - p0.x,
          'y': st - p0.y
        },
        angle = {
          'x': -p1.y * unit,
          'y': p1.x * unit
        };

      for (i = 0; i < faces.length; i++) {
        tmp = 'rotateX(' + angle.x + 'deg)' + ' rotateY(' + angle.y + 'deg)' + styles[i];
        faces[i].style.transform = p + tmp;
        faces[i].style['-webkit-transform'] = p + tmp;
        //Save the state of the style of the cube faces. This ensures that if you switch to dragging, then there will be no jumps because all of the transforms will still be correctly applied.
        style = faces[i].style;
        var tmpStyle = style.transform || style['-webkit-transform'];
        styles[i] = tmpStyle.replace('perspective(32em) ', '');
      }
    }
    lastScrollTop = st;
  });
});


// END OF UNSURE PART








init();
//===========================================================
//			onMouseMove
//===========================================================
function onMouseMove(e) {
  var p1, angle, i, tmp;

  if (!dragging) return;

  p1 = {
      'x': e.clientX - p0.x,
      'y': e.clientY - p0.y
    },
    angle = {
      'x': -p1.y * unit,
      'y': p1.x * unit
    };
  for (i = 0; i < faces.length; i++) {
    tmp = 'rotateX(' + angle.x + 'deg)' + ' rotateY(' + angle.y + 'deg)' + styles[i];
    faces[i].style.transform = p + tmp;
    faces[i].style['-webkit-transform'] = p + tmp;
  }
}
//===========================================================
//			onMouseDown
//===========================================================
function onMouseDown(e) {
  var element;

  onMouseUp(); // disable if dragging

  element = e.target;
  //if (! element.classList.contains('face')) return false;

  e.preventDefault();
  window.p0 = {
    'x': e.clientX,
    'y': e.clientY
  };
  dragging = true;
  return false;
}
//===========================================================
//			onMouseUp
//===========================================================
function onMouseUp(e) {
  var i, tmp, style;

  if (!dragging) return;
  dragging = false;

  //Save the state of the style of the cube faces. This ensures that if you switch to dragging, then there will be no jumps because all of the transforms will still be correctly applied.
  for (i = 0; i < faces.length; i++) {
    style = faces[i].style;
    tmp = style.transform || style['-webkit-transform'];
    styles[i] = tmp.replace('perspective(32em) ', '');
  }
  //Reset the window.p0 variable back for scrolling to work
  window.p0 = {
    'x': 0,
    'y': 0
  };

}
//=====================================================================
//			initializeCube
//=====================================================================
function initializeCube() {
  var i, tmp;

  for (i = 0; i < faces.length; i++) {
    if (i < 4) tmp = 'rotateY(' + i * 90 + 'deg)';
    if (i >= 4) tmp = 'rotateX(' + Math.pow(-1, i) * 90 + 'deg)';
    tmp += ' translateZ(' + side / 2 + 'px)';

    faces[i].style.transform = p + tmp;
    faces[i].style['-webkit-transform'] = p + tmp;
    styles.push(tmp);
  }
}
//=====================================================================
//			init
//=====================================================================
function init() {
  window.addEventListener('mousedown', onMouseDown, false);
  window.addEventListener('mouseup', onMouseUp, false);
  window.addEventListener('mousemove', onMouseMove, false);

  window.faces = document.querySelectorAll('.face');
  window.styles = new Array();
  window.style = getComputedStyle(faces[0]);
  window.factor = 3;
  window.side = parseInt(style.width.split('px')[0], 10);
  window.max_amount = factor * side;
  window.unit = 360 / max_amount;
  window.dragging = false;
  window.scrolling = false;
  window.p = 'perspective(32em)';

  initializeCube();
}
body {
  position: relative;
  height: 5000px;
}

.cube,
.cube * {
  position: absolute;
  top: 25vh;
  left: 50%;
}

.cube {
  user-select: none;
  cursor: move;
}

.cube div span {
  position: relative;
  top: 60px;
  left: -5px;
  font-size: 8em;
}

.face {
  box-sizing: border-box;
  border: solid 1px;
  margin: -8em;
  width: 16em;
  height: 16em;
  box-shadow: inset 0 0 15px rgba(0, 0, 255, 0.6);
  text-align: center;
  /** backface-visibility: hidden; /**/
}

.face:nth-child(1) {
  background: rgba(255, 0, 0, 0.2);
}

.face:nth-child(2) {
  background: rgba(255, 255, 0, 0.2);
}

.face:nth-child(3) {
  background: rgba( 0, 255, 0, 0.2);
}

.face:nth-child(4) {
  background: rgba( 0, 255, 255, 0.2);
}

.face:nth-child(5) {
  background: rgba( 0, 0, 255, 0.2);
}

.face:nth-child(6) {
  background: rgba(255, 0, 255, 0.2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body translate="no" onload="init()">
  <div class='cube' id="cubo">
    <div class='face'><span>1</span></div>
    <div class='face'><span>2</span></div>
    <div class='face'><span>3</span></div>
    <div class='face'><span>4</span></div>
    <div class='face'><span>5</span></div>
    <div class='face'><span>6</span></div>
  </div>
</body>