Как сделать div с изменением размера сверху?
Я делаю небольшой сайт с окнами. Я успешно сделал перемещение окон, но с изменением размера у меня проблемы.
Вот то, что есть сейчас:
Я хочу, чтобы то окно меняло размер как вот это окно Chrome:
Основная часть кода:
class DesktopWindow {
element;
#width;
#height;
title;
// Window maximizing & restoring
#prevWidth;
#prevHeight;
#prevTop;
#prevLeft;
#maximized = false;
constructor(title, initialWidth, initialHeight, closeButton, maximizeButton, minimizeButton) {
this.title = title;
this.#width = initialWidth;
this.#height = initialHeight;
this.element = document.createElement("div");
this.element.classList.add("window");
this.element.style.width = this.#width + "px";
this.element.style.height = this.#height + "px";
this.element.innerHTML = `
<div class="resizer_up"></div>
<div class="resizer_right"></div>
<div class="resizer_left"></div>
<div class="resizer_bottom"></div>
<div class="resizer_up_left"></div>
<div class="resizer_up_right"></div>
<div class="resizer_bottom_left"></div>
<div class="resizer_bottom_right"></div>
<div class="frame">
<div class="left">
<div class="icon"></div>
<div class="title">${this.title}</div>
</div>
<div class="right">
<div class="minimize"></div>
<div class="restore"></div>
<div class="maximize"></div>
<div class="close"></div>
</div>
</div>
<div class="content">
</div>
`
// Hide buttons that don't need to be shown
if (!closeButton) this.closeButton.style.display = 'none';
if (!maximizeButton) this.maximizeButton.style.display = 'none';
if (!minimizeButton) this.minimizeButton.style.display = 'none';
// Button actions
this.closeButton.addEventListener('click', () => {
this.close();
})
this.maximizeButton.addEventListener('click', () => {
this.toggleMaximize();
})
this.minimizeButton.addEventListener('click', () => {
// Not implemented yet
})
this.hide();
// Center the window
const screenWidth = window.innerWidth;
const screenHeight = window.innerHeight;
this.element.style.top = `${(screenHeight - this.#height) / 2}px`
this.element.style.left = `${(screenWidth - this.#width) / 2}px`
// Draggable window
this.#draggableWindow();
// Resizers
this.#resizer_up();
document.getElementById("windows").appendChild(this.element);
}
get element() {
return this.element;
}
get width() {
this.#updateBounds();
return this.#width;
}
get height() {
this.#updateBounds();
return this.#height;
}
get title() {
return this.title;
}
set title(title) {
this.title = title;
this.element.querySelector(".title").innerHTML = title;
}
#updateBounds() {
this.#width = Number(this.element.style.width.replace("px", ""));
this.#height = Number(this.element.style.height.replace("px",""));
}
async show() {
this.element.classList.add("opening");
this.element.style.display = "flex";
await delay(250);
this.element.classList.remove("opening");
}
async hide() {
// TODO make this work
/* this.element.classList.add("closing");
await delay(250);
this.element.classList.remove("closing"); */
this.element.style.display = "none";
}
set height(height) {
this.#height = height;
this.element.style.height = height + "px";
}
set width(width) {
this.#width = width;
this.element.style.width = width + "px";
}
close() {
this.element.classList.add("closing");
setTimeout(() => {
this.element.remove();
}, 250);
}
async maximize() {
if (this.#maximized) {
return;
}
this.#prevWidth = this.#width;
this.#prevHeight = this.#height;
this.#prevTop = this.element.style.top;
this.#prevLeft = this.element.style.left;
this.element.style.transition = "all 0.25s ease-in-out";
this.element.style.width = "100%";
this.element.style.height = "calc(100vh - 40px)";
this.element.style.top = "0";
this.element.style.left = "0";
await delay(250)
this.element.style.transition = "";
this.maximizeButton.style.display = "none";
this.restoreButton.style.display = "block";
this.#updateBounds();
this.#maximized = true;
}
async restore() {
if (!this.#maximized) {
return;
}
this.#height = this.#prevHeight;
this.#width = this.#prevWidth;
this.element.style.transition = "all 0.25s ease-in-out";
this.element.style.width = this.#width + "px";
this.element.style.height = this.#height + "px";
this.element.style.top = this.#prevTop;
this.element.style.left = this.#prevLeft;
await delay(250);
this.element.style.transition = "";
this.#prevHeight = undefined;
this.#prevWidth = undefined;
this.#prevTop = undefined;
this.#prevLeft = undefined;
this.maximizeButton.style.display = "block";
this.restoreButton.style.display = "none";
this.#updateBounds();
this.#maximized = false;
}
toggleMaximize() {
if (this.#maximized) {
this.restore();
} else {
this.maximize();
}
}
get minimizeButton() {
return this.element.querySelector(".frame > .right > .minimize");
}
get maximizeButton() {
return this.element.querySelector(".frame > .right > .maximize");
}
get restoreButton() {
return this.element.querySelector(".frame > .right > .restore");
}
get closeButton() {
return this.element.querySelector(".frame > .right > .close");
}
#draggableWindow() {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
const frame = this.element.querySelector(".frame");
const obj = this;
frame.addEventListener("mousedown", (e) => {
dragMouseDown(e);
});
function dragMouseDown(e) {
obj.restore();
frame.style.cursor = "move";
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
obj.element.style.top = (obj.element.offsetTop - pos2) + "px";
obj.element.style.left = (obj.element.offsetLeft - pos1) + "px";
}
function closeDragElement() {
/* stop moving when mouse button is released:*/
document.onmouseup = null;
document.onmousemove = null;
frame.style.cursor = "default";
}
}
// Getters for resizers
get resizer_up() {
return this.element.querySelector(".resizer_up");
}
get resizer_right() {
return this.element.querySelector(".resizer_right");
}
get resizer_left() {
return this.element.querySelector(".resizer_left");
}
get resizer_bottom() {
return this.element.querySelector(".resizer_bottom");
}
get resizer_up_left() {
return this.element.querySelector(".resizer_up_left");
}
get resizer_up_right() {
return this.element.querySelector(".resizer_up_right");
}
get resizer_bottom_left() {
return this.element.querySelector(".resizer_bottom_left");
}
get resizer_bottom_right() {
return this.element.querySelector(".resizer_bottom_right");
}
// Resizers
#resizer_up() {
var pos1, pos2, pos3, pos4 = 0;
const obj = this;
obj.resizer_up.addEventListener("mousedown", (e) => {
dragMouseDown(e);
});
function dragMouseDown(e) {
obj.restore();
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
const prevTop = obj.element.style.top.replace("px", "");
// Update the top and height positions of the element based on the mouse movement
obj.element.style.top = (obj.element.offsetTop - pos2) + "px";
const val = Number(prevTop - obj.element.style.top.replace("px", ""));
obj.element.style.height = (obj.element.clientHeight + val) + "px";
console.log(obj.element.clientHeight + val == obj.element.style.height.replace("px", ""));
console.log(obj.element.clientHeight + val)
console.log(obj.element.style.height)
}
function closeDragElement() {
/* stop moving when mouse button is released:*/
document.onmouseup = null;
document.onmousemove = null;
}
}
}
Весь код я сюда уместить не смогу, полный код на GitHub
Сайт: клик