Умная адаптация под разрешение экрана на fileboard.ru
Многие знают про мой проект — fileboard.ru. Рассказывать про него не буду. Просто перейдите, зарегистрируйтесь, попробуйте.
Так вот, существовала проблема, до которой долго не доходили руки. Когда пользователь группирует файлы в одном разрешении, а потом открывает, например, на телефоне, в намного меньшем разрешении — все слепляется в кучу. Появляется эта проблема из-за того, что координаты файлов на экране не привязаны к разрешению, а имеют относительные координаты по осям от 0 до 1. Масштабировать текст и превьюшки — плохая идея, т.к. не хочется ограничивать пользователей 24″ мониторов огромными значками в угоду сохранения читаемости на мобильных.
Пример (1366×768):
превращается в (800х600):
нужно было разработать систему, которая бы сама решала такие конфликты и потихоньку двигала файлы (если это возможно), да так, чтоб пользователя не покидало ощущение того, что все так, как он и расположил раньше.
В результате была разработана отдельная от ООП структуры клиентского приложения функция, отвечающая за onload и onresize масштабирование.
В основу была положена идея: поскольку все файлы симметричны, то можно рассматривать 4 случая перекрытия файлами друг друга.
Назовем красный файл — ei, зеленый — ej.
Первый случай — левый верхний угол ej расположен внутри ei. Растаскивать нужно либо по вертикали либо по горизонтали, в зависимости от того что меньше.
Второй случай — правый верхний угол ej расположен внутри ei. Растаскивать нужно либо по вертикали либо по горизонтали, в зависимости от того что меньше.
Третий случай: верхняя сторона ej полностью перекрывает нижнюю ei. Растаскивать нужно по вертикали, ei вверх, ej вниз.
Четвертый случай: левая сторона ej полностью перекрывает праву ei. Растаскивать нужно по горизонтали, ei влево, ej вправо.
После анализа всех возможных вариантов была написана функция:
function compose(){
var elems = new Array;
$(".template-download").each(function( i ){
elems[i] = {'x': parseInt( $(this).css('left') ),
'y': parseInt( $(this).css('top') ),
'width': $(this).width(),
'height': $(this).height(), };
});
var container = $('#files-container');
var minX = parseInt(container.css('left'));
var minY = parseInt(container.css('top'));
var maxX = $(window).width();
var maxY = $(window).height();
for( var k = 0; k < 3; k++ ){
var noConflicts = 1;
for( var i = 0; i < elems.length; i++ ){
var ei = elems[i];
if( ei.x < ( minX ) ) ei.x = minX;
if( ei.y < ( minY ) ) ei.y = minY;
if( ei.x > ( maxX - ei.width ) ) ei.x = maxX - ei.width;
if( ei.y > ( maxY - ei.height ) ) ei.y = maxY - ei.height;
for( var j = 0; j < elems.length; j++ ){
if( i == j ) continue;
var ej = elems[j];
if( ei.x < ej.x && (ei.x + ei.width) > ej.x && ei.y < ej.y && (ei.y + ei.height) > ej.y ){ //если левый верхний угол ej лежит внутри
var delta_x = ( ei.x + ei.width ) - ej.x;
var delta_y = ( ei.y + ei.height ) - ej.y;
if( delta_x < delta_y ){
ei.x -= delta_x / 2;
ej.x += delta_x / 2;
} else {
ei.y -= delta_y / 2;
ej.y += delta_y / 2;
}
noConflicts = 0;
}
else if( ei.x < ( ej.x + ej.width ) && (ei.x + ei.width) > ( ej.x + ej.width) && ei.y < ej.y && (ei.y + ei.height) > ej.y ){ //если правый верхний угол ej лежит внутри
var delta_x = (ej.x + ej.width) - ei.x;
var delta_y = ( ei.y + ei.height ) - ej.y;
if( delta_x < delta_y ){
ei.x += delta_x / 2;
ej.x -= delta_x / 2;
} else {
ei.y -= delta_y / 2;
ej.y += delta_y / 2;
}
noConflicts = 0;
} else if( ( ( ei.x < ej.x && ( ei.x + ei.width ) > ( ej.x + ej.width ) ) || ( ei.x > ej.x && ( ei.x + ei.width ) < ( ej.x + ej.width ) ) ) && ei.y < ej.y && ( ei.y + ei.height ) > ej.y ){ //если ej верхней стороной перекрывает ei или ei нижней стороной перекрывает ej
var delta_y = ( ei.y + ei.height ) - ej.y;
ei.y -= delta_y / 2;
ej.y += delta_y / 2;
noConflicts = 0;
} else if( ( ( ei.y < ej.y && ( ei.y + ei.height ) > ( ej.y + ej.height ) ) || ( ei.y > ej.y && ( ei.y + ei.height ) < ( ej.y + ej.height ) ) ) && ei.x < ej.x && ( ei.x + ei.width ) > ej.x ){ //если ej левой стороной перекрывает ei или ei правой стороной перекрывает ej
var delta_x = ( ei.x + ei.width ) - ej.x;
ei.x -= delta_x / 2;
ej.x += delta_x / 2;
noConflicts = 0;
}
}
if( ei.x < ( minX ) ) ei.x = minX;
if( ei.y < ( minY ) ) ei.y = minY;
if( ei.x > ( maxX - ei.width ) ) ei.x = maxX - ei.width;
if( ei.y > ( maxY - ei.height ) ) ei.y = maxY - ei.height;
}
if( noConflicts )
break;
}
$(".template-download").each(function( i ){
$(this).css('left', elems[i].x );
$(this).css('top', elems[i].y );
});
}
После ряда доработок, добавления ограничений, была получена функциональность, полностью удовлетворяющая поставленной задаче. С результатом вы всегда можете ознакомиться на fileboard.ru создав аккаунт и накачав файлов:) Так же хороший пример — мой аккаунт: nwr.fileboard.ru - переходим и ресайзим окошко браузера.




