【问题标题】:Can not make div/element movable in nested shadowdom无法在嵌套的 shadowdom 中使 div/元素可移动
【发布时间】:2020-04-17 00:34:10
【问题描述】:

我无法让我的 div 可移动。它是一个自定义元素,由事件监听器创建。 这两个自定义元素都有自己的 shadowdom。

树形结构

第一个自定义元素是<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 }

WebDesktop 自定义元素

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 }

【问题讨论】:

  • 如果您创建一个 JSFiddle、Codepen 或内联 SO 代码会有所帮助,这样我们就可以运行代码...乍一看:.style.right = rect.top 是错误的.. 我认为
  • 好的,我会继续这样做。
  • 我保存(从未使用过)这个:javascript.info/mouse-drag-and-drop 来自我的每周 JS 通讯阅读

标签: javascript web-component shadow-dom custom-element


【解决方案1】:

&lt;app-window&gt; 上,您应该使用dragstart 事件处理程序并在DragEvent.dataTransfer 属性中记录您单击的位置:

appwindow.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 }

&lt;web-desktop&gt;容器上,你应该阻止dragover事件的默认行为,然后定义一个drop事件处理程序来设置新的&lt;app-window&gt;位置,根据上下点击差异计算:

webdesktop.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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多