Moveable Documentation

repository·master·Indexed 27 days ago

https://github.com/daybrush/moveable

A versatile library for performing transformations on HTML and SVG web elements, including dragging, resizing, scaling, rotating, warping, and pinching. It supports 3D transforms and provides dedicated packages for React (react-moveable), Vue 2 (vue-moveable), Vue 3 (vue3-moveable), Angular (ngx-moveable), and Lit (lit-moveable). Key features include groupable targets, snapping to guidelines, clipping, and the ability to implement custom controls via the Able interface.

Tokens
19.3K
Snippets
32
Records
83
Agent score
95%

What's inside Moveable

  1. Overview of Moveable features

    master

    Moveable provides a comprehensive set of transformation tools for web elements, including:

    • Draggable: Drag and move targets.
    • Resizable: Adjust target width and height.
    • Scalable: Scale target x and y via transform.
    • Rotatable: Rotate the target.
    • Warpable: Warp, distort, or bend the target.
    • Pinchable: Pinch targets with support for dragging, resizing, scaling, and rotating.
    • Groupable: Move multiple targets together as a group.
    • Snappable: Snap targets to guidelines.
    • OriginDraggable: Drag the origin point.
    • Clippable: Clip the target.
    • Roundable: Show and drag/double-click border-radius.

    Moveable supports SVG elements (svg, path, line, ellipse, g, rect, etc.), major browsers, and 3D transforms.

  2. Moveable features overview

    master

    The vue3-moveable component provides a wide range of manipulation capabilities:

    • Draggable: Drag and move targets.
    • Resizable: Change target width and height.
    • Scalable: Scale target x and y via transform.
    • Rotatable: Rotate the target.
    • Warpable: Distort or bend the target.
    • Pinchable: Combine draggable, resizable, scalable, and rotatable via pinching.
    • Groupable: Move multiple targets as a group.
    • Snappable: Snap targets to guidelines.
    • OriginDraggable: Drag from the origin.
    • Clippable: Clip the target.
    • Roundable: Show and drag/double-click border-radius.

    It supports SVG elements (svg, path, line, ellipse, g, rect, etc.), major browsers, and 3D transforms.

  3. Features of Angular Moveable

    master

    Angular Moveable supports a wide range of manipulation features:

    • Draggable: Move targets.
    • Resizable: Change target width and height.
    • Scalable: Scale target x and y via transform.
    • Rotatable: Rotate the target.
    • Warpable: Distort or bend the target.
    • Pinchable: Combine dragging, resizing, scaling, and rotating via pinching.
    • Groupable: Move multiple targets as a group.
    • Snappable: Snap to guidelines.
    • OriginDraggable: Drag the origin.
    • Clippable: Clip the target.
    • Roundable: Show and drag/double-click border-radius.

    Additional Support:

    • SVG Elements (svg, path, line, ellipse, g, rect, etc.)
    • Major Browsers
    • 3D Transforms
  4. Vue Moveable Features

    master

    Vue Moveable provides the following transformation and interaction capabilities:

    • Draggable: Drag and move targets.
    • Resizable: Increase or decrease target width and height.
    • Scalable: Scale target x and y via transform.
    • Rotatable: Rotate the target.
    • Warpable: Distort or bend the target.
    • Pinchable: Combine draggable, resizable, scalable, and rotatable via pinch gestures.
    • Groupable: Move multiple targets in a group.
    • Snappable: Snap targets to guidelines.
    • OriginDraggable: Drag the origin of the target.
    • Clippable: Clip the target.
    • Roundable: Show and drag or double-click border-radius.

    Additional Support:

    • SVG Elements (svg, path, line, ellipse, g, rect, etc.)
    • Major Browsers
    • 3D Transforms
  5. Use Groupable with preact-moveable

    master

    The Groupable feature in preact-moveable allows multiple targets to be moved, resized, scaled, rotated, or pinched as a single group. To enable group operations, pass an array of elements to the target prop instead of a single element.

    Key features include:

    • draggable: Move the group.
    • resizable: Resize the group (Note: only one of resizable, scalable, or warpable can be used at a time).
    • scalable: Scale the group.
    • rotatable: Rotate the group.
    • pinchable: Enables pinch gestures which can trigger drag, rotate, scale, or resize group events.
    • keepRatio: When true, maintains the width/height ratio during resize or scale operations.
    import Moveable from "preact-moveable";
    
    // Inside your render function
    <Moveable
        /* multiple targets */
        target={[].slice.call(document.querySelectorAll(".target"))}
        container={null}
        origin={true}
    
        /* draggable */
        draggable={true}
        onDragGroupStart={({ targets }) => {
            console.log("onDragGroupStart", targets);
        }}
        onDragGroup={({ targets, events }) => {
            events.forEach(ev => {
                ev.target!.style.transform = ev.transform;
            });
        }}
        onDragGroupEnd={({ targets, isDrag, clientX, clientY }) => {
            console.log("onDragGroupEnd", targets, isDrag);
        }}
    
        /* resizable */
        resizable={true}
        keepRatio={true}
        onResizeGroupStart={({ targets, clientX, clientY }) => {
            console.log("onResizeGroupStart", targets);
        }}
        onResizeGroup={({ targets, direction }) => {
            // Handle resize logic
        }}
        onResizeGroupEnd={({ targets, isDrag, clientX, clientY }) => {
            console.log("onResizeGroupEnd", targets, isDrag);
        }}
    
        /* scalable */
        scalable={true}
        onScaleGroupStart={({ targets, clientX, clientY }) => {
            console.log("onScaleGroupStart", targets);
        }}
        onScaleGroup={({ targets, events }) => {
            events.forEach(ev => {
                const target = ev.target;
                target!.style.transform = ev.transform;
            });
        }}
        onScaleGroupEnd={({ targets, isDrag, clientX, clientY }) => {
            console.log("onScaleGroupEnd", targets, isDrag);
        }}
    
        /* rotatable */
        rotatable={true}
        onRotateGroupStart={({ targets, clientX, clientY }) => {
            console.log("onRotateGroupStart", targets);
        }}
        onRotateGroup={({ targets, events }) => {
            // Handle rotation logic
        }}
        onRotateGroupEnd={({ targets, isDrag, clientX, clientY }) => {
            console.log("onRotateGroupEnd", targets, isDrag);
        }}
    
        /* pinchable */
        pinchable={true}
        onPinchGroupStart={({ targets, clientX, clientY, datas }) => {
            console.log("onPinchGroupStart");
        }}
        onPinchGroup={({ targets, clientX, clientY, datas }) => {
            console.log("onPinchGroup");
        }}
        onPinchGroupEnd={({ isDrag, targets, clientX, clientY, datas }) => {
            console.log("onPinchGroupEnd");
        }}
    />
  6. Use lit-moveable in a Lit application

    master

    Import lit-moveable to register the <lit-moveable> custom element. When using the component, note the following naming conventions:

    • Event names are prefixed with lit (e.g., litDragStart, litDrag).
    • Properties related to the moveable functionality are prefixed with lit (e.g., .litMoveable).
    • Method names (if accessed via detail) are prefixed with lite (e.g., litDragStart).

    Example usage with lit-html:

    import "lit-moveable";
    import { render, html } from "lit-html";
    
    let translate = [0, 0];
    
    render(html`
    <div class="target" style="width: 200px;height: 100px;">Target</div>
    <lit-moveable
        .target=${".target"}
        .litMoveable=${true}
        .resizable=${true}
        @litDragStart=${({ detail: e }) => {
            e.set(translate);
        }}
        @litDrag=${({ detail: e }) => {
            e.target.style.transform = t`translate(${e.beforeTranslate[0]}px, ${e.beforeTranslate[1]}px)`;
            translate = e.beforeTranslate;
        }}
        @litResizeStart=${({ detail: e }) => {
            e.dragStart && e.dragStart.set(translate);
        }}
        @litResize=${({ detail: e }) => {
            const beforeTranslate = e.drag.beforeTranslate;
    
            e.target.style.width = `${e.width}px`;
            e.target.style.height = `${e.height}px`;
            e.target.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`;
            translate = beforeTranslate;
        }}
    />
    `);
    import "lit-moveable";
    import { render, html } from "lit-html";
    
    let translate = [0, 0];
    
    render(html`
    <div class="target" style="width: 200px;height: 100px;">Target</div>
    <lit-moveable
        .target=${".target"}
        .litMoveable=${true}
        .resizable=${true}
        @litDragStart=${({ detail: e }) => {
            e.set(translate);
        }}
        @litDrag=${({ detail: e }) => {
            e.target.style.transform = `translate(${e.beforeTranslate[0]}px, ${e.beforeTranslate[1]}px)`;
            translate = e.beforeTranslate;
        }}
        @litResizeStart=${({ detail: e }) => {
            e.dragStart && e.dragStart.set(translate);
        }}
        @litResize=${({ detail: e }) => {
            const beforeTranslate = e.drag.beforeTranslate;
    
            e.target.style.width = `${e.width}px`;
            e.target.style.height = `${e.height}px`;
            e.target.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`;
            translate = beforeTranslate;
        }}
    />
    `);
  7. Configure ngx-moveable in an Angular Module

    master

    Import NgxMoveableModule and NgxMoveableComponent into your Angular module to make the Moveable component available for use.

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { NgxMoveableModule, NgxMoveableComponent } from '../ngx-moveable';
    
    @NgModule({
      declarations: [
        AppComponent,
        NgxMoveableComponent,
      ],
      imports: [
        BrowserModule,
        // NgxMoveableModule,
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
  8. Understand Moveable Event Sequences

    master

    Moveable events follow a specific lifecycle sequence. For any action (like dragging), events are triggered in three main stages: start, during, and end. Each stage has a beforeRender prefix (triggered before calculations) and a render prefix (triggered after values like size, position, or CSS are updated).

    Draggable Sequence:

    • dragStart: beforeRenderStart => dragStart => renderStart
    • drag: beforeRender => drag => render
    • dragEnd: beforeRenderEnd => dragEnd => renderEnd

    Resizable Sequence:

    • resizeStart: beforeRenderStart => resizeStart => renderStart
    • resize: beforeRender => beforeResize => resize => render
    • resizeEnd: beforeRenderEnd => resizeEnd => renderEnd