Skip to content

useDraggable

适用于 Vue3Nuxt3HTML

使元素可拖动

示例

基础示例

拖着我满世界跑吧

offsetX: 0 offsetY: 0

点击召回

查看代码
vue
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { useDraggable } from "@pureadmin/utils";

const targetRef = ref();
const dragRef = ref();

const { dragging, transform, init, reset } = useDraggable(targetRef, dragRef);
// 初始化开启拖动功能
init();

let info = computed(() => {
  return `offsetX: ${Math.round(transform.offsetX)} offsetY: ${Math.round(
    transform.offsetY
  )}`;
});

watch(
  () => dragging.value,
  val => {
    val ? console.log("正在拖动") : console.log("停止拖动");
  }
);
</script>

<template>
  <div
    ref="targetRef"
    class="pure-target"
    :style="{ zIndex: transform.offsetX === 0 ? 0 : 999 }"
  >
    <div ref="dragRef" class="pure-drag">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="88"
        height="88"
        viewBox="0 0 1024 1024"
      >
        <path
          fill="#3451b2"
          d="M119.026 584.87a43.651 43.651 0 1 0-43.651-43.652 43.651 43.651 0 0 0 43.651 43.652M945.487 45.633a32.01 32.01 0 0 0-58.201-27.064L694.348 465.848a183.917 183.917 0 0 1 58.201 25.026zM645.46 511.245c-51.218 0-68.096 34.048-140.557 89.339a475.215 475.215 0 0 1-254.923 90.794c-85.265 4.365-217.091 0-229.896 12.805s26.191 123.387 127.17 191.483c58.202 38.704 200.214 136.191 332.04 127.752 213.018-13.677 255.505-174.605 268.31-229.896a838.102 838.102 0 0 0 12.804-203.705c-4.365-51.8-55.292-77.117-114.948-77.117zm-12.805 396.061c-119.895 116.403-229.896 63.73-229.896 63.73l138.229-95.159-224.076 58.202-64.021-38.413 171.694-48.89-235.425 10.477-12.804-25.609 160.927-43.07-199.34 17.752-67.223-63.73a1504.51 1504.51 0 0 0 293.626-25.609 478.707 478.707 0 0 0 166.166-76.535l166.165 76.535a207.488 207.488 0 0 1-64.022 191.483zM948.398 584.87a58.202 58.202 0 1 0 58.201 58.201 58.202 58.202 0 0 0-58.201-58.201m-87.303 261.906a29.1 29.1 0 1 0 29.101 29.101 29.1 29.1 0 0 0-29.1-29.1zM308.181 555.77a29.1 29.1 0 1 0-29.1-29.1 29.1 29.1 0 0 0 29.1 29.1"
        />
      </svg>
      <p>拖着我满世界跑吧</p>
      <p>{{ info }}</p>
    </div>
    <p class="pure-reset" title="复位" @click="reset">点击召回</p>
  </div>
</template>

<style scoped>
.pure-target {
  position: relative;
  width: 15em;
  height: 15em;
  display: flex;
  align-items: center;
  overflow: hidden;
  justify-content: center;
  color: var(--vp-c-brand);
  border-radius: 0.5em;
  background-color: var(--vp-custom-block-tip-bg);
  border: 1px solid var(--vp-custom-block-tip-border);
}

.pure-reset {
  cursor: pointer;
  position: absolute;
  bottom: -10px;
  right: 10px;
}

.pure-reset:hover {
  color: var(--vp-c-text-1);
}

.pure-drag {
  text-align: center;
}

.pure-drag svg {
  margin: 0 auto;
}
</style>

可拖动的 naiveui模态框

基础用法
查看代码
vue
<script setup lang="ts">
import { ref } from "vue";
import { useDraggable } from "@pureadmin/utils";

const targetRef = ref();
const dragRef = ref();
let showModal = ref(false);

const { init } = useDraggable(targetRef, dragRef);

function onOpenModal() {
  showModal.value = true;
  init();
}
</script>

