├── image.png
├── babel.config.js
├── public
├── favicon.ico
└── index.html
├── src
├── assets
│ └── logo.png
├── main.js
├── App.vue
└── components
│ └── FreeTransform.vue
├── .npmignore
├── .travis.yml
├── .gitignore
├── .github
└── FUNDING.yml
├── LICENSE.md
├── package.json
└── README.md
/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skmail/vue-free-transform/HEAD/image.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skmail/vue-free-transform/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/skmail/vue-free-transform/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 |
4 | Vue.config.productionTip = false
5 |
6 | new Vue({
7 | render: h => h(App)
8 | }).$mount('#app')
9 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src
2 | __tests__
3 | node_modules
4 | .babelrc
5 | .eslintrc
6 | .gitignore
7 | .npmignore
8 | .travis.yml
9 | package.json
10 | package-lock.json
11 | yarn-error.log
12 | .idea
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "8"
5 |
6 | before_install:
7 | - 'nvm install-latest-npm'
8 |
9 | env:
10 | matrix:
11 |
12 | sudo: false
13 |
14 | script:
15 | - npm run lint
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vue-free-transform
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: skmail
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Solaiman Kmail (skmail)
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.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-free-transform",
3 | "description": "A free transform tool",
4 | "author": "Solaiman Kmail (https://github.com/skmail)",
5 | "version": "1.0.11",
6 | "main": "./dist/FreeTransform.common.js",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/skmail/vue-free-transform"
10 | },
11 | "scripts": {
12 | "serve": "vue-cli-service serve",
13 | "test": "vue-cli-service test",
14 | "build": "vue-cli-service build",
15 | "build:lib": "vue-cli-service build --target lib --name FreeTransform ./src/components/FreeTransform.vue",
16 | "lint": "vue-cli-service lint"
17 | },
18 | "dependencies": {
19 | "free-transform": "^0.1.3",
20 | "vue": "^2.5.17"
21 | },
22 | "devDependencies": {
23 | "@vue/cli-plugin-babel": "^3.0.1",
24 | "@vue/cli-plugin-eslint": "^3.0.1",
25 | "@vue/cli-service": "^3.0.1",
26 | "vue-template-compiler": "^2.5.17"
27 | },
28 | "eslintConfig": {
29 | "root": true,
30 | "env": {
31 | "node": true
32 | },
33 | "extends": [
34 | "plugin:vue/essential",
35 | "eslint:recommended"
36 | ],
37 | "rules": {},
38 | "parserOptions": {
39 | "parser": "babel-eslint"
40 | }
41 | },
42 | "postcss": {
43 | "plugins": {
44 | "autoprefixer": {}
45 | }
46 | },
47 | "browserslist": [
48 | "> 1%",
49 | "last 2 versions",
50 | "not ie <= 8"
51 | ],
52 | "files": [
53 | "dist/*",
54 | "src/*",
55 | "public/*",
56 | "*.json",
57 | "*.js"
58 | ]
59 | }
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VueJS Free Transform Tool
2 |
3 |
4 | [](https://www.npmjs.com/package/vue-free-transform) [](https://www.npmjs.com/package/vue-free-transform) [](https://opensource.org/licenses/MIT) [](https://travis-ci.org/skmail/vue-free-transform)
5 |
6 |
7 | VueJS component for resizing, dragging and rotating html elements using css transform matrix
8 |
9 | 
10 |
11 |
12 | ## Installation
13 | `yarn install vue-free-transform` or `npm install vue-free-transform --save`
14 |
15 | ## Demo
16 | https://codesandbox.io/s/1jl7z9p3q
17 |
18 |
19 | ## Usage
20 |
21 | ```js
22 | import FreeTransform from 'vue-free-transform'
23 | ```
24 |
25 | ```vue
26 |
27 |
39 |
40 |

41 |
42 |
43 |
44 | ```
45 | ## Optional Attributes
46 |
47 | `selected`
48 | `selectOn`
49 | `styles`
50 |
51 | | Attribute | Description |
52 | | ------------- |:-------------:|
53 | | styles | additional styles for parent wrapper usefull for z-index|
54 | | selected | hide the controls when values is false |
55 | | selectOn | trigger selection on `mousedown`, `click` or `dblclick` |
56 | | aspect-ratio | enable aspect ratio resizing default (true)|
57 | | scale-from-center | enable scale from center resizing default (true)|
58 |
59 |
60 |
61 | ## Events
62 | `onSelect`
63 | `dblclick`
64 | `click`
65 | `mousedown`
66 |
67 | ## css
68 |
69 | ```css
70 |
71 | .tr-transform--active{
72 | position: absolute;
73 | z-index: 5;
74 | }
75 |
76 | .tr-transform__content{
77 | user-select: none;
78 | }
79 | .tr-transform__rotator {
80 | top: -45px;
81 | left: calc(50% - 7px);
82 | }
83 |
84 | .tr-transform__rotator,
85 | .tr-transform__scale-point {
86 | background: #fff;
87 | width: 15px;
88 | height: 15px;
89 | border-radius: 50%;
90 | position: absolute;
91 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
92 | border: 1px solid rgba(0, 0, 0, 0.1);
93 | cursor: pointer;
94 | }
95 |
96 | .tr-transform__rotator:hover,
97 | .tr-transform__scale-point:hover {
98 | background: #F1F5F8;
99 | }
100 |
101 | .tr-transform__rotator:active,
102 | .tr-transform__scale-point:active {
103 | background: #DAE1E7;
104 | }
105 |
106 | .tr-transform__scale-point {
107 |
108 | }
109 |
110 | .tr-transform__scale-point--tl {
111 | top: -7px;
112 | left: -7px;
113 | }
114 |
115 | .tr-transform__scale-point--ml {
116 | top: calc(50% - 7px);
117 | left: -7px;
118 | }
119 |
120 | .tr-transform__scale-point--tr {
121 | left: calc(100% - 7px);
122 | top: -7px;
123 | }
124 |
125 | .tr-transform__scale-point--tm {
126 | left: calc(50% - 7px);
127 | top: -7px;
128 | }
129 |
130 | .tr-transform__scale-point--mr {
131 | left: calc(100% - 7px);
132 | top: calc(50% - 7px);
133 | }
134 |
135 | .tr-transform__scale-point--bl {
136 | left: -7px;
137 | top: calc(100% - 7px);
138 | }
139 |
140 | .tr-transform__scale-point--bm {
141 | left: calc(50% - 7px);
142 | top: calc(100% - 7px);
143 | }
144 |
145 | .tr-transform__scale-point--br {
146 | left: calc(100% - 7px);
147 | top: calc(100% - 7px);
148 | }
149 | ```
150 |
151 |
152 | ## Keyboard shortcuts
153 | `shift` for aspect ratio resizing
154 |
155 | `alt` for scaling from center
156 |
157 | `shift` + `alt` scaling from center based on aspect ratio
158 |
159 | `shift` while rotation will snap rotation using 15 degrees
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
27 |
29 | {{element.text}}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
153 |
154 |
261 |
--------------------------------------------------------------------------------
/src/components/FreeTransform.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
13 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
31 |
32 |
33 |
34 |
237 |
--------------------------------------------------------------------------------