JSFiddle - React, Tailwind, and code Playground
by kentaromiura
HTML
<div id=container>
</div>
CSS
#container{
position: relative;
width: 620px;
height: 720px;
outline:3px #ececec dashed;
padding:0 10px;
}
#container div {
margin:0 -10px;
}
JavaScript
function DateEvent(details, index){
this.start = details.start
this.end = details.end
this.index = index
this.maxCollisions = 0
}
DateEvent.prototype.notifyCollisions = function(collisions){
this.maxCollisions = Math.max(this.maxCollisions, collisions)
}
DateEvent.prototype.collides = function(min, max){
var result = false
//it can collide at the end.
if (this.end < max && this.end > min) result = true
//it can collide at the beginning.
if (this.start < max && this.start > min) result = true
//it can collide right in the middle.
return result;
}
DateEvent.prototype.lasercast = function(inputs){
// this will use a raycast-like approach, only that raycast stop on first obstacole, while this have to 'go through' everything, hence the name lasercast, also lasers are cool.
var collisions = 0, notifyLater = []
for (var i = this.index +1, max = inputs.length; i<max; i++){
var next = inputs[i]
if (next.collides(this.start, this.end)){
notifyLater.push(next) //can be optimized with indexOf
console.log(i, 'collides with me, ', this.index)
collisions ++;
}
}
var toNotify
while( toNotify = notifyLater.pop() ){
toNotify.notifyCollisions(collisions)
}
this.notifyCollisions(collisions)
}
var input = [ {start: 30, end: 150}, {start: 540, end: 600}, {start: 560, end: 620}, {start: 610, end: 670} ];
var res = input.map(function(details, index){ // copy so it doesn't modify the input.
return new DateEvent(details, index)
}).sort(function(a, b){ return a.start >= b.start });
var container = document.getElementById('container');
res.forEach(function(de, i){
de.lasercast(res)
var div = document.createElement('div')
div.innerHTML = i;
div.style.position = 'absolute'
div.style.backgroundColor = 'rgba(12,12,12,0.3)'
div.style.width = 100 / (de.maxCollisions + 1) + '%'
...