Stagger elements along an angle

Viewed 43

I'm trying to stagger a random number of elements along an angle using javascript (jQuery used for this question).

For example, this is the result I'm looking to achieve:

enter image description here

So we can have any number of boxes of which the height is random but shared across them all and the angle in which they are staggered is also random.

I've found a thread with what I think is the solution but I can figure out how to put it in practise: https://math.stackexchange.com/questions/143932/calculate-point-given-x-y-angle-and-distance

Below is what I currently have, note that the DOM and CSS is not restricted but values to need to be responsive.

( function( $ ) {
    'use strict';
  
  // Return random int from min -> max (inclusive).
  const rand = ( min, max ) => {
      min = Math.ceil( min );
      max = Math.floor( max );
      return Math.floor( Math.random() * ( max - min + 1 ) ) + min;
  };
  
  $( 'button' ).on( 'click', function( event ) {
    event.preventDefault();

    // Get container element.
    const $container = $( '.container' );
    
    // Remove any old boxes.
    $container.find( '.box' ).remove();
    
    // Generate line angle.
        const angle = rand( 22, 68 ); // degrees
    
        // Generate a random number of boxes to display.
    const boxCount = rand( 2, 4 );
    
    // Generate a random box height percentage.
    const boxHeight = rand( 30, 60 );
    
    // Add angle to container.
    $container.css( {
        '--angle': `${angle}deg`,
      '--height': `${boxHeight}%`
    } );

        // Create boxes.
    for ( let i = 0; i < boxCount; i++ ) {
    
        // Calculate offset x
        const x = Math.abs( ( boxHeight * ( i + 1 ) ) * Math.cos( angle * Math.PI ) );
    
      $( '<div>', {
        class: 'box',
        style: `margin-left: ${x}%`
      } ).appendTo( $container );
    }

  } ).trigger( 'click' );
  
  
  
} )( jQuery );
button {
  margin-bottom: 10px;
}

.container {
  position: relative;
}

.container .line {
  width: 200vw;
  height: 2px;
  background-color: red;
  transform-origin: 0% 50%;
  transform: rotate(var(--angle));
  position: absolute;
  top: 0;
  left: 0;
}

.container .box {
  width: 50%;
  background-color: darkblue;
}

.container .box:nth-child(odd) {
  background-color: darkgreen;
}

.container .box::before {
  content: '';
  display: block;
  padding-bottom: var(--height);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Randomise</button>
<div class="container">
  <div class="line"></div>
</div>

1 Answers

Seems you want to find X-offset of point, which has some Y-coordinate Y_offset - corner of rectangle.

Here Y_offset is cumulative height of rectangles before the current one (like your boxHeight * ( i + 1 ) for case of equal heights), angle is desired angle relative to vertical axis.

X_Offset = Y_Offset * Math.tan( angle * Math.PI / 180 ));
Related