user6732041
user6732041

Reputation:

Equally distributing elements around a div?

I'm making a seating chart app where users can choose how many chairs they want at a table (1 - 13 seats). The problem is that I can't find a way to equally distribute the seats dynamically. If a user picks 3 chairs, there should be 33.3% of space between them around the circle. 4 chairs means 25% of space and so on.

Code snippet is a quick mockup. On select change, the correct number of seats should appear and equidistant from each other.

.tableContain
{
  width: 300px;
  height: 300px;
  border: 3px dotted black;
  position: relative;
}
.table
{
  width: 200px;
  height: 200px;
  border-radius: 100%;
  border: 1px solid black;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.seat
{
  width: 30px;
  height: 30px;
  border-radius: 100%;
  border: 1px solid black;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}
<div class="tableContain">
  <div class="table"></div>
  <div id="seat1" class="seat"></div>
</div>
Number Of Seats<select>
   <option val=1>1</option>
<option val=1>2</option>
<option val=1>3</option>
<option val=1>4</option>
</select>
<br>
<br>

Upvotes: 0

Views: 98

Answers (2)

Kevin Jantzer
Kevin Jantzer

Reputation: 9451

CSS & HTML Divs

Here's a working example using CSS and HTML divs along with some JavaScript to do the updating on select change.

function renderSeats(num){
  
  var diff = 1 / num;
  var seats = '';
  
  for( i=0; i<num; i++){
    var rotate = (diff * 360) * i;
  	seats += '<div class="seat-wrap"\
                  style="transform:rotate('+rotate+'deg);">\
                <div class="seat"></div>\
              </div>'
  }
  
  document.querySelector('.seats').innerHTML = seats
}

document.querySelector('select').addEventListener('change', function(){
  renderSeats(this.value)
})

renderSeats(1)
.tableContain
{
  width: 300px;
  height: 300px;
  border: 3px dotted black;
  position: relative;
}
.table
{
  width: 200px;
  height: 200px;
  border-radius: 100%;
  border: 1px solid black;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.seat-wrap {
  height: 100%;
  width: 100%;
  position: absolute;
  pointer-events: none;
}

.seat
{
  width: 30px;
  height: 30px;
  border-radius: 100%;
  border: 1px solid black;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  pointer-events: all;
}
<div class="tableContain" data-n="2">
  <div class="table"></div>
  <div class="seats"></div>
</div>

Number Of Seats

<select>
  <option val=1>1</option>
  <option val=1>2</option>
  <option val=1>3</option>
  <option val=1>4</option>
</select>

Upvotes: 1

Giladd
Giladd

Reputation: 1389

Here's a solution using canvas. Basically we listen to change events on the select element and call a function that draws the visualization.
This function works by dividing the circle to equal segments and drawing a circle at the end of each segment.

const select = document.getElementById("seatsNum");
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext('2d');
const cW = canvas.width, cH = canvas.height;

function drawSeats(count) {
  ctx.clearRect(0, 0, cW, cH);
  const tableRad = cW*0.2;
  const chairRad = cW*0.05;
  
  ctx.strokeStyle = "#000";
  ctx.beginPath();
  ctx.arc(cW/2, cH/2, tableRad, 0, 2*Math.PI, false);
  ctx.stroke();
  
  ctx.fillStyle = "#ccc";
  const segment = 360 / count;
  for (let i = 0; i < count; i++) {
    const x = (tableRad + 2*chairRad) * Math.cos(i*segment*Math.PI/180);
    const y = (tableRad + 2*chairRad) * Math.sin(i*segment*Math.PI/180);
    ctx.beginPath();
    ctx.arc(cW/2 + x, cH/2 + y, chairRad, 0, 2*Math.PI, false);
    ctx.fill();
    ctx.stroke();    
  }
}

select.onchange = function(ev) {
  const val = select.value;
  drawSeats(val);  
}

drawSeats(1);
canvas {
  border: 3px dotted black;
  position: relative;
}
<div class="tableContain">
  <div class="table"></div>
  <div id="seat1" class="seat"></div>
</div>
<canvas id="canvas" width="300" height="300"></canvas>
<br/>
Number Of Seats
<select id="seatsNum">
  <option val="1">1</option>
  <option val="2">2</option>
  <option val="3">3</option>
  <option val="4">4</option>
  <option val="5">5</option>
  <option val="6">6</option>
  <option val="7">7</option>
  <option val="8">8</option>
  <option val="9">9</option>
  <option val="10">10</option>
  <option val="11">11</option>
</select>
<br>
<br>

Upvotes: 2

Related Questions