简体   繁体   English

将鼠标事件绑定和解除绑定到自定义元素的问题

[英]Problem with binding and unbinding mouse events to custom element

I am trying to add "move by mouse" functionality to my CustomElement to enable it to move by mouse drag, by this simple function as below.我正在尝试将“通过鼠标移动”功能添加到我的 CustomElement 中,以使其能够通过鼠标拖动来移动,如下所示。 But it has a lot of lag and the event does not attach and detach correctly on "mouseup" or "mousedown" events.但是它有很多滞后,并且事件在“mouseup”或“mousedown”事件上无法正确附加和分离。 I couldn't found why this happens because it works normally on simple "div" elements.我找不到为什么会发生这种情况,因为它可以在简单的“div”元素上正常工作。

drag functionality:拖动功能:

 //drag-element.js export default function dragElement(elm) { const header = elm.Cardheader; header.style.cursor = "all-scroll"; let [initX, initY] = [0, 0]; let mousedown = false; let mousemoveEventHandler = function(e) { if (mousedown) { elm.style.top = `${e.clientY - initY}px`; elm.style.left = `${e.clientX - initX}px`; } }; let mousedownEventHandler = function(e) { mousedown = true; header.onmousemove = mousemoveEventHandler; initX = e.clientX - elm.offsetLeft; initY = e.clientY - elm.offsetTop; }; let mouseupEventHandler = function(e) { mousedown = false; header.onmousemove = null; }; document.addEventListener("mouseup", mouseupEventHandler); header.onmousedown = mousedownEventHandler; }

Custom Element:自定义元素:

 //content-card.js export default class ContentCard extends HTMLElement { constructor() { super(); let shadow = this.attachShadow({ mode: "open" }); let style = document.createElement("style"); style.textContent = ` :host { position: absolute; background-color: #fff; width: 50%; margin: 20px auto; display: block; border: 1px solid #eee; box-shadow: 1px 1px 4px 1px #444; box-sizing: border-box; } .header { background-color: #eee; min-height: 20px; display: block; padding: 15px; } .body { min-height: 150px; display: block; padding: 15px; } `; this.Cardheader = document.createElement("div"); this.Cardheader.setAttribute("class", "header"); this.Cardbody = document.createElement("div"); this.Cardbody.setAttribute("class", "body"); this.Cardheader.textContent = this.getAttribute("subject"); this.Cardbody.innerHTML = this.getAttribute("content"); shadow.appendChild(this.Cardheader); shadow.appendChild(this.Cardbody); shadow.appendChild(style); } static get observedAttributes() { return ["subject", "content"]; } get subject() { return this.Cardheader.textContent; } set subject(val) { this.Cardheader.textContent = val; } get content() { return this.Cardbody.innerHTML; } set content(val) { this.Cardbody.innerHTML = val; } connectedCallback() {} disconnectedCallback() {} attributeChangedCallback(name, oldValue, newValue) { if (newValue === oldValue) return; switch (name) { case "subject": this.subjetct = newValue; break; case "content": this.content = newValue; break; default: break; } } adoptedCallback() {} }

main Javascript:主要的Javascript:

 //index.js import ContentCard from "./content-card.js"; import ContentCard from "./drag-element.js"; customElements.define("content-card", ContentCard); let cCard = new ContentCard(); document.body.appendChild(cCard); dragElement(cCard);
 <html> <head> <script defer type="module" src="./index.js"></script> </head> <body> <content-card subject="subject" content="Content"></content-card> </body> </html>

With thanks of @fubar and @Zydnar I change Style of host and removed the margin: 20 auto and also add event.preventDefault() to mousedown event and lag decreased a lot and also unbinding problem fixed in the separate browser.感谢@fubar 和@Zydnar,我更改了主机的样式并删除了margin: 20 auto并将event.preventDefault()添加到 mousedown 事件和延迟减少了很多,并且在单独的浏览器中修复了解绑问题。 (But it has still, the problem with code snippets) but it does not occur in the real page. (但它仍然存在,代码片段的问题)但它不会出现在真实页面中。 I add some improvement to drag methods:我对拖动方法添加了一些改进:

