Я пытаюсь создать пользовательский компонент для обучения, который позволит контенту иметь возможность плавать на странице и быть перетаскиваемым. Я столкнулся с проблемой при установлении исходной позиции компонента в правой стороне страницы. Я использую систему проектирования кальцита и ArcGIS JS, и мне нужно отображать компонент ArcGIS-Sketch в моем пользовательском компоненте. Установка исходной позиции на верхнюю правую я пытаюсь позиционировать ее, используя левый атрибут CSS, однако, когда я пытаюсь получить позицию, она не работает из-за того, что виджет эскизов все еще отображается, поэтому я получаю неправильное значение ширины. Я попытался использовать запрос QuestionAnimationFrame, изменить размер наблюдателя и слушателя событий Slotchange, но он все еще не работает. Я также пытаюсь сделать компонент для обработки какого -либо контента, но я не уверен, что это глупо или нет. Я также знаю, что я мог бы использовать компонент диалога кальцита, но я пытаюсь сделать свой собственный учиться и для некоторых других проблем.
toggleSketchLayout()}>
toggleDock("draw")}>
< /code>
import html from './floater.html?raw';
import styleText from './floater.css?inline';
class Floater extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
// Wait for Calcite's to be defined before injecting HTML
customElements.whenDefined("calcite-action").then(() => {
// Initial state
this.isDragging = false;
this.offsetX = 0;
this.offsetY = 0;
// Link the css file
const style = document.createElement("style");
style.textContent = styleText
this.shadowRoot.appendChild(style);
// Inject template from raw HTML
const template = document.createElement("template");
template.innerHTML = html;
this.shadowRoot.appendChild(template.content.cloneNode(true));
this._init();
});
}
_init() {
this.floater = this.shadowRoot.querySelector(".floater");
this.heading = this.shadowRoot.querySelector(".floater-heading")
this.hTitle = this.shadowRoot.querySelector(".floater-heading-title");
this.originalhTitle = this.hTitle?.outerHTML || null;
this.headingEnd = this.shadowRoot.querySelector(".floater-heading-end")
this.closeButton = this.shadowRoot.querySelector("calcite-action");
this.originalCloseButton = this.closeButton?.outerHTML || null
this.contentSlot = this.shadowRoot.querySelector('slot:not([name])');
requestAnimationFrame(() => {
this._onReady()
});
}
// Trigger after component has been created
_onReady() {
this._updateTitle();
this._updateClose();
this._setScale();
window.addEventListener("resize", this._onResize);
this.heading.addEventListener("mousedown", this._onMouseDown);
this.closeButton.addEventListener("click", () => this.remove());
// Wait for the next repaint to ensure rendering is complete
requestAnimationFrame(() => {
this._setInitalPosition();
});
}
// Trigger on component delete
disconnectedCallback() {
window.removeEventListener("resize", this._onResize)
document.removeEventListener("mousemove", this._onMouseMove);
document.removeEventListener("mouseup", this._onMouseUp);
}
static get observedAttributes() {
return ["title", "close-disabled", "scale"];
}
// Trigger when attribute changes
attributeChangedCallback(name, oldValue, newValue) {
if (name === "title") this._updateTitle();
if (name === "close-disabled") this._updateClose();
if (name === "scale") this._setScale();
}
_onResize = () => {
console.log("resize")
}
// This function will either create or delete, depending on the attribute
_handleElementLife = (atr, currentEl, originalEl, parent) => {
// If empty then remove the element
if (!atr.trim()) {
if (currentEl) currentEl.remove()
return null;
}
// Add the element
if (!currentEl && originalEl) {
const temp = document.createElement("div");
temp.innerHTML = originalEl;
currentEl = temp.firstElementChild;
parent.insertBefore(currentEl, parent.firstChild);
}
if (currentEl) {
currentEl.textContent = atr;
return currentEl;
}
}
_updateTitle = () => {
const titleAtr = this.getAttribute("title") || "";
this.hTitle = this._handleElementLife(titleAtr, this.hTitle, this.originalhTitle, this.heading)
}
_updateClose = () => {
const disabled = this.hasAttribute("close-disabled");
if (disabled) {
this.closeButton.remove();
this.closeButton = null;
return;
}
// Add the element
if (!this.closeButton && this.originalCloseButton) {
const temp = document.createElement("div");
temp.innerHTML = this.originalCloseButton;
this.closeButton = temp.firstElementChild;
this.headingEnd.append(this.closeButton);
}
}
_setInitalPosition = () => {
const positionAtr = this.getAttribute("position") || "center";
// Reset existing positions
this.floater.style.top = "0px";
this.floater.style.left = "0px";
this.floater.style.transform = "none";
console.log(this.floater)
switch (positionAtr) {
case "center":
this.floater.style.top = "50%";
this.floater.style.left = "50%";
this.floater.style.transform = "translate(-50%, -50%)";
break;
case "top-left":
this.floater.style.top = "10px";
this.floater.style.left = "10px";
break;
case "top-right":
console.log(window.innerWidth)
console.log("width", this.floater.offsetWidth);
this.floater.style.top = "10px";
this.floater.style.left = `${window.innerWidth - this.floater.offsetWidth}px`;
break;
case "bottom-left":
this.floater.style.bottom = "10px";
this.floater.style.left = "10px";
break;
case "bottom-right":
this.floater.style.bottom = "10px";
this.floater.style.left = `${window.innerWidth - this.floater.offsetWidth}px`;
break;
}
// Change transform to position style
if (positionAtr === "center") {
requestAnimationFrame(() => this._convertTransformToPosition());
}
}
_convertTransformToPosition = () => {
const rect = this.floater.getBoundingClientRect();
const style = getComputedStyle(this.floater);
const transform = style.transform;
if (transform && transform !== "none") {
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const actualLeft = rect.left + scrollLeft;
const actualTop = rect.top + scrollTop;
this.floater.style.left = `${actualLeft}px`;
this.floater.style.top = `${actualTop}px`;
this.floater.style.transform = "none";
}
}
_setScale = () => {
let scaleAtr = this.getAttribute("scale") || "s";
if(this.closeButton) this.closeButton.dataset.scale = scaleAtr
}
// Handle floater movement
_onMouseDown = (e) => {
this.isDragging = true;
// Compute position based on visual location
const rect = this.floater.getBoundingClientRect();
this.offsetX = e.clientX - rect.left;
this.offsetY = e.clientY - rect.top;
document.addEventListener("mousemove", this._onMouseMove);
document.addEventListener("mouseup", this._onMouseUp);
};
_onMouseMove = (e) => {
if (!this.isDragging) return;
let newLeft = e.clientX - this.offsetX;
let newTop = e.clientY - this.offsetY;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const floaterWidth = this.floater.offsetWidth;
const floaterHeight = this.floater.offsetHeight;
newLeft = Math.max(0, Math.min(windowWidth - floaterWidth, newLeft));
newTop = Math.max(0, Math.min(windowHeight - floaterHeight, newTop));
this.floater.style.left = `${newLeft}px`;
this.floater.style.top = `${newTop}px`;
}
_onMouseUp = () => {
this.isDragging = false;
document.removeEventListener("mousemove", this._onMouseMove);
document.removeEventListener("mouseup", this._onMouseUp);
}
}
if (!customElements.get("custom-floater"))
customElements.define("custom-floater", Floater);
< /code>
.floater{
/* min-width: 150px; */
display: block;
position: fixed;
top: 0;
left: 0;
z-index: var(--calcite-z-index-modal);
box-sizing: border-box;
border-radius: 0.25rem;
background-color: var(--floater-background-color);
font-family: var(--calcite-sans-family);
box-shadow: var(--calcite-shadow-sm);
}
.floater-heading{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
border-bottom: 1px solid var(--calcite-color-border-3);
cursor: move;
user-select: none;
}
.floater-heading-title{
padding: var(--calcite-spacing-xs) var(--calcite-spacing-md-plus);
font-weight: var(--calcite-font-weight-medium);
font-size: var(--calcite-font-size-0);
color: var(--calcite-color-text-1);
}
.floater-heading-end{
margin-left: auto;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.floater-close{
height: 100%;
width: auto;
background-color: transparent;
border: 0;
cursor: pointer;
}
.floater-content{
padding: var(--calcite-spacing-md);
}
< /code>
Подробнее здесь: https://stackoverflow.com/questions/796 ... l-position
Компоненты Фактическая ширина не получается при установке начальной позиции ⇐ Javascript
Форум по Javascript
1751633989
Anonymous
Я пытаюсь создать пользовательский компонент для обучения, который позволит контенту иметь возможность плавать на странице и быть перетаскиваемым. Я столкнулся с проблемой при установлении исходной позиции компонента в правой стороне страницы. Я использую систему проектирования кальцита и ArcGIS JS, и мне нужно отображать компонент ArcGIS-Sketch в моем пользовательском компоненте. Установка исходной позиции на верхнюю правую я пытаюсь позиционировать ее, используя левый атрибут CSS, однако, когда я пытаюсь получить позицию, она не работает из-за того, что виджет эскизов все еще отображается, поэтому я получаю неправильное значение ширины. Я попытался использовать запрос QuestionAnimationFrame, изменить размер наблюдателя и слушателя событий Slotchange, но он все еще не работает. Я также пытаюсь сделать компонент для обработки какого -либо контента, но я не уверен, что это глупо или нет. Я также знаю, что я мог бы использовать компонент диалога кальцита, но я пытаюсь сделать свой собственный учиться и для некоторых других проблем.
toggleSketchLayout()}>
toggleDock("draw")}>
< /code>
import html from './floater.html?raw';
import styleText from './floater.css?inline';
class Floater extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
// Wait for Calcite's to be defined before injecting HTML
customElements.whenDefined("calcite-action").then(() => {
// Initial state
this.isDragging = false;
this.offsetX = 0;
this.offsetY = 0;
// Link the css file
const style = document.createElement("style");
style.textContent = styleText
this.shadowRoot.appendChild(style);
// Inject template from raw HTML
const template = document.createElement("template");
template.innerHTML = html;
this.shadowRoot.appendChild(template.content.cloneNode(true));
this._init();
});
}
_init() {
this.floater = this.shadowRoot.querySelector(".floater");
this.heading = this.shadowRoot.querySelector(".floater-heading")
this.hTitle = this.shadowRoot.querySelector(".floater-heading-title");
this.originalhTitle = this.hTitle?.outerHTML || null;
this.headingEnd = this.shadowRoot.querySelector(".floater-heading-end")
this.closeButton = this.shadowRoot.querySelector("calcite-action");
this.originalCloseButton = this.closeButton?.outerHTML || null
this.contentSlot = this.shadowRoot.querySelector('slot:not([name])');
requestAnimationFrame(() => {
this._onReady()
});
}
// Trigger after component has been created
_onReady() {
this._updateTitle();
this._updateClose();
this._setScale();
window.addEventListener("resize", this._onResize);
this.heading.addEventListener("mousedown", this._onMouseDown);
this.closeButton.addEventListener("click", () => this.remove());
// Wait for the next repaint to ensure rendering is complete
requestAnimationFrame(() => {
this._setInitalPosition();
});
}
// Trigger on component delete
disconnectedCallback() {
window.removeEventListener("resize", this._onResize)
document.removeEventListener("mousemove", this._onMouseMove);
document.removeEventListener("mouseup", this._onMouseUp);
}
static get observedAttributes() {
return ["title", "close-disabled", "scale"];
}
// Trigger when attribute changes
attributeChangedCallback(name, oldValue, newValue) {
if (name === "title") this._updateTitle();
if (name === "close-disabled") this._updateClose();
if (name === "scale") this._setScale();
}
_onResize = () => {
console.log("resize")
}
// This function will either create or delete, depending on the attribute
_handleElementLife = (atr, currentEl, originalEl, parent) => {
// If empty then remove the element
if (!atr.trim()) {
if (currentEl) currentEl.remove()
return null;
}
// Add the element
if (!currentEl && originalEl) {
const temp = document.createElement("div");
temp.innerHTML = originalEl;
currentEl = temp.firstElementChild;
parent.insertBefore(currentEl, parent.firstChild);
}
if (currentEl) {
currentEl.textContent = atr;
return currentEl;
}
}
_updateTitle = () => {
const titleAtr = this.getAttribute("title") || "";
this.hTitle = this._handleElementLife(titleAtr, this.hTitle, this.originalhTitle, this.heading)
}
_updateClose = () => {
const disabled = this.hasAttribute("close-disabled");
if (disabled) {
this.closeButton.remove();
this.closeButton = null;
return;
}
// Add the element
if (!this.closeButton && this.originalCloseButton) {
const temp = document.createElement("div");
temp.innerHTML = this.originalCloseButton;
this.closeButton = temp.firstElementChild;
this.headingEnd.append(this.closeButton);
}
}
_setInitalPosition = () => {
const positionAtr = this.getAttribute("position") || "center";
// Reset existing positions
this.floater.style.top = "0px";
this.floater.style.left = "0px";
this.floater.style.transform = "none";
console.log(this.floater)
switch (positionAtr) {
case "center":
this.floater.style.top = "50%";
this.floater.style.left = "50%";
this.floater.style.transform = "translate(-50%, -50%)";
break;
case "top-left":
this.floater.style.top = "10px";
this.floater.style.left = "10px";
break;
case "top-right":
console.log(window.innerWidth)
console.log("width", this.floater.offsetWidth);
this.floater.style.top = "10px";
this.floater.style.left = `${window.innerWidth - this.floater.offsetWidth}px`;
break;
case "bottom-left":
this.floater.style.bottom = "10px";
this.floater.style.left = "10px";
break;
case "bottom-right":
this.floater.style.bottom = "10px";
this.floater.style.left = `${window.innerWidth - this.floater.offsetWidth}px`;
break;
}
// Change transform to position style
if (positionAtr === "center") {
requestAnimationFrame(() => this._convertTransformToPosition());
}
}
_convertTransformToPosition = () => {
const rect = this.floater.getBoundingClientRect();
const style = getComputedStyle(this.floater);
const transform = style.transform;
if (transform && transform !== "none") {
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const actualLeft = rect.left + scrollLeft;
const actualTop = rect.top + scrollTop;
this.floater.style.left = `${actualLeft}px`;
this.floater.style.top = `${actualTop}px`;
this.floater.style.transform = "none";
}
}
_setScale = () => {
let scaleAtr = this.getAttribute("scale") || "s";
if(this.closeButton) this.closeButton.dataset.scale = scaleAtr
}
// Handle floater movement
_onMouseDown = (e) => {
this.isDragging = true;
// Compute position based on visual location
const rect = this.floater.getBoundingClientRect();
this.offsetX = e.clientX - rect.left;
this.offsetY = e.clientY - rect.top;
document.addEventListener("mousemove", this._onMouseMove);
document.addEventListener("mouseup", this._onMouseUp);
};
_onMouseMove = (e) => {
if (!this.isDragging) return;
let newLeft = e.clientX - this.offsetX;
let newTop = e.clientY - this.offsetY;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
const floaterWidth = this.floater.offsetWidth;
const floaterHeight = this.floater.offsetHeight;
newLeft = Math.max(0, Math.min(windowWidth - floaterWidth, newLeft));
newTop = Math.max(0, Math.min(windowHeight - floaterHeight, newTop));
this.floater.style.left = `${newLeft}px`;
this.floater.style.top = `${newTop}px`;
}
_onMouseUp = () => {
this.isDragging = false;
document.removeEventListener("mousemove", this._onMouseMove);
document.removeEventListener("mouseup", this._onMouseUp);
}
}
if (!customElements.get("custom-floater"))
customElements.define("custom-floater", Floater);
< /code>
.floater{
/* min-width: 150px; */
display: block;
position: fixed;
top: 0;
left: 0;
z-index: var(--calcite-z-index-modal);
box-sizing: border-box;
border-radius: 0.25rem;
background-color: var(--floater-background-color);
font-family: var(--calcite-sans-family);
box-shadow: var(--calcite-shadow-sm);
}
.floater-heading{
display: flex;
flex-direction: row;
flex-wrap: nowrap;
border-bottom: 1px solid var(--calcite-color-border-3);
cursor: move;
user-select: none;
}
.floater-heading-title{
padding: var(--calcite-spacing-xs) var(--calcite-spacing-md-plus);
font-weight: var(--calcite-font-weight-medium);
font-size: var(--calcite-font-size-0);
color: var(--calcite-color-text-1);
}
.floater-heading-end{
margin-left: auto;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.floater-close{
height: 100%;
width: auto;
background-color: transparent;
border: 0;
cursor: pointer;
}
.floater-content{
padding: var(--calcite-spacing-md);
}
< /code>
Подробнее здесь: [url]https://stackoverflow.com/questions/79690219/components-actual-width-is-not-being-obtained-while-setting-inital-position[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия