使用jQuery的平铺式窗口
- categories
- >
- others
使用 HTML、CSS 和 jQuery UI 构建一个简单的类似 i3wm 的窗口样式
支持三种布局:浮动、平铺和堆叠
首先定义一组按钮和容器,通过点击按钮切换布局
<div>
<button onclick="setLayout('tile')">Tile</button>
<button onclick="setLayout('stack')">Stack</button>
<button onclick="setLayout('floating')">Floating</button>
</div>
<div id="layout">
<div class="window" id="w-content">Tile Window 2</div>
<div class="window" id="w-tag">Tile Window 2</div>
<div class="window" id="w-archive">Tile Window 3</div>
</div>
然后设置整体样式
body {
overflow: hidden;
margin: 0;
padding: 0;
}
.window {
border: 1px solid #333;
background-color: #f9f9f9;
min-height: 100px;
cursor: move;
z-index: 1;
}
设置 tile 模式
CSS 样式
.layout-tile {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 10px;
height: 100vh;
width: 100vw;
position: relative;
}
.t-content {
grid-column: 1 / 2;
grid-row: 1 / 3;
}
.t-tag {
grid-column: 2 / 3;
grid-row: 1 / 2;
}
.t-archive {
grid-column: 2 / 3;
grid-row: 2 / 3;
}
js 代码
function swapWindows(windowA, windowB) {
// Swap the inner HTML of the two windows
const contentA = windowA.html();
windowA.html(windowB.html());
windowB.html(contentA);
}
$("#layout").addClass("layout-tile");
$("#w-content").addClass("t-content");
$("#w-tag").addClass("t-tag");
$("#w-archive").addClass("t-archive");
$(".layout-tile .window").on("mousedown", function () {
currentWindow = $(this);
$(".layout-tile").css("user-select", "none");
});
$(".layout-tile .window").on("mouseup", function (event) {
const mouseX = event.pageX;
const mouseY = event.pageY;
let targetWindow = null;
// Check if the mouse position is within the bounds of any window
$(".layout-tile .window").each(function () {
const targetPosition = $(this).offset();
const targetWidth = $(this).outerWidth();
const targetHeight = $(this).outerHeight();
if (
mouseX >= targetPosition.left &&
mouseX <= targetPosition.left + targetWidth &&
mouseY >= targetPosition.top &&
mouseY <= targetPosition.top + targetHeight
) {
targetWindow = $(this);
return false;
}
});
if (targetWindow && currentWindow && targetWindow[0] !== currentWindow[0]) {
swapWindows(currentWindow, targetWindow);
}
currentWindow = null;
$(".layout-tile .window").removeAttr("user-select");
});
代码解释
$(".layout-tile .window").on("mousedown", function () {
currentWindow = $(this);
$(".layout-tile").css("user-select", "none");
});
- 为
.layout-tile
类下的每个.window
元素绑定mousedown
事件。当用户按下鼠标按钮时,当前被按下的窗口被存储在currentWindow
变量中。 - 通过设置
user-select: none
,禁用文本选择,防止在拖动时选择文本
$(".layout-tile .window").on("mouseup", function (event) {
const mouseX = event.pageX;
const mouseY = event.pageY;
let targetWindow = null;
- 为每个
.window
绑定mouseup
事件。当用户释放鼠标按钮时,记录鼠标的 X 和 Y 坐标,并初始化targetWindow
变量为null
。
$(".layout-tile .window").each(function () {
const targetPosition = $(this).offset();
const targetWidth = $(this).outerWidth();
const targetHeight = $(this).outerHeight();
if (
mouseX >= targetPosition.left &&
mouseX <= targetPosition.left + targetWidth &&
mouseY >= targetPosition.top &&
mouseY <= targetPosition.top + targetHeight
) {
targetWindow = $(this);
return false;
}
});
- 遍历
.layout-tile
下的每个.window
元素,检查鼠标释放时的位置是否在任何窗口的边界内。 targetPosition
获取当前窗口的位置,targetWidth
和targetHeight
获取其宽度和高度。- 如果鼠标位置在某个窗口内,将该窗口存储在
targetWindow
中,并通过return false
提前结束循环。
if (targetWindow && currentWindow && targetWindow[0] !== currentWindow[0]) {
swapWindows(currentWindow, targetWindow);
}
- 如果
targetWindow
和currentWindow
都存在,并且它们不是同一个窗口(即用户释放鼠标时并没有在同一个窗口上),则调用swapWindows
函数,交换这两个窗口的内容。
currentWindow = null;
$(".layout-tile .window").removeAttr("user-select");
});
- 将
currentWindow
设置为null
,准备进行下一次操作。 - 移除
user-select
属性,恢复文本选择的能力。
设置 stack 模式
CSS 样式
.layout-stack {
position: relative;
height: 100%;
width: 100%;
}
.s-content {
top: 40px;
left: 40px;
height: 100vh;
width: 100%;
z-index: 3;
position: absolute;
}
.s-tag {
top: 20px;
left: 20px;
height: 100vh;
width: 100%;
z-index: 2;
position: absolute;
}
.s-archive {
top: 0px;
left: 0px;
height: 100vh;
width: 100%;
z-index: 1;
position: absolute;
}
js 代码
$("#layout").addClass("layout-stack");
$("#w-content").addClass("s-content");
$("#w-tag").addClass("s-tag");
$("#w-archive").addClass("s-archive");
$(".layout-stack .window")
.off("click")
.on("click", function () {
const currentZIndex = parseInt($(this).css("z-index"), 10);
const zIndex3Window = $(".window").filter(function () {
return parseInt($(this).css("z-index"), 10) === 3;
});
const clickedWindow = $(this);
swapWindows(zIndex3Window, clickedWindow);
});
代码解释
$("#layout").addClass("layout-stack");
- 作用:给
#layout
元素添加layout-stack
类,设置布局为 stack。
$("#w-content").addClass("s-content");
$("#w-tag").addClass("s-tag");
$("#w-archive").addClass("s-archive");
- 作用:分别为
#w-content
、#w-tag
和#w-archive
元素添加对应的样式类,以便在堆叠布局下定义它们的样式和位置。
$(".layout-stack .window")
.off("click")
.on("click", function () {
- 作用:为
.layout-stack
下的所有.window
元素绑定点击事件。 .off("click")
是用来移除之前绑定的点击事件,确保不会重复绑定。
const currentZIndex = parseInt($(this).css("z-index"), 10);
- 作用:获取当前被点击窗口的 z-index 值,存储在
currentZIndex
变量中。
const zIndex3Window = $(".window").filter(function () {
return parseInt($(this).css("z-index"), 10) === 3;
});
- 作用:查找所有窗口中 z-index 值为 3 的窗口,并将其存储在
zIndex3Window
变量中。因为 CSS 中设置 z-index 为 3 的窗口是最上面的窗口。
const clickedWindow = $(this);
- 作用:将当前被点击的窗口元素存储在
clickedWindow
变量中,方便后续操作。
swapWindows(zIndex3Window, clickedWindow);
- 作用:调用
swapWindows
函数,交换zIndex3Window
和clickedWindow
的内容。点击一个窗口时,它会与当前在最上层的窗口交换位置。
设置 floating 模式
CSS 样式
.layout-floating {
position: absolute;
height: 100%;
width: 100%;
}
.f-content {
width: 100%;
}
.f-tag {
width: 100%;
}
.f-archive {
width: 100%;
}
js 代码
$("#layout").addClass("layout-floating");
$("#w-content").addClass("f-content");
$("#w-tag").addClass("f-tag");
$("#w-archive").addClass("f-archive");
$("#w-content").addClass("ui-draggable ui-draggable-handle ui-resizable");
$("#w-tag").addClass("ui-draggable ui-draggable-handle ui-resizable");
$("#w-archive").addClass("ui-draggable ui-draggable-handle ui-resizable");
$(".layout-floating .window")
.draggable({
containment: "window",
start: function () {
$(".window").css("z-index", 1);
$(this).css("z-index", 2);
},
})
.resizable();
$(".layout-floating .window").on("click", function () {
$(".window").css("z-index", 1);
$(this).css("z-index", 2);
});
代码解释
$("#layout").addClass("layout-floating");
- 作用:给
#layout
元素添加layout-floating
类,设置布局为浮动模式。
$("#w-content").addClass("f-content");
$("#w-tag").addClass("f-tag");
$("#w-archive").addClass("f-archive");
- 作用:分别为
#w-content
、#w-tag
和#w-archive
元素添加各自的浮动类。这些类会定义它们在浮动布局下的样式。
$("#w-content").addClass("ui-draggable ui-draggable-handle ui-resizable");
$("#w-tag").addClass("ui-draggable ui-draggable-handle ui-resizable");
$("#w-archive").addClass("ui-draggable ui-draggable-handle ui-resizable");
- 作用:为每个窗口元素添加 jQuery UI 的拖动和调整大小的类。这样,窗口就可以通过鼠标拖动或调整大小。
$(".layout-floating .window").draggable({
containment: "window",
start: function () {
$(".window").css("z-index", 1);
$(this).css("z-index", 2);
},
});
- 作用:
- 使
.layout-floating
类下的所有.window
元素可拖动。 containment: "window"
:限制窗口只能在浏览器窗口内拖动。start
:当拖动开始时便将所有窗口的 z-index 设置为 1,将当前拖动的窗口的 z-index 设置为 2,以确保它在其他窗口上方。
- 使
$(".layout-floating .window").on("click", function () {
$(".window").css("z-index", 1);
$(this).css("z-index", 2);
});
- 作用:为每个窗口添加点击事件:
- 当窗口被点击时,将所有窗口的 z-index 设置为 1,确保它们在同一层级。
- 将当前点击的窗口的 z-index 设置为 2,使其处于最上层。
comment:
- Valine
- LiveRe
- ChangYan