<template>
  <naive-theme>
    <n-button @click="onOpenModal"> 点击打开模态框 </n-button>
    <n-modal v-model:show="showModal">
      <div ref="targetRef">
        <n-card
          style="width: 400px"
          title="模态框"
          :bordered="false"
          size="huge"
          role="dialog"
          aria-modal="true"
        >
          <template #header>
            <div ref="dragRef">拖动我吧</div>
          </template>
          emm...不知道写点啥 🤷
        </n-card>
      </div>
    </n-modal>
  </naive-theme>
</template>
使用 Dialog 预设

哈哈,你没有看错,就是如此简单

查看代码
vue
<script setup lang="ts">
import { ref } from "vue";
import { useDraggable } from "@pureadmin/utils";

let showModal = ref(false);

const { draggable, init, close, reset, open } = useDraggable(
  ".n-dialog",
  ".n-dialog__title"
);

function onOpenDialog() {
  showModal.value = true;
  init();
}
</script>

<template>
  <naive-theme>
    <n-button @click="onOpenDialog"> 点击打开模态框 </n-button>
    <n-modal v-model:show="showModal" preset="dialog" :maskClosable="false">
      <template #header> 拖动我吧 </template>
      <div>
        <p>naiveui:我暴露了足够的api,怎么会难用呢?🤔</p>
        <p>二开疯子:确实,这下很多组件都能更好地二次封装了 😄</p>
        <p>拷贝高手:好咧,赶紧动起来!👍</p>
      </div>
      <template #action>
        <n-button @click="reset">复位</n-button>
        <n-button @click="close" v-if="draggable">关闭拖动</n-button>
        <n-button @click="open" v-else>开启拖动</n-button>
      </template>
    </n-modal>
  </naive-theme>
</template>

最简代码

可拖动的Div

vue
<script setup lang="ts">
import { ref } from "vue";
import { useDraggable } from "@pureadmin/utils";

const targetRef = ref();
const dragRef = ref();

const { init } = useDraggable(targetRef, dragRef);
// 初始化开启拖动功能
init();
</script>

<template>
  <div ref="targetRef">
    <div ref="dragRef">
      <!-- 内容区 -->
    </div>
  </div>
</template>

API

参数

ts
//  在此处配置参数
const {} = useDraggable(targetRef, dragRef, args);
参数属性必传说明类型
targetRef要拖动的元素。可以是获取DOM元素或组件实例引用的ref,也可以是class类名(如:".target")或元素ID(如:"#target"Ref<HTMLElement>/string
dragRef拖动的地方。可以是获取DOM元素或组件实例引用的ref,也可以是class类名(如:".drag")或元素ID(如:"#drag"Ref<HTMLElement>/string
args额外的可选参数,具体看下面的args详情ArgsDraggable
args 详情

对象格式,拥有下面两个属性

参数属性说明类型默认值
dragRefStyle为了方便用户识别可拖动的区域,添加额外样式到dragRef上。可以使用{}空对象清空默认样式,也可以自定义样式CSSProperties{ cursor: "move", userSelect: "none" }
resize当页面resize时,如果拖动的元素超出新的视口边界,是否将其恢复到初始位置。true:代表恢复到初始位置。false:代表不会恢复到初始位置。当然也可以填写resize时的防抖延迟时间,默认60毫秒boolean/numbertrue

返回值、方法

返回值、方法说明类型
draggable是否已经开启拖动功能(响应式)。true代表已开启拖动功能,false代表关闭了拖动功能Ref<boolean>
dragging是否正在拖动中(响应式)。true代表正在拖动,false代表没有拖动Ref<boolean>
transform响应式对象transform:包含当前被拖动元素的offsetXoffsetY信息{offsetX: number;offsetY: number;}
init初始化开启拖动功能() => void
open开启拖动功能。常用于当关闭拖动时,想再次开启拖动并在当前所处位置继续拖动() => void
close关闭拖动功能() => void
reset将拖动元素恢复到初始位置() => void

Released under the MIT License