为什么我的可拖动苗条在缩放后无法正常工作?



我已经创建了一个细长的组件来允许拖动Dom元素:

<script>
export let posX = 0
export let posY = 0
let moving = false
let offsetX
let offsetY
function dragStart(e) {
const rect = e.currentTarget.getBoundingClientRect()
offsetX = e.pageX - rect.left
offsetY = e.pageY - rect.top
moving = true
}
function dragStop() {
moving = false
}
function dragMove(e) {
if (moving) {
posX = e.pageX - offsetX
posY = e.pageY - offsetY
}
}
</script>
<style>
.draggable {
user-select: none;
position: absolute;
cursor: grab;
}
.draggable:active {
cursor: grabbing;
}
</style>
<svelte:window on:mouseup={dragStop} on:mousemove={dragMove} />
<div
on:mousedown={dragStart}
style="top: {posY}px; left: {posX}px;"
class="draggable"
>
<slot/>
</div>

当我将CSS属性transform: scale(0.5);添加到包含可拖动组件的div时,可拖动组件停止按预期工作。它们的位置从鼠标位置偏移。

<script>
import Draggable from "./Draggable.svelte"
</script>
<style>
.box {
background: red;
width: 150px;
height: 150px;
}

.container {
transform: scale(0.5);
}
</style>
<div class="container">
<Draggable>
<div class="box"/>
</Draggable>

<Draggable posY={250}>
<div class="box"/>
</Draggable>
</div>

这里是一个链接到简洁的REPL: https://svelte.dev/repl/679692b94afc48b48a2a3ebd39875ea0?version=3.42.5

我该如何解决这个问题?

提前感谢!

当您缩小容器时,会发生两件事:

  1. 容器的大小变得小于视口,导致鼠标位置的偏移未被纠正。
  2. top/leftCSS属性的单位现在是一半大,这也没有纠正。

要解决这个问题,我们必须计算父容器相对于视口的偏移量,并将该值传递给<Draggable>组件。我们还需要传入我们正在使用的比例值。

<!-- App.svelte -->
<script>
import {onMount} from "svelte"
import Draggable from "./Draggable.svelte"

let parent;
let parentOffset = {x: 0, y:0}

onMount(() => {
let rect = parent.getBoundingClientRect()
parentOffset = {x: rect.x, y: rect.y}
})
</script>
<style>
.box {
background: red;
width: 150px;
height: 150px;
}

.container {
transform: scale(0.5);
}
</style>
<div class="container" bind:this={parent}>
<Draggable {parentOffset} scale={0.5}>
<div class="box"/>
</Draggable>

<Draggable posY={250} {parentOffset} scale={0.5}>
<div class="box"/>
</Draggable>
</div>
<!-- Draggable.svelte -->
<script>
export let posX = 0
export let posY = 0

export let parentOffset;
export let scale;
let moving = false
let offsetX
let offsetY
function dragStart(e) {
const rect = e.currentTarget.getBoundingClientRect()
offsetX = e.pageX - rect.left
offsetY = e.pageY - rect.top
moving = true
}
function dragStop() {
moving = false
}
function dragMove(e) {
if (moving) {
// new math! we subtract the parent offset to correct the parent shift
// and also divide by the scale to correct the scale multiplication
posX = ((e.pageX - offsetX)-parentOffset.x)/scale
posY = ((e.pageY - offsetY)-parentOffset.y)/scale
}
}
</script>
<style>
.draggable {
user-select: none;
position: absolute;
cursor: grab;
}
.draggable:active {
cursor: grabbing;
}
</style>
<svelte:window on:mouseup={dragStop} on:mousemove={dragMove} />
<div
on:mousedown={dragStart}
style="top: {posY}px; left: {posX}px;"
class="draggable"
>
<slot/>
</div>

新增REPL: https://svelte.dev/repl/9ec1a1598e8f407e8ec807dbb8a4d92b?version=3.42.5

最新更新