1- instead of setting elm.style.top and elm.style.left I used elm.style.transform = translate(${left}px,${top}px) ; 1- 而不是设置elm.style.topelm.style.left我使用elm.style.transform = translate(${left}px,${top}px) ; 2- instead of using element.offsetLeft and element.offsetTop I used let rect = elm.getBoundingClientRect(); 2- 而不是使用element.offsetLeftelement.offsetTop我使用let rect = elm.getBoundingClientRect(); and rect,left and rect.toprect,leftrect.top

 //drag-element.js function dragElement(elm) { const header = elm.Cardheader; header.style.cursor = "all-scroll"; let [initX, initY] = [0, 0]; let mousedown = false; let mousemoveEventHandler = function(e) { if (mousedown) { let top = e.clientY - initY || elm.top; let left = e.clientX - initX || elm.left; elm.style.transform = `translate(${left}px,${top}px)`; } }; let mousedownEventHandler = function(e) { e.preventDefault(); mousedown = true; header.onmousemove = mousemoveEventHandler; let rect = elm.getBoundingClientRect(); initX = e.clientX - rect.left; initY = e.clientY - rect.top; }; let mouseupEventHandler = function(e) { mousedown = false; header.onmousemove = null; }; document.addEventListener("mouseup", mouseupEventHandler); header.onmousedown = mousedownEventHandler; } //content-card.js class ContentCard extends HTMLElement { constructor() { super(); let shadow = this.attachShadow({ mode: "open" }); let style = document.createElement("style"); style.textContent = ` :host { position: absolute; background-color: #fff; backface-visibility: hidden; width: 50%; display: block; border: 1px solid #eee; box-shadow: 1px 1px 4px 1px #444; box-sizing: border-box; } .header { background-color: #eee; min-height: 20px; display: block; padding: 15px; } .body { min-height: 150px; display: block; padding: 15px; } `; this.Cardheader = document.createElement("div"); this.Cardheader.setAttribute("class", "header"); this.Cardbody = document.createElement("div"); this.Cardbody.setAttribute("class", "body"); this.Cardheader.textContent = this.getAttribute("subject"); this.Cardbody.innerHTML = this.getAttribute("content"); shadow.appendChild(this.Cardheader); shadow.appendChild(this.Cardbody); shadow.appendChild(style); } static get observedAttributes() { return ["subject", "content"]; } get subject() { return this.Cardheader.textContent; } set subject(val) { this.Cardheader.textContent = val; } get content() { return this.Cardbody.innerHTML; } set content(val) { this.Cardbody.innerHTML = val; } connectedCallback() {} disconnectedCallback() {} attributeChangedCallback(name, oldValue, newValue) { if (newValue === oldValue) return; switch (name) { case "subject": this.subjetct = newValue; break; case "content": this.content = newValue; break; default: break; } } adoptedCallback() {} } customElements.define("content-card", ContentCard); let cCard = new ContentCard(); document.body.appendChild(cCard); dragElement(cCard);

Ok, so the px fixed the sticking and the funny snapping behavior at the start can be offset by adding the padding of the header to the initY .好的,因此px修复了开始时的粘连和有趣的捕捉行为,可以通过将标题的填充添加到initYinitY This caused by the header having padding and the offset of the elm not accounting for this and the header snaped to the mouse position so it was snapping with 15px to much which caused the mouse to move out of the header and dropping the element.这是由于标题具有填充和elm的偏移量没有考虑到这一点,并且header与鼠标位置对齐,因此它与15px对齐,导致鼠标移出标题并丢弃元素。 Any one know a the correct prop here?有人知道这里的正确道具吗? This will answer your question why it was kind of weird...这将回答你的问题,为什么它有点奇怪......

Regarding the laggy bit you might have to look at maybe skipping a few events.关于滞后位,您可能需要考虑跳过一些事件。

 //drag-element.js function dragElement(elm) { const header = elm.Cardheader; header.style.cursor = "all-scroll"; let [initX, initY] = [0, 0]; let mousedown = false; let mousemoveEventHandler = function(e) { if (mousedown) { elm.style.top = `${e.clientY - initY}px`; elm.style.left = `${e.clientX - initX}px`; } }; let mousedownEventHandler = function(e) { mousedown = true; elm.onmousemove = mousemoveEventHandler; initX = e.clientX - elm.offsetLeft; initY = e.clientY - elm.offsetTop + 15; }; let mouseupEventHandler = function(e) { mousedown = false; header.onmousemove = null; }; document.addEventListener("mouseup", mouseupEventHandler); header.onmousedown = mousedownEventHandler; } //content-card.js class ContentCard extends HTMLElement { constructor() { super(); let shadow = this.attachShadow({ mode: "open" }); let style = document.createElement("style"); style.textContent = ` :host { position: absolute; background-color: #fff; width: 50%; margin: 20px auto; display: block; border: 1px solid #eee; box-shadow: 1px 1px 4px 1px #444; box-sizing: border-box; } .header { background-color: #eee; min-height: 20px; display: block; padding: 15px; } .body { min-height: 150px; display: block; padding: 15px; } `; this.Cardheader = document.createElement("div"); this.Cardheader.setAttribute("class", "header"); this.Cardbody = document.createElement("div"); this.Cardbody.setAttribute("class", "body"); this.Cardheader.textContent = this.getAttribute("subject"); this.Cardbody.innerHTML = this.getAttribute("content"); shadow.appendChild(this.Cardheader); shadow.appendChild(this.Cardbody); shadow.appendChild(style); } static get observedAttributes() { return ["subject", "content"]; } get subject() { return this.Cardheader.textContent; } set subject(val) { this.Cardheader.textContent = val; } get content() { return this.Cardbody.innerHTML; } set content(val) { this.Cardbody.innerHTML = val; } connectedCallback() {} disconnectedCallback() {} attributeChangedCallback(name, oldValue, newValue) { if (newValue === oldValue) return; switch (name) { case "subject": this.subjetct = newValue; break; case "content": this.content = newValue; break; default: break; } } adoptedCallback() {} } customElements.define("content-card", ContentCard); let cCard = new ContentCard(); document.body.appendChild(cCard); dragElement(cCard);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM