0

I'm trying to understand how to add basic interactivity to specific elements. Here I'm hoping for the user to be able to press any arrow key and see the element rotate and translate accordingly. I'm not sure the difference between using the DOM vs Canvas for this, but being I know how to work with the DOM I chose that method here. My problem is the element isn't consistent in it's movements and I think its because I'm accidentally overwriting transform values with my functions.

Here is the snippet below. All arrow keys doing something besides the down key.

function rotate( e, n ) {  //get current rotation and add n to it
  var curTranslation = getTrans( e );
  
  e.style.transform = 
  'rotate( ' + n + 'deg ) translateY(' + curTranslation + 'px )';
}
function translate( e, n ) { //get current translation and add n to it
  var curRotation = getRot( e );  
  
  e.style.transform = 
  'rotate( ' + curRotation + 'deg ) translateY(' + n + 'px )';
}     
function checkKey( e ) { //fire when a key on the keyboard is pressed. 
  var d = document,
      triBx = d.getElementById( 'tri-bx' );
  
  if ( e.keyCode == '38' ) { //up
    countTrans = Math.abs( countTrans ) * -1.1;  
    translate( triBx, countTrans );
  }
  else if ( e.keyCode == '40' ) { //down
    body.innerHTML = 'down';
  }
  else if ( e.keyCode == '37' ) { //left
    countRot = Math.abs( countRot ) * -1.1;
    rotate( triBx, countRot );
  }
  else if ( e.keyCode == '39' ) { //right
    countRot = Math.abs( countRot ) * 1.1;
    rotate( triBx, countRot );
  }
}

function start() { //call first function
  var d = document,
      triBx = d.getElementById( 'tri-bx' );
  
  window.addEventListener( 'keydown', checkKey );
}

//prevent entire window from scrolling
window.addEventListener("keydown", function(e) { 
    // space and arrow keys
    if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
        e.preventDefault();
    }
}, false);
start();
html, 
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
}
.tri-bx {
  transform: rotate( 0 );
  transition: transform 1s;
}
.tri {
  width: 0; 
  height: 0; 
  border-left: 1rem solid transparent;
  border-right: 1rem solid transparent;
  border-bottom: 1rem solid black;
  transform: scaleX( 0.5 );
}
<div id="tri-bx" class="tri-bx">

  <div id="tri" class="tri"></div>

</div>

<p style="position:absolute; bottom: 0;">use arrow keys</p>

<script>
  var countRot = 1,   //keep track of how many times the keys are pressed for rotation
  countTrans = 1;     //Same for translation

  function getRot( e ) {  //get rotation angle of element
    var st = window.getComputedStyle( e, null ),
        tr = st.getPropertyValue( 'transform' ) || 'FAIL',
        values = tr.split( '(' )[ 1 ].split( ')' )[ 0 ].split( ',' ),
        a = values[ 0 ],
        b = values[ 1 ],
        c = values[ 2 ],
        d = values[ 3 ],
        scale = Math.sqrt( a * a + b * b ),
        sin = b / scale,
        angle = Math.round( Math.atan2( b, a ) * ( 180 / Math.PI ) );

    return angle;
  }
  
  function getTrans( e ) { //get translation value of element
  var st = window.getComputedStyle( e, null ),
      tr = st.getPropertyValue( 'transform' ) || 'FAIL',
      values = tr.split( '(' )[ 1 ].split( ')' )[ 0 ].split( ',' ),
      f = values[ 5 ];

  return f;
}
</script>

My question is why does the object skip around the screen and how can I avoid overwriting the transforms to get this working properly. Ideas?

Lynel Hudson
  • 2,335
  • 1
  • 18
  • 34

1 Answers1

0

You are using transform for something it was not intended to do. The element is being transformed always from it's original position. That's why after you translate it and then change its rotation, it rotates a bunch (that's probably not what you where expecting to happen). If you think about it, it rotates in degrees, so the further you take the triangle from the "middle", or where it started from, the more distance it'll move.

I suggest you either use canvas for this (there are great game libraries that makes it easier than you'd think). Remember that CSS was created for styling, not interaction.

Alon Dahari
  • 1,138
  • 1
  • 9
  • 27
  • Yeah so in my code I'm trying to only add to the previous transform values with my `curTranslation` and `curRotation` variables that call `getRot()` and `getTrans()` to avoid overwriting them. Something is wrong in my code because it seems to overwrite some values still. Thanks for your suggestion and this is mainly an exercise to learn about transforms and how they work before I move on to canvas. – Lynel Hudson Apr 29 '17 at 23:43
  • Your code seems to be fine, but trying to achieve something impossible. If you think about it, you can't turn the triangle on it's axis, when it's actually turning on the original position's axis! – Alon Dahari May 01 '17 at 16:14
  • Not impossible. I did it here: http://stackoverflow.com/questions/43723656/transforms-are-added-endlessly, but have an even bigger problem. – Lynel Hudson May 01 '17 at 18:05