Reputation:
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
Reputation: 9451
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
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