Perepelenok,
показ всех картинок не гарантирован, можно задать время поиска свободных мест(строка 119), изменение фона это конец "поиска", можно таскать за чёрный фон.
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.dragscroll{
overflow: hidden;
position:relative;
width: 100vw;
height: 100vh;
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: -o-grab;
cursor: grab;
color: #fff;
}
.dragscroll img{
position:absolute;
width: 200px;
opacity: 0;
left: 50%;
top: 50%;
box-sizing: border-box;
display: block;
}
.dragscroll img.add{
transition: 1s;
opacity: 1;
}
.dragscroll.add{
background-color: #000000;
}
.dragscroll.add img.add{
border: 2px solid #FFFFFF;
border-radius: 4px;
}
#app{
max-width: 600px;
height: 400px;
box-shadow: 0 0 1em black;
overflow: hidden;
border-radius: 4px;
margin: 20px auto;
}
</style>
<script>
window.addEventListener("load", function() {
function random(length) {
return Math.trunc(Math.random() * length)
}
function dataAcquisition(parent, elem) {
var width = elem.offsetWidth + 6;
var height = elem.offsetHeight + 6;
var left = random(parent.clientWidth - width);
var top = random(parent.clientHeight - height);
return [left, top, width, height]
}
function collisionDetection(x1, y1, w1, h1, x2, y2, w2, h2) {
return x1 < x2 + w2 && y1 < y2 + h2 && x1 + w1 > x2 && y1 + h1 > y2
}
function reshuffle(parent, duration) {
cancelAnimationFrame(timer);
parent.classList.remove("add");
var imgs = [...parent.querySelectorAll("img")];
imgs.forEach(elem => elem.classList.remove("add"));
var beginTime = performance.now();
var arrayAdd = [];
function addPos(currentTime) {
var i = random(imgs.length);
var elem = imgs[i];
var {style} = elem;
var a = dataAcquisition(parent, elem);
var add = arrayAdd.every(b => !collisionDetection(...a, ...b))
if (add) {
var w = (parent.clientWidth - a[0])/2, h = (parent.clientHeight - a[1])/2, temp = a.slice(0);
for (var k = 0; k < 1; k+= .05) {
var c = a.slice(0);
c[1] += (h - c[1]) * k;
add = arrayAdd.every(b => !collisionDetection(...c, ...b));
if(add) temp = c.slice(0);
else break;
};
a = temp.slice(0);
for (var k = 0; k < 1; k+= .05) {
var c = a.slice(0);
c[0] += (w - c[0]) * k;
add = arrayAdd.every(b => !collisionDetection(...c, ...b));
if(add) temp = c.slice(0);
else break;
};
arrayAdd.push(temp);
imgs.splice(i, 1);
var [left, top] = temp;
left += "px";
top += "px";
Object.assign(style, {left, top});
elem.classList.add("add")
};
if (imgs.length && currentTime - beginTime < duration) timer = requestAnimationFrame(addPos);
else parent.classList.add("add");
}
timer = requestAnimationFrame(addPos)
}
var parent = document.querySelector(".dragscroll");
var duration = 10 * 1000;
reshuffle(parent, duration);
var timer;
window.addEventListener("resize", function() {
cancelAnimationFrame(timer);
clearTimeout(timer);
timer = window.setTimeout(() => reshuffle(parent, duration), 100)
});
var _startX, _startY, _scrollLeft, _scrollTop;
function pointerHandler(event)
{
const { screenX, screenY } = event;
if(event.type === "pointerdown") {
document.addEventListener("pointermove", pointerHandler);
document.addEventListener("pointerup", pointerHandler);
_startX = screenX;
_startY = screenY;
_scrollLeft = app.scrollLeft;
_scrollTop = app.scrollTop;
}
if(event.type === "pointerup") {
document.removeEventListener("pointermove", pointerHandler);
document.removeEventListener("pointerup", pointerHandler);
}
if(event.type === "pointermove") {
const dx = (screenX - _startX) ;
const dy = (screenY - _startY) ;
app.scrollLeft = _scrollLeft - dx;
app.scrollTop = _scrollTop - dy;
}
event.preventDefault();
}
var app = document.querySelector("#app");
app.addEventListener("pointerdown", pointerHandler);
});
</script>
</head>
<body>
<div id="app">
<div class="dragscroll">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=1" alt="">
<img src="https://loremflickr.com/320/400/kitty,kitten?random=2" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=3" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=4" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=5" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=6" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=7" alt="">
<img src="https://loremflickr.com/320/400/kitty,kitten?random=8" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=9" alt="">
<img src="https://loremflickr.com/320/500/kitty,kitten?random=10" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=11" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=12" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=13" alt="">
<img src="https://loremflickr.com/320/400/kitty,kitten?random=14" alt="">
<img src="https://loremflickr.com/320/100/kitty,kitten?random=15" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=16" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=17" alt="">
<img src="https://loremflickr.com/320/400/kitty,kitten?random=18" alt="">
<img src="https://loremflickr.com/320/200/kitty,kitten?random=19" alt="">
<img src="https://loremflickr.com/320/100/kitty,kitten?random=20" alt="">
</div>
</div>
</body>
</html>