Web动画api填充模式混乱,(影响可拖动元素后续交互)

问题描述 投票:0回答:1

所以我有这个简单的例子,它模仿棋盘中的可拖动棋子。

pointerup
我想执行回弹动画到片段起始位置。 好吧,如果我不指定
fill
模式(使用
fill: 'none'
)并在动画完成时手动翻译元素,它就可以工作。

为什么当我指定了

fill: 'forwards'
时它不起作用?我还尝试在动画完成后使用
commitStyles()
将这些样式提交到内联 css,但之后拖动仍然不起作用。您可以在开发工具中看到该部分应该移动,但它仍然留在原处。向前填充应该保持最终动画帧的状态,这基本上就是我想要我的作品所在的位置,不知道为什么它会使其之后不可拖动。

我认为 Web 动画 api 样式和我的样式存在一些冲突,但我无法弄清楚到底是什么问题。 这是否记录在某处,我找不到任何相关内容。

const board = document.querySelector('section')
const piece = document.querySelector('div')

const pieceOffsetSize = 35 // half piece size
const lastPos = { x: 0, y: 0 }
let dragging = false

function translateElement(elm, dx, dy) {
  elm.style.transform = `translate(${dx}px, ${dy}px)`
}

function performSnapback(elm) {
  const opts = { duration: 300 } // no fill mode (fill: 'none')
  const keyframes = [{ transform: `translate(${lastPos.x}px, ${lastPos.y}px)` }]
  const animation = elm.animate(keyframes, opts)

  animation.onfinish = () => {
    translateElement(elm, lastPos.x, lastPos.y) // after finish, i translate element manually
  }
}

function performSnapback2(elm) {
  const opts = { duration: 300, fill: 'forwards' } // tried fill: 'both' also and does not work
  const keyframes = [{ transform: `translate(${lastPos.x}px, ${lastPos.y}px)` }]  
  const animation = elm.animate(keyframes, opts)

  animation.onfinish = () => {
    animation.commitStyles() // tried with and without this and does not work
  }
}

piece.onpointerdown = e => {
  dragging = true
  e.target.setPointerCapture(e.pointerId)
  e.target.style.userSelect = 'none'
  const deltaX = e.clientX - board.offsetLeft - pieceOffsetSize
  const deltaY = e.clientY - board.offsetTop - pieceOffsetSize
  translateElement(e.target, deltaX, deltaY)
}

piece.onpointerup = e => {
  dragging = false
  e.target.releasePointerCapture(e.pointerId)
  e.target.style.userSelect = 'auto'
  // performSnapback(e.target) // WORKS
  performSnapback2(e.target)   // DOES NOT WORK 
}

piece.onpointermove = e => {
  if (!dragging) return
  const deltaX = e.clientX - board.offsetLeft - pieceOffsetSize
  const deltaY = e.clientY - board.offsetTop - pieceOffsetSize
  translateElement(e.target, deltaX, deltaY)
}
body { padding: 0; margin: 0; }
section { width: 400px; height: 400px; outline: 2px solid darkviolet; margin: 100px; position: relative; }
div { position: absolute; background: plum; width: 70px; height: 70px; }
<section>
  <div style="transform: translate(0px, 0px)"></div>
</section>

javascript html css draggable web-animations
1个回答
0
投票

如果您通过设置

none
来移动元素,则必须使用
animation

检查

none
上的文档:

动画在不执行时不会将任何样式应用于目标。 该元素将使用应用于其的任何其他 CSS 规则来显示。这是默认值。

这正是您所需要的。

animation.onfinish
也不需要。

第二次拖动仍会执行

performSnapback
x=0
y=0
,因为您尚未更新
lastPos

const board = document.querySelector('section')
const piece = document.querySelector('div')

const pieceOffsetSize = 35 // half piece size
const lastPos = { x: 0, y: 0 }
let dragging = false

function translateElement(elm, dx, dy) {
  elm.style.transform = `translate(${dx}px, ${dy}px)`
}

function performSnapback2(elm) {
  const opts = { duration: 300, fill: 'none' };
  const keyframes = [{ transform: `translate(${lastPos.x}px, ${lastPos.y}px)` }]  
  elm.animate(keyframes, opts)
}

piece.onpointerdown = function(e) {
  dragging = true
  e.target.setPointerCapture(e.pointerId)
  const deltaX = e.clientX - board.offsetLeft - pieceOffsetSize
  const deltaY = e.clientY - board.offsetTop - pieceOffsetSize
  translateElement(e.target, deltaX, deltaY)
}

piece.onpointerup = e => {
  dragging = false
  e.target.releasePointerCapture(e.pointerId)
  e.target.style.userSelect = 'auto'
  performSnapback2(e.target)
}

piece.onpointermove = e => {
  if (!dragging) return
  const deltaX = e.clientX - board.offsetLeft - pieceOffsetSize
  const deltaY = e.clientY - board.offsetTop - pieceOffsetSize
  translateElement(e.target, deltaX, deltaY)
}
body { padding: 0; margin: 0; }
section { width: 400px; height: 400px; outline: 2px solid darkviolet; margin: 100px; position: relative; }
div { position: absolute; background: plum; width: 70px; height: 70px; z-index: 1; }
<section>
  <div style="transform: translate(0px, 0px)"></div>
</section>

© www.soinside.com 2019 - 2024. All rights reserved.