Skip to content

Drag and Scale

Operate elements to move within the parent container and perform scaling.

Installation

INFO

If you need to use other components, please refer toFull Components Installation

To install this component individually, run the following command:

shell
npm install @havue/drag-and-scale --save
shell
yarn add @havue/drag-and-scale
shell
pnpm install @havue/drag-and-scale

Import

vue
<script>
import { HvDragAndScale } from 'havue'
// or 
import { HvDragAndScale } from '@havue/components'
// or
import { HvDragAndScale } from '@havue/color-picker'
</script>

Examples

Set container actual dimensions to 1920x1080.

The first black element limits minimum size to 64x64, maintains aspect ratio, and restricts movement within the container.

The second gray element limits minimum size to 128x128 and maximum size to 512x300.

min: 64*64
keepRatio: true
inContaienr: true
min: 128*128
max: 512*300
keepRatio: false
inContaienr: false
Click to view code
vue
<template>
  <div class="drag-area" ref="containerRef">
    <DragAndScale
      :container="containerRef"
      :containerRealSize="containerRealSize"
      :keepRatio="{
        enable: true,
        scaleCase: 'min'
      }"
      :limit="{ minWidth: 64, minHeight: 64 }"
      :disabled="false"
      class="drag-box"
      @change="handleChange"
      :style="dragStyle"
    >
      <div class="inner-box">
        <div>min: 64*64</div>
        <div>keepRatio: true</div>
        <div>inContaienr: true</div>
      </div>
    </DragAndScale>
    <DragAndScale
      :container="containerRef"
      :containerRealSize="containerRealSize"
      :keepRatio="{
        enable: false,
        scaleCase: 'min'
      }"
      :limit="{ inContainer: false, minWidth: 128, minHeight: 128, maxWidth: 512, maxHeight: 300 }"
      :disabled="false"
      class="drag-box"
      @change="handleChange2"
      :style="dragStyle2"
    >
      <div class="inner-box">
        <div>min: 128*128</div>
        <div>max: 512*300</div>
        <div>keepRatio: false</div>
        <div>inContaienr: false</div>
      </div>
    </DragAndScale>
  </div>
</template>
ts
<script setup lang="ts">
import type { DragAndScaleChangeResultType } from '@havue/drag-and-scale'
import { ref, computed } from 'vue'
// import { HvDragAndScale as DragAndScale } from '@havue/drag-and-scale'
import { HvDragAndScale as DragAndScale } from '@havue/components'
const containerRef = ref()

const dragPosition = ref({
  x: 50,
  y: 50,
  width: 100,
  height: 50
})

const dragPosition2 = ref({
  x: 230,
  y: 50,
  width: 100,
  height: 50
})

const containerRealSize = ref({ width: 1920, height: 1080 })

const dragStyle = computed(() => {
  return {
    top: `${dragPosition.value.y}px`,
    left: `${dragPosition.value.x}px`,
    width: `${dragPosition.value.width}px`,
    height: `${dragPosition.value.height}px`
  }
})

const dragStyle2 = computed(() => {
  return {
    top: `${dragPosition2.value.y}px`,
    left: `${dragPosition2.value.x}px`,
    width: `${dragPosition2.value.width}px`,
    height: `${dragPosition2.value.height}px`,
    background: 'gray'
  }
})

function handleChange(params: DragAndScaleChangeResultType) {
  Object.assign(dragPosition.value, {
    x: params.elX,
    y: params.elY,
    width: params.elWidth,
    height: params.elHeight
  })
  console.log(params)
}

function handleChange2(params: DragAndScaleChangeResultType) {
  Object.assign(dragPosition2.value, {
    x: params.elX,
    y: params.elY,
    width: params.elWidth,
    height: params.elHeight
  })
  console.log(params)
}
</script>
scss
<style lang="scss" scoped>
.drag-area {
  position: relative;
  box-sizing: border-box;
  width: 100%;
  height: 400px;
  overflow: hidden;
  background-color: rgb(71 121 105);

  .drag-box {
    position: absolute;
    background-color: rgb(26 24 24);

    .inner-box {
      width: 100%;
      height: 100%;
      overflow: hidden;
      white-space: nowrap;
      user-select: none;
    }
  }
}
</style>

To disable scaling while keeping dragging, add these styles:

css
  .hv-drag-and-scale {
    --scale-area-width: 0px;
    border: none;
  }

To disable dragging while keeping scaling, add these styles:

scss
  .hv-drag-and-scale {
    .hv-drag-and-scale__area-center {
      pointer-events: none;
    }
  }

Props

TIP

Properties marked with '?' are optional.

PropertyDescriptionTypeDefault
containerContainer elementHTMLElement | Ref<HTMLElement>
containerRealSize?Actual physical dimensions of containerobject
containerRealSize.widthActual physical widthnumber
containerRealSize.heightActual physical heightnumber
keepRatio?Aspect ratio configurationobject
keepRatio.enableWhether to maintain aspect ratiobooleanfalse
keepRatio?.scaleCaseUse min/max delta when scaling'min' | 'max''min'
limit?Size constraintsobject
limit?.inContainerRestrict within parentbooleantrue
limit?.minWidthMinimum width limitnumber0
limit?.minHeightMinimum height limitnumber0
limit?.maxWidthMaximum width limitnumberInfinity
limit?.maxHeightMaximum height limitnumberInfinity
disabled?Disable interactionbooleanfalse

Events

EventDescriptionParameters
changeTriggered during drag/scale(params: DragAndScaleChangeResultType) => void
finishTriggered after drag/scale ends() => void
ts
type DragAndScaleChangeResultType {
  /** Operation type */
  type: 'move' | 'scale'
  /** Horizontal distance moved compared to last change event */
  deltaX: number
  /** Vertical distance moved compared to last change event */
  deltaY: number
  /** Element X position in container */
  elX: number
  /** Element Y position in container */
  elY: number
  /** Element width */
  elWidth: number
  /** Element height */
  elHeight: number
  /** Actual X coordinate converted via containerRealSize */
  realX: number
  /** Actual Y coordinate converted via containerRealSize */
  realY: number
  /** Actual width converted via containerRealSize */
  realWidth: number
  /** Actual height converted via containerRealSize */
  realHeight: number
}

Slots

SlotsDescription
defaultDefault content