javascript - 无法在嵌套的 shadowdom 中使 div/元素可移动
问题描述
我不能让我的 div 可移动。它是一个自定义元素,由事件监听器创建。这两个自定义元素都有自己的影子。
第一个自定义元素是<web-desktop>
/WebDesktop.js 第二个元素是<app-window>
/AppWindow.js
<app-window>
在我单击事件侦听器后创建。现在我试图通过单击按钮创建该“窗口”(div)后移动。
但是,我这样做了几个小时都没有成功。
我包括了这两个部分,我坚信问题出在 AppWindow 内。
AppWindow 自定义元素
const template = document.createElement('template')
template.innerHTML = `
<style>
#mydiv {
position: absolute;
z-index: 9;
background-color: #f1f1f1;
border: 1px solid #d3d3d3;
text-align: center;
}
#mydivheader {
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
</style>
<div id="mydiv">
<div id="mydivheader">Click here to move</div>
<p>Move</p>
<p>this</p>
<p>DIV</p>
</div>
`
class AppWindow extends window.HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.shadowRoot.appendChild(template.content.cloneNode(true))
this.appWindowHeader = this.shadowRoot.querySelector('#mydivheader')
this.appWindow = this.shadowRoot.querySelector('#mydiv')
this.prevX = undefined
this.prevY = undefined
this.newX = undefined
this.newY = undefined
}
static get observedAttributes() {
return []
}
attributesChangedCallback(name, oldValue, newValue) {
}
connectedCallback() {
this.appWindow.addEventListener('mousedown', this.mousedown)
}
mousedown(event) {
window.addEventListener('mousemove', this.mousemove)
window.addEventListener('mouseup', this.mouseup)
this.prevX = event.clientX
this.prevY = event.clientY
}
mousemove(event) {
this.newX = event.clientX
this.newY = event.clientY
const rect = this.appWindow.getBoundingClientRect()
this.appWindow.style.left = rect.left - this.newX + 'px'
this.appWindow.style.right = rect.top - this.newY + 'px'
this.prevX = event.clientX
this.prevY = event.clientY
}
mouseup() {
}
}
window.customElements.define('app-window', AppWindow)
export { AppWindow }
Web桌面自定义元素
import { AppWindow } from './AppWindow.js'
const template = document.createElement('template')
template.innerHTML = `
<style>
.resizer {
position: absolute;
width: 10px;
height: 10px;
border-radius: 5px;
background-color: black;
z-index: 2;
}
#appImg1 {
cursor:pointer;
}
#menuDiv {
background-color: rgb(23, 23, 23);
position: fixed;
bottom: 0;
width: 100%;
padding: 0px;
margin: 0px;
}
#menuDiv img {
margin-left: 25px;
}
hr {
border: 1px solid black;
border-radius: 0px;
margin:0;
margin-bottom:5px;
}
</style>
<div id="webDesktopDiv">
<div id="menuDiv">
<hr>
<img src="../image/icon.png" id="appImg1">
</div>
</div>
`
class WebDesktop extends window.HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.shadowRoot.appendChild(template.content.cloneNode(true))
this.menuDiv = this.shadowRoot.querySelector('#menuDiv')
this.webDesktopDiv = this.shadowRoot.querySelector('#webDesktopDiv')
this.appImg1 = this.shadowRoot.querySelector('#appImg1')
}
static get observedAttributes() {
return []
}
attributesChangedCallback(name, oldValue, newValue) {
}
connectedCallback() {
this.appImg1.addEventListener('click', event => {
this.createWindow()
})
}
createWindow() {
let appWindow = document.createElement('app-window')
appWindow.classList = 'item'
appWindow.setAttribute('draggable', 'true')
this.webDesktopDiv.appendChild(appWindow)
}
}
window.customElements.define('web-desktop', WebDesktop)
export { WebDesktop }
解决方案
在 上<app-window>
,您应该使用dragstart
事件处理程序并记录您在属性中单击的位置DragEvent.dataTransfer
:
应用程序窗口.js
const template = `
<style>
:host {
position: absolute
}
#mydiv {
z-index: 9;
background-color: #f1f1f1;
border: 1px solid #d3d3d3;
text-align: center;
}
#mydivheader {
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
</style>
<div id="mydiv">
<div id="mydivheader">Click here to move</div>
<p>Move</p>
<p>this</p>
<p>DIV</p>
</div>
`
var count = 0
class AppWindow extends window.HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' }).innerHTML = template
}
connectedCallback() {
this.setAttribute( 'draggable', 'true' )
this.id = count++
this.ondragstart = ev => ev.dataTransfer.setData( 'text', JSON.stringify( {
id: ev.target.id,
x: ev.clientX,
y: ev.clientY
} ) )
}
}
window.customElements.define('app-window', AppWindow)
export { AppWindow }
在<web-desktop>
容器上,你应该阻止dragover
事件的默认行为,然后定义一个事件处理程序来设置根据上下点击差异计算drop
的新位置:<app-window>
网页桌面.js
import { AppWindow } from './AppWindow.js'
const template = `
<style>
:host {
height: 100% ;
display: block ;
}
button {
position: fixed;
bottom: 10px; left: 10px;
}
</style>
<button>Add</buton>
`
var count = 0
class WebDesktop extends window.HTMLElement {
constructor() {
super()
this.attachShadow( { mode: 'open' } ).innerHTML = template
}
connectedCallback() {
this.shadowRoot.querySelector( 'button' ).onclick = () => this.shadowRoot.appendChild( new AppWindow )
this.ondragover = ev => ev.preventDefault()
this.ondrop = ev => {
let origin = JSON.parse( ev.dataTransfer.getData( 'text' ) )
console.log( origin )
let app = this.shadowRoot.getElementById( origin.id )
let childPos = app.getBoundingClientRect()
app.style.left = childPos.left + ( ev.clientX - origin.x ) + 'px'
app.style.top = childPos.top + ( ev.clientY - origin.y ) + 'px'
}
}
}
window.customElements.define('web-desktop', WebDesktop)
推荐阅读
- c++ - MIP 模型中忽略了等式约束
- c# - DBContext 构造函数中的 System.ExecutionEngineException
- python - TfidfVectorizer的词汇表和get_features()之间的区别?
- html - 如何使用 CSS 创建 3 段甜甜圈/环?
- java - Delete 和 DeleteById 方法在 Hibernate 中不起作用
- java - 错误:无法找到或加载主类 -Xms1G
- vba - vba scrape html - 获取具有动态类的元素
- user-interface - 在 Tkinter GUI 中嵌入散景和大数据
- javascript - 在 JavaScript 中使用 setInterval 循环时如何让精灵停止移动
- javascript - 选中复选框时,如何将表单控件的所有值传递给另一个表单?