{"id":13447763,"url":"https://github.com/nichollascarter/subjx","last_synced_at":"2025-04-05T05:06:28.198Z","repository":{"id":42233512,"uuid":"147208812","full_name":"nichollascarter/subjx","owner":"nichollascarter","description":"Drag/Resize/Rotate Javascript library","archived":false,"fork":false,"pushed_at":"2023-11-05T07:41:45.000Z","size":3366,"stargazers_count":207,"open_issues_count":18,"forks_count":40,"subscribers_count":9,"default_branch":"staging","last_synced_at":"2024-04-24T16:10:39.085Z","etag":null,"topics":["drag","javascript","no-dependencies","resize","rotate","snap","svg","vanilla-javascript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nichollascarter.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-09-03T13:28:44.000Z","updated_at":"2024-04-17T02:46:13.000Z","dependencies_parsed_at":"2024-01-14T04:59:43.653Z","dependency_job_id":"8ad68b9e-c696-4c8e-826b-7e234438cb2d","html_url":"https://github.com/nichollascarter/subjx","commit_stats":{"total_commits":185,"total_committers":3,"mean_commits":"61.666666666666664","dds":0.0972972972972973,"last_synced_commit":"e7421e13000aac87c0af1e537ad61ef58ae752fb"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichollascarter%2Fsubjx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichollascarter%2Fsubjx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichollascarter%2Fsubjx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichollascarter%2Fsubjx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nichollascarter","download_url":"https://codeload.github.com/nichollascarter/subjx/tar.gz/refs/heads/staging","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247289427,"owners_count":20914464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["drag","javascript","no-dependencies","resize","rotate","snap","svg","vanilla-javascript"],"created_at":"2024-07-31T05:01:26.307Z","updated_at":"2025-04-05T05:06:28.155Z","avatar_url":"https://github.com/nichollascarter.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003ch2 align=\"middle\"\u003e\r\n    Subjx(dragging/resizing/rotating)\r\n\u003c/h2\u003e\r\n\r\n\u003cp align=\"center\"\u003e\r\n    \u003cimg src=\"https://raw.githubusercontent.com/nichollascarter/subjx/master/examples/demo.gif\"\u003e\r\n\u003c/p\u003e\r\n\r\n\u003ch3 align=\"middle\"\u003e\r\n    Draggable, Resizable, Rotatable library for creating drag-n-drop applications.\r\n\u003c/h3\u003e\r\n\r\n## Demos\r\n\r\n### [Basic example](http://jsfiddle.net/nichollascarter/qgwzch0v/)\r\n\r\n### [Drag, zoom and pan SVG](https://codesandbox.io/s/svg-drag-pan-zoom-wb95s)\r\n\r\n## Usage\r\n\r\nLibrary provides dragging/resizing/rotating/snapping SVG/HTML Elements.\r\n\r\n## Installation\r\n\r\nRun `npm install` to install with `npm`.\r\n\r\n```\r\nnpm install subjx\r\n```\r\n\r\nIncluding via a `\u003cscript\u003e` tag:\r\n\r\n```html\r\n\u003cscript src=\"../dist/js/subjx.js\"\u003e\u003c/script\u003e\r\n```\r\n\r\n## Get started\r\n\r\n Main function `subjx` returns `Subjx` instance which based on elements finded by\r\n passed parameters:\r\n\r\n```javascript\r\nimport subjx from 'subjx';\r\nimport 'subjx/dist/style/subjx.css';\r\n\r\n// possible parameters\r\nconst xElem = subjx( 'selector' ) |\r\n                subjx( element ) |\r\n                subjx( elementArray );\r\n```\r\n\r\n## Transformation(drag/resize/rotate)\r\n\r\n```javascript\r\n// enabling tool by `drag` method with the optional parameters\r\n// by default just call `.drag()`\r\nconst xDraggable = xElem.drag();\r\n\r\n// for disabling use `disable` method for each object\r\nxDraggable.disable();\r\n```\r\n\r\n\r\n### \"Draggable\" API\r\n\r\n```javascript\r\n// getter returns root DOM element of 'controls'\r\nxDraggable.controls;\r\n\r\n// provides access to useful options\r\nxDraggable.storage;\r\n// for example: to get reference to any handle's DOM\r\nconst {\r\n  handles: { tl, tr, ...etc }\r\n} = xDraggable.storage;\r\n\r\n// enables dragging\r\n// there is no need to call this method manually\r\nxDraggable.enable(options);\r\n\r\n// disables dragging, removes controls and handles\r\nxDraggable.disable();\r\n\r\n // adds event listener for some events\r\nxDraggable.on(eventName, cb);\r\n\r\n// removes event listener for some events\r\nxDraggable.off(eventName, cb);\r\n\r\n// Event names\r\nconst EVENTS = [\r\n    'dragStart',\r\n    'drag',\r\n    'dragEnd',\r\n    'resizeStart',\r\n    'resize',\r\n    'resizeEnd',\r\n    'rotateStart',\r\n    'rotate',\r\n    'rotateEnd'\r\n];\r\n\r\n// execute dragging manually\r\nxDraggable.exeDrag({\r\n    dx, // drag along the x axis\r\n    dy // drag along the y axis\r\n});\r\n\r\n// execute resizing manually\r\nxDraggable.exeResize({\r\n    dx, // resize along the x axis\r\n    dy, // resize along the y axis\r\n    revX, // reverse resizing along the x axis\r\n    revY, // reverse resizing along the y axis\r\n    doW, // allow width resizing\r\n    doH  // allow height resizing\r\n});\r\n\r\n// execute rotating manually\r\nxDraggable.exeRotate({\r\n    delta // radians\r\n});\r\n\r\n// Align element inside container: ['t', 'l', 'r', 'b', 'v', 'h']\r\nxDraggable.applyAlignment('tr');\r\n\r\n// Call this method when applying scale or viewBox values changing\r\n// useful when element's container was transformed from outside\r\nxDraggable.fitControlsToSize();\r\n\r\n// Sets the origin for an element's transformations\r\nxDraggable.setTransformOrigin(\r\n    {\r\n        x, // absolute the origin's position x coordinate\r\n        y, // absolute he origin's position y coordinate\r\n        dx, // offset the origin's position x coordinate\r\n        dy // offset the origin's position y coordinate\r\n    },\r\n    pin // leaves current origin fixed if true or not if false\r\n);\r\n\r\n// Sets transform origin to default\r\nxDraggable.resetTransformOrigin();\r\n\r\n// Returns element's current dimensions\r\nxDraggable.getDimensions();\r\n```\r\n\r\n### Options\r\n\r\n|Property|Description|Type|Default|\r\n|--|--|--|--|\r\n| **container** | Transformation coordinate system | `'selector'` \\| `element` | element.parentNode |\r\n| **controlsContainer** | Parent element of 'controls' | `'selector'` \\| `element` | element.parentNode |\r\n| **axis** | Constrain movement along an axis | `string`: 'x' \\| 'y' \\| 'xy' | 'xy' |\r\n| **snap** | Snapping to grid in pixels/radians | `object` | { x: 10, y: 10, angle: 10 } |\r\n| **each** | Mimic behavior with other '.draggable' elements | `object` | { move: false, resize: false, rotate: false } |\r\n| **proportions** | Keep aspect ratio on resizing / scaling | `boolean` | false |\r\n| **draggable** | Allow or deny an action | `boolean` | true |\r\n| **resizable** | Allow or deny an action | `boolean` | true |\r\n| **rotatable** | Allow or deny an action | `boolean` | true |\r\n| **scalable** | Applies scaling only to root element | `boolean` | false |\r\n| **restrict** | Restricts element dragging/resizing/rotation | `'selector'` \\| `element` | - |\r\n| **rotatorAnchor** | Rotator anchor direction | `string`: 'n' \\| 's' \\| 'w' \\| 'e' | 'e' |\r\n| **rotatorOffset** | Rotator offset  | `number` | 50 |\r\n| **transformOrigin** | Sets the origin for an element's transformations | `boolean` \\| Array\u003cnumber\u003e | false |\r\n\r\n#### Notice: In most cases, it is recommended to use 'proportions' option\r\n\r\n### Methods\r\n\r\n```javascript\r\nsubjx('.draggable').drag({\r\n    onInit(elements) {\r\n        // fires on tool activation\r\n    },\r\n    onMove({ clientX, clientY, dx, dy, transform }) {\r\n        // fires on moving\r\n    },\r\n    onResize({ clientX, clientY, dx, dy, transform, width, height }) {\r\n        // fires on resizing\r\n    },\r\n    onRotate({ clientX, clientY, delta, transform }) {\r\n        // fires on rotation\r\n    },\r\n    onDrop({ clientX, clientY }) {\r\n        // fires on drop\r\n    },\r\n    onDestroy(el) {\r\n        // fires on tool deactivation\r\n    }\r\n});\r\n```\r\n\r\nSubscribing new draggable element to previously activated(useful with `each` option)\r\n\r\n```javascript\r\nconst options = {};\r\nconst observable = subjx.createObservable();\r\nsubjx('.draggable').drag(options, observable);\r\n\r\n// pass Observable to new element\r\nconst createDraggableAndSubscribe = e =\u003e {\r\n    subjx(e.target).drag(options, observable);\r\n};\r\n```\r\n\r\nAllowed SVG elements:\r\n`g`, `path`, `rect`, `ellipse`, `line`, `polyline`, `polygon`, `circle`\r\n\r\n## Cloning\r\n\r\n### Options\r\n\r\n```javascript\r\nconst xCloneable = xElem.clone({\r\n    // dropping area\r\n    stack: 'selector',\r\n    // set clone parent\r\n    appendTo: 'selector',\r\n    // set clone additional style\r\n    style: {\r\n        border: '1px dashed green',\r\n        background: 'transparent'\r\n    }\r\n});\r\n```\r\n\r\n### Methods\r\n\r\n```javascript\r\nsubjx('.cloneable').clone({\r\n    onInit(el) {\r\n        // fires on tool activation\r\n    },\r\n    onMove(dx, dy) {\r\n        // fires on moving\r\n    },\r\n    onDrop(e) {\r\n        // fires on drop\r\n    },\r\n    onDestroy() {\r\n        // fires on tool deactivation\r\n    }\r\n});\r\n```\r\n\r\nDisabling\r\n\r\n```javascript\r\nxCloneable.disable();\r\n```\r\n\r\n## License\r\n\r\nMIT (c) Karen Sarksyan\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichollascarter%2Fsubjx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnichollascarter%2Fsubjx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichollascarter%2Fsubjx/lists"}