<div id="map">
<div id="tiles"></div>
<div id="loader" hidden>
<div class="lds-ring"><div></div><div></div><div></div><div></div></div>
</div>
</div>
#map {
width: 100%;
height: 100vh;
background: wihte;
overflow: hidden;
cursor: grab;
}
#map.moving { cursor: grabbing; }
#tiles {
position: relative;
background-image:
linear-gradient(45deg, gray 25%, transparent 25%, transparent 74%, gray 75%, gray),
linear-gradient(45deg, gray 25%, transparent 25%, transparent 74%, gray 75%, gray);
background-size: 20px 20px;
background-position: 0 0, 10px 10px;
}
.tile {
position: absolute;
pointer-events: none;
}
#loader {
position: absolute;
left: 50%;
top: 0;
z-index:200;
transform: translateX(-50%);
}
.lds-ring {
display: inline-block;
position: relative;
width: 64px;
height: 64px;
}
.lds-ring div {
box-sizing: border-box;
display: block;
position: absolute;
width: 51px;
height: 51px;
margin: 6px;
border: 6px solid #fff;
border-radius: 50%;
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
border-color: #fff transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes lds-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
const imageWidth = 200;
const imagesPath = 'http://lss.format23.ru/screens/';
const imagePrefix = 'Image_';
let map = document.getElementById('map');
let tiles = document.getElementById('tiles');
const data = [];
let maxX = 0;
let maxY = 0;
const delta = 1500;
const imgs = {};
function Loader() {
this.loader = document.getElementById('loader');
this.counter = 0;
this.show = () => {
this.counter++;
this.loader.hidden = false;
}
this.hide = () => {
this.counter--;
if (this.counter <= 0) this.loader.hidden = true;
}
}
const loader = new Loader();
const leadingZero = n => ('0000' + n).substr(-4);
const makeKey = imageDef => imageDef.src + '_' + imageDef.x + '_' + imageDef.y;
const isVisible = (item, mapCenter) => item.x > mapCenter.x - map.clientWidth / 2 - delta
&& item.x < mapCenter.x + map.clientWidth / 2 + delta
&& item.y > mapCenter.y - map.clientHeight / 2 - delta
&& item.y < mapCenter.y + map.clientHeight / 2 + delta;
const initData = () => {
let coordX = 0;
let coordY = 30300;
let gamecorX = 0;
let gamecorY = 1212;
for (let imageIndex = 0; imageIndex < 30400; imageIndex++) {
if (imageIndex % 301 == 0) {
coordX = 0 + 600 * (imageIndex / 301);
coordY = 30300 - 300 * (imageIndex / 301);
gamecorY = gamecorY - 12;
gamecorX = 0;
}
data.push({
src: leadingZero(imageIndex) + '.jpg',
x: coordX,
y: coordY,
gx: gamecorX,
gy: gamecorY,
});
coordX += 200;
coordY += 100;
gamecorX += 4;
maxX = Math.max(maxX, coordX);
maxY = Math.max(maxY, coordY);
}
}
const initView = () => {
tiles.style.width = maxX + 'px';
tiles.style.height = maxY + 'px';
map.scrollLeft = maxX / 2 - map.clientWidth / 2;
map.scrollTop = maxY / 2 - map.clientHeight / 2;
}
const updateViewport = () => {
let statCounter = 0;
const mapCenter = {
x: map.scrollLeft + map.clientWidth / 2,
y: map.scrollTop + map.clientHeight / 2,
}
let images = data.filter(item => isVisible(item, mapCenter));
images.forEach(image => {
let key = makeKey(image);
if (!imgs[key]) {
const img = document.createElement('img');
loader.show();
img.classList.add('tile');
img.style.left = image.x + 'px';
img.style.top = image.y + 'px';
img.onload = () => loader.hide();
img.src = imagesPath + imagePrefix + image.src;
imgs[key] = img;
tiles.appendChild(img);
statCounter++;
}
});
console.log('Добавлено ' + statCounter + ' элементов');
};
initData();
initView();
updateViewport();
const moveCoords = {x:0, y:0, l:0, t:0};
const moving = event => {
map.scrollLeft = moveCoords.l - (event.screenX - moveCoords.x);
map.scrollTop = moveCoords.t - (event.screenY - moveCoords.y);
};
map.addEventListener('mousedown', event => {
map.classList.add('moving');
moveCoords.x = event.screenX;
moveCoords.y = event.screenY;
moveCoords.l = map.scrollLeft;
moveCoords.t = map.scrollTop;
document.addEventListener('mousemove', moving);
});
document.addEventListener('mouseup', event => {
document.removeEventListener('mousemove', moving);
map.classList.remove('moving');
updateViewport();
let statCounter = 0;
const mapCenter = {
x: map.scrollLeft + map.clientWidth / 2,
y: map.scrollTop + map.clientHeight / 2,
}
data
.filter(item => !isVisible(item, mapCenter))
.forEach(image => {
let key = makeKey(image);
if (imgs[key]) {
tiles.removeChild(imgs[key]);
imgs[key] = null;
statCounter++;
}
});
console.log('Удалено ' + statCounter + ' элементов');
});
let tmp;
window.addEventListener('resize', event => {
clearTimeout(tmp);
tmp = setTimeout(() => updateViewport(), 300);
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.