├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── rollup.config.js └── src ├── FreeTransform.svelte ├── index.js └── vector.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /public/build/ 3 | /dist/ 4 | 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 @mononaut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # svelte-free-transform 2 | 3 | A freely user-transformable container component for Svelte. 4 | 5 | Wraps arbitrary content in a frame for users to drag, resize and rotate via handles or multi-touch gestures. 6 | 7 | [Try out a demo!](https://svelte.dev/repl/528b834fb07f4d1ea5de986e6c728efc?version=3.38.2) 8 | 9 | ## Installation 10 | 11 | ```bash 12 | npm install --save svelte-free-transform 13 | ``` 14 | 15 | 16 | ## Usage 17 | 18 | Wrap any components or markup in a `` element. The container element should be _positioned_. 19 | 20 | Set an initial position using the `position` prop. 21 | 22 | ```html 23 | 27 | 28 |
29 | 41 | 42 | 43 |
44 | 45 |
46 | 47 |
48 | 49 | 54 | ``` 55 | 56 | We can also wrap the `` element in another div (for example, if we want to apply Svelte animations), and instead transform that wrapper element: 57 | 58 | ```html 59 | 63 | 64 |
65 |
69 | 76 | 77 | 78 |
79 |
80 | 81 | 86 | ``` 87 | 88 | 89 | ## Props 90 | 91 | **Prop** | **Type** | **Possible Values** | **Default** 92 | ---|---|---|--- 93 | position | `{x, y, w, h, r, style }`| x, y, w, h = position, width and height in pixels. r = rotation in radians. style = css inline style string representing the applied transform | `{ x: 0, y: 0, w: 100, h: 100, r: 0 }` 94 | target | DOM Element | the element to transform | this element 95 | container | DOM Element | nearest positioned ancestor of the target element | immediate parent of the target element 96 | handleMode | String | 'resize' or 'rotate' | 'resize' 97 | rotatorEnabled | Boolean | Show a separate handle for rotation? | `false` 98 | rotatorBar | Boolean | Draw a line from the rotation handle to the frame? | `false` 99 | lockAspect | Boolean | Keep a fixed aspect ratio? | `false` 100 | lockTouchResize | Boolean | Allow resizing via multitouch gesture? | `false` 101 | 102 | ## Styling 103 | 104 | Style the frame border by overriding the --frameBorder CSS variable: 105 | 106 | 107 | 108 | ```html 109 | 114 | ``` 115 | 116 | 117 | ## License 118 | 119 | [MIT](LICENSE) 120 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-free-transform", 3 | "version": "1.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/polyfill": { 8 | "version": "7.12.1", 9 | "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", 10 | "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", 11 | "dev": true, 12 | "requires": { 13 | "core-js": "^2.6.5", 14 | "regenerator-runtime": "^0.13.4" 15 | } 16 | }, 17 | "@types/node": { 18 | "version": "15.12.2", 19 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", 20 | "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", 21 | "dev": true 22 | }, 23 | "balanced-match": { 24 | "version": "1.0.2", 25 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 26 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 27 | "dev": true 28 | }, 29 | "brace-expansion": { 30 | "version": "1.1.11", 31 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 32 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 33 | "dev": true, 34 | "requires": { 35 | "balanced-match": "^1.0.0", 36 | "concat-map": "0.0.1" 37 | } 38 | }, 39 | "builtin-modules": { 40 | "version": "3.2.0", 41 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", 42 | "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", 43 | "dev": true 44 | }, 45 | "camel-case": { 46 | "version": "3.0.0", 47 | "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", 48 | "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", 49 | "dev": true, 50 | "requires": { 51 | "no-case": "^2.2.0", 52 | "upper-case": "^1.1.1" 53 | } 54 | }, 55 | "clean-css": { 56 | "version": "4.2.3", 57 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", 58 | "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", 59 | "dev": true, 60 | "requires": { 61 | "source-map": "~0.6.0" 62 | } 63 | }, 64 | "commander": { 65 | "version": "2.17.1", 66 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", 67 | "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", 68 | "dev": true 69 | }, 70 | "concat-map": { 71 | "version": "0.0.1", 72 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 73 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 74 | "dev": true 75 | }, 76 | "core-js": { 77 | "version": "2.6.12", 78 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", 79 | "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", 80 | "dev": true 81 | }, 82 | "fsevents": { 83 | "version": "2.3.2", 84 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 85 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 86 | "dev": true, 87 | "optional": true 88 | }, 89 | "function-bind": { 90 | "version": "1.1.1", 91 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 92 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 93 | "dev": true 94 | }, 95 | "has": { 96 | "version": "1.0.3", 97 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 98 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 99 | "dev": true, 100 | "requires": { 101 | "function-bind": "^1.1.1" 102 | } 103 | }, 104 | "he": { 105 | "version": "1.2.0", 106 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 107 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 108 | "dev": true 109 | }, 110 | "html-minifier": { 111 | "version": "3.5.21", 112 | "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", 113 | "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", 114 | "dev": true, 115 | "requires": { 116 | "camel-case": "3.0.x", 117 | "clean-css": "4.2.x", 118 | "commander": "2.17.x", 119 | "he": "1.2.x", 120 | "param-case": "2.1.x", 121 | "relateurl": "0.2.x", 122 | "uglify-js": "3.4.x" 123 | } 124 | }, 125 | "is-core-module": { 126 | "version": "2.4.0", 127 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", 128 | "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", 129 | "dev": true, 130 | "requires": { 131 | "has": "^1.0.3" 132 | } 133 | }, 134 | "is-module": { 135 | "version": "1.0.0", 136 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", 137 | "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", 138 | "dev": true 139 | }, 140 | "lower-case": { 141 | "version": "1.1.4", 142 | "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", 143 | "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", 144 | "dev": true 145 | }, 146 | "minimatch": { 147 | "version": "3.0.4", 148 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 149 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 150 | "dev": true, 151 | "requires": { 152 | "brace-expansion": "^1.1.7" 153 | } 154 | }, 155 | "no-case": { 156 | "version": "2.3.2", 157 | "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", 158 | "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", 159 | "dev": true, 160 | "requires": { 161 | "lower-case": "^1.1.1" 162 | } 163 | }, 164 | "param-case": { 165 | "version": "2.1.1", 166 | "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", 167 | "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", 168 | "dev": true, 169 | "requires": { 170 | "no-case": "^2.2.0" 171 | } 172 | }, 173 | "path-parse": { 174 | "version": "1.0.7", 175 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 176 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 177 | "dev": true 178 | }, 179 | "picomatch": { 180 | "version": "2.3.0", 181 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 182 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 183 | "dev": true 184 | }, 185 | "regenerator-runtime": { 186 | "version": "0.13.7", 187 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", 188 | "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", 189 | "dev": true 190 | }, 191 | "relateurl": { 192 | "version": "0.2.7", 193 | "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", 194 | "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", 195 | "dev": true 196 | }, 197 | "require-relative": { 198 | "version": "0.8.7", 199 | "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", 200 | "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", 201 | "dev": true 202 | }, 203 | "resolve": { 204 | "version": "1.20.0", 205 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 206 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 207 | "dev": true, 208 | "requires": { 209 | "is-core-module": "^2.2.0", 210 | "path-parse": "^1.0.6" 211 | } 212 | }, 213 | "rollup": { 214 | "version": "2.52.1", 215 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.1.tgz", 216 | "integrity": "sha512-/SPqz8UGnp4P1hq6wc9gdTqA2bXQXGx13TtoL03GBm6qGRI6Hm3p4Io7GeiHNLl0BsQAne1JNYY+q/apcY933w==", 217 | "dev": true, 218 | "requires": { 219 | "fsevents": "~2.3.2" 220 | } 221 | }, 222 | "rollup-plugin-css-only": { 223 | "version": "3.1.0", 224 | "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz", 225 | "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==", 226 | "dev": true, 227 | "requires": { 228 | "@rollup/pluginutils": "4" 229 | }, 230 | "dependencies": { 231 | "@rollup/pluginutils": { 232 | "version": "4.1.0", 233 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz", 234 | "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==", 235 | "dev": true, 236 | "requires": { 237 | "estree-walker": "^2.0.1", 238 | "picomatch": "^2.2.2" 239 | } 240 | }, 241 | "estree-walker": { 242 | "version": "2.0.2", 243 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 244 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 245 | "dev": true 246 | } 247 | } 248 | }, 249 | "rollup-plugin-html": { 250 | "version": "0.2.1", 251 | "resolved": "https://registry.npmjs.org/rollup-plugin-html/-/rollup-plugin-html-0.2.1.tgz", 252 | "integrity": "sha1-oYYuyoeuVLZ3aJ0NQTORHoImRj0=", 253 | "dev": true, 254 | "requires": { 255 | "html-minifier": "^3.0.2", 256 | "rollup-pluginutils": "^1.5.0" 257 | }, 258 | "dependencies": { 259 | "estree-walker": { 260 | "version": "0.2.1", 261 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", 262 | "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", 263 | "dev": true 264 | }, 265 | "rollup-pluginutils": { 266 | "version": "1.5.2", 267 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", 268 | "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", 269 | "dev": true, 270 | "requires": { 271 | "estree-walker": "^0.2.1", 272 | "minimatch": "^3.0.2" 273 | } 274 | } 275 | } 276 | }, 277 | "rollup-plugin-node-resolve": { 278 | "version": "5.2.0", 279 | "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", 280 | "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", 281 | "dev": true, 282 | "requires": { 283 | "@types/resolve": "0.0.8", 284 | "builtin-modules": "^3.1.0", 285 | "is-module": "^1.0.0", 286 | "resolve": "^1.11.1", 287 | "rollup-pluginutils": "^2.8.1" 288 | }, 289 | "dependencies": { 290 | "@types/resolve": { 291 | "version": "0.0.8", 292 | "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", 293 | "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", 294 | "dev": true, 295 | "requires": { 296 | "@types/node": "*" 297 | } 298 | } 299 | } 300 | }, 301 | "rollup-plugin-svelte": { 302 | "version": "7.1.0", 303 | "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", 304 | "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", 305 | "dev": true, 306 | "requires": { 307 | "require-relative": "^0.8.7", 308 | "rollup-pluginutils": "^2.8.2" 309 | } 310 | }, 311 | "rollup-pluginutils": { 312 | "version": "2.8.2", 313 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", 314 | "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", 315 | "dev": true, 316 | "requires": { 317 | "estree-walker": "^0.6.1" 318 | }, 319 | "dependencies": { 320 | "estree-walker": { 321 | "version": "0.6.1", 322 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", 323 | "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", 324 | "dev": true 325 | } 326 | } 327 | }, 328 | "source-map": { 329 | "version": "0.6.1", 330 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 331 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 332 | "dev": true 333 | }, 334 | "svelte": { 335 | "version": "3.38.2", 336 | "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.2.tgz", 337 | "integrity": "sha512-q5Dq0/QHh4BLJyEVWGe7Cej5NWs040LWjMbicBGZ+3qpFWJ1YObRmUDZKbbovddLC9WW7THTj3kYbTOFmU9fbg==", 338 | "dev": true 339 | }, 340 | "uglify-js": { 341 | "version": "3.4.10", 342 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", 343 | "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", 344 | "dev": true, 345 | "requires": { 346 | "commander": "~2.19.0", 347 | "source-map": "~0.6.1" 348 | }, 349 | "dependencies": { 350 | "commander": { 351 | "version": "2.19.0", 352 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", 353 | "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", 354 | "dev": true 355 | } 356 | } 357 | }, 358 | "upper-case": { 359 | "version": "1.1.3", 360 | "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", 361 | "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", 362 | "dev": true 363 | } 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-free-transform", 3 | "version": "1.1.5", 4 | "description": "A freely user-transformable container component for Svelte.", 5 | "repository": "github:mononaut/svelte-free-transform", 6 | "private": false, 7 | "main": "dist/index.js", 8 | "module": "dist/index.mjs", 9 | "svelte": "src/index.js", 10 | "scripts": { 11 | "build": "rollup -c", 12 | "dev": "rollup -c -w" 13 | }, 14 | "devDependencies": { 15 | "@babel/polyfill": "^7.12.1", 16 | "rollup": "^2.52.1", 17 | "rollup-plugin-css-only": "^3.1.0", 18 | "rollup-plugin-html": "^0.2.1", 19 | "rollup-plugin-node-resolve": "^5.2.0", 20 | "rollup-plugin-svelte": "^7.0.0", 21 | "svelte": "^3.30.0" 22 | }, 23 | "author": "mononaut", 24 | "license": "MIT", 25 | "keywords": [ 26 | "svelte", 27 | "drag", 28 | "resize", 29 | "rotate" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte' 2 | import resolve from 'rollup-plugin-node-resolve' 3 | import pkg from './package.json' 4 | 5 | export default [ 6 | { 7 | input: 'src/FreeTransform.svelte', 8 | output: [ 9 | { file: pkg.module, 'format': 'es' }, 10 | { file: pkg.main, 'format': 'umd', name: 'FreeTransform' } 11 | ], 12 | plugins: [ 13 | svelte(), 14 | resolve() 15 | ] 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /src/FreeTransform.svelte: -------------------------------------------------------------------------------- 1 | 362 | 363 | 367 | 368 |
375 |
376 | 377 |
378 |
379 |
380 |
381 |
382 |
383 | {#if rotatorEnabled } 384 |
385 |
386 | {#if rotatorBar }
{/if} 387 |
388 | {/if} 389 |
390 |
391 | 392 | 495 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import FreeTransform from './FreeTransform.svelte' 2 | 3 | export default FreeTransform 4 | -------------------------------------------------------------------------------- /src/vector.js: -------------------------------------------------------------------------------- 1 | function add (a, b) { 2 | return { 3 | x: a.x + b.x, 4 | y: a.y + b.y 5 | } 6 | } 7 | 8 | function subtract (a, b) { 9 | return { 10 | x: a.x - b.x, 11 | y: a.y - b.y 12 | } 13 | } 14 | 15 | function scale (p, scale) { 16 | return { 17 | x: p.x * scale, 18 | y: p.y * scale 19 | } 20 | } 21 | 22 | function rotate (p, a, origin = { x: 0, y: 0 }) { 23 | const dx = p.x - origin.x 24 | const dy = p.y - origin.y 25 | return { 26 | x: origin.x + (dx * Math.cos(a)) - (dy * Math.sin(a)), 27 | y: origin.y + (dy * Math.cos(a)) + (dx * Math.sin(a)) 28 | } 29 | } 30 | 31 | function direction (v) { 32 | const a = Math.atan(v.x / v.y) 33 | if (v.y > 0) return a + Math.PI 34 | else return a 35 | } 36 | 37 | function length (v) { 38 | return Math.sqrt((v.x * v.x) + (v.y * v.y)) 39 | } 40 | 41 | export default { 42 | add, 43 | subtract, 44 | sub: subtract, 45 | scale, 46 | rotate, 47 | direction, 48 | length, 49 | len: length 50 | } 51 | --------------------------------------------------------------------------------