jellies-draw 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.js ADDED
@@ -0,0 +1,89 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: {
4
+ node: true,
5
+ browser: true,
6
+ es6: true
7
+ },
8
+ extends: [
9
+ 'plugin:vue/essential',
10
+ 'eslint:recommended'
11
+ ],
12
+ globals: {
13
+ WeixinJSBridge : false
14
+ },
15
+ parserOptions: {
16
+ ecmaFeatures: {
17
+ legacyDecorators: true
18
+ }
19
+ },
20
+ rules: {
21
+ "indent": ["error", 2, { "SwitchCase": 1 }],
22
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
23
+ "func-names": 0,
24
+ "one-var": [1, "never"],
25
+ "prefer-const": 1,
26
+ "prefer-arrow-callback": 2,
27
+ "arrow-body-style": 0,
28
+ "prefer-template": ["error"],
29
+ "consistent-return": "off",
30
+ "prefer-rest-params": 2,
31
+ "no-script-url": 0,
32
+ "no-console": [
33
+ 2,
34
+ {
35
+ "allow": ["info", "error", "warn", "log"]
36
+ }
37
+ ],
38
+ "no-duplicate-imports": 2,
39
+ "eol-last": 2,
40
+ "no-useless-rename": 2,
41
+ "class-methods-use-this": 0,
42
+ "prefer-destructuring": 0,
43
+ "no-unused-vars": [2, {
44
+ // 允许声明未使用变量
45
+ "vars": "local",
46
+ // 参数不检查
47
+ "args": "none"
48
+ }],
49
+ "no-plusplus": 0,
50
+ "import/prefer-default-export": 0,
51
+ "no-use-before-define": [
52
+ "error",
53
+ {
54
+ "functions": false
55
+ }
56
+ ],
57
+ "@typescript-eslint/no-use-before-define": 0,
58
+ "object-shorthand": ["error", "always"],
59
+ "@typescript-eslint/explicit-function-return-type": 0,
60
+ "@typescript-eslint/interface-name-prefix": 0,
61
+ "no-invalid-this": 0,
62
+ "no-await-in-loop": "off",
63
+ "array-callback-return": "off",
64
+ "no-restricted-syntax": "off",
65
+ "@typescript-eslint/no-explicit-any": 0,
66
+ "import/no-extraneous-dependencies": 0,
67
+ "import/no-unresolved": 0,
68
+ "@typescript-eslint/explicit-member-accessibility": 0,
69
+ "@typescript-eslint/no-object-literal-type-assertion": 0,
70
+ "generator-star-spacing": "off",
71
+ "eqeqeq": 0,
72
+ "no-else-return": 2,
73
+ "arrow-parens": 0,
74
+ "space-before-function-paren": ["error", "never"],
75
+ "comma-dangle": [2, "never"]
76
+ },
77
+ overrides: [
78
+ {
79
+ files: [
80
+ '**/__tests__/*.{j,t}s?(x)',
81
+ '**/tests/unit/**/*.spec.{j,t}s?(x)'
82
+ ],
83
+ env: {
84
+ jest: true
85
+ }
86
+ }
87
+ ]
88
+ }
89
+
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # jellies-draw
2
+
3
+ ## Project setup
4
+ ```
5
+ yarn install
6
+ ```
7
+
8
+ ### Compiles and hot-reloads for development
9
+ ```
10
+ yarn serve
11
+ ```
12
+
13
+ ### Compiles and minifies for production
14
+ ```
15
+ yarn build
16
+ ```
17
+
18
+ ### Lints and fixes files
19
+ ```
20
+ yarn lint
21
+ ```
22
+
23
+ ### Customize configuration
24
+ See [Configuration Reference](https://cli.vuejs.org/config/).
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ presets: [
3
+ '@vue/cli-plugin-babel/preset'
4
+ ]
5
+ }
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "jellies-draw",
3
+ "version": "0.1.0",
4
+ "description": "A drawer for jellies",
5
+ "private": false,
6
+ "main": "./src/index.js",
7
+ "scripts": {
8
+ "serve": "vue-cli-service serve",
9
+ "build": "webpack --display-error-details --config webpack.config.js",
10
+ "lint": "vue-cli-service lint"
11
+ },
12
+ "files": [
13
+ "src/*",
14
+ "package",
15
+ "public/*",
16
+ "*.json",
17
+ "*.js"
18
+ ],
19
+ "dependencies": {
20
+ "core-js": "^3.6.5",
21
+ "konva": "^9.0.1",
22
+ "vue": "^2.6.11"
23
+ },
24
+ "devDependencies": {
25
+ "@vue/cli-plugin-babel": "^4.1.1",
26
+ "@vue/cli-plugin-eslint": "^4.1.1",
27
+ "@vue/cli-service": "^4.1.1",
28
+ "babel-eslint": "^10.1.0",
29
+ "eslint": "^6.7.2",
30
+ "eslint-plugin-vue": "^6.2.2",
31
+ "babel-core": "^6.26.3",
32
+ "babel-loader": "^7.1.5",
33
+ "css-loader": "^0.28.7",
34
+ "less": "^2.7.3",
35
+ "less-loader": "^4.0.5",
36
+ "sass": "^1.26.5",
37
+ "sass-loader": "^7.3.1",
38
+ "style-loader": "^0.19.0",
39
+ "url-loader": "^0.6.2",
40
+ "vue": "^2.5.9",
41
+ "vue-loader": "^13.5.0",
42
+ "vue-style-loader": "^3.0.3",
43
+ "vue-template-compiler": "^2.5.9",
44
+ "webpack": "^3.9.1"
45
+ },
46
+ "eslintConfig": {
47
+ "root": true,
48
+ "env": {
49
+ "node": true
50
+ },
51
+ "extends": [
52
+ "plugin:vue/essential",
53
+ "eslint:recommended"
54
+ ],
55
+ "parserOptions": {
56
+ "parser": "babel-eslint"
57
+ },
58
+ "rules": {}
59
+ },
60
+ "browserslist": [
61
+ "> 1%",
62
+ "last 2 versions",
63
+ "not dead"
64
+ ]
65
+ }
Binary file
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html lang="">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
+ <link rel="icon" href="<%= BASE_URL %>favicon.ico">
8
+ <title><%= htmlWebpackPlugin.options.title %></title>
9
+ </head>
10
+ <body>
11
+ <noscript>
12
+ <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
13
+ </noscript>
14
+ <div id="app"></div>
15
+ <!-- built files will be auto injected -->
16
+ </body>
17
+ </html>
package/src/App.vue ADDED
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <div id="app">
3
+ <div class="toolbar" v-show="isCanvasEnabled">
4
+ <tool-buttons :has-short-cuts="isCanvasEnabled" />
5
+ <div class="toolbar-divider"/>
6
+ <property-pickers />
7
+ </div>
8
+ <div class="demo-entry">
9
+ <input type="checkbox" v-model="isCanvasEnabled"/> Enable Canvas
10
+ </div>
11
+ <drawing-canvas
12
+ ref="drawingCanvas"
13
+ v-if="isCanvasCreated"
14
+ v-show="isCanvasVisible"
15
+ />
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ import DrawingCanvas from './components/DrawingCanvas.vue'
21
+ import ToolButtons from './components/ToolButtons.vue'
22
+ import PropertyPickers from './components/PropertyPickers.vue'
23
+ export default {
24
+ name: 'App',
25
+ components: {
26
+ DrawingCanvas,
27
+ ToolButtons,
28
+ PropertyPickers
29
+ },
30
+ data: () => ({
31
+ isCanvasCreated: false,
32
+ isCanvasVisible: false
33
+ }),
34
+ computed: {
35
+ isCanvasEnabled: {
36
+ get() {
37
+ return this.isCanvasCreated && this.isCanvasVisible
38
+ },
39
+ set(isEnabled) {
40
+ if (isEnabled) {
41
+ if (this.isCanvasCreated) {
42
+ this.isCanvasVisible = true
43
+ } else {
44
+ this.isCanvasCreated = true
45
+ this.isCanvasVisible = true
46
+ }
47
+ } else {
48
+ this.isCanvasVisible = false
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ </script>
55
+
56
+ <style>
57
+ body {
58
+ margin: 0;
59
+ padding: 0;
60
+ font-family: 'Avenir', Helvetica, Arial, sans-serif;
61
+ -webkit-font-smoothing: antialiased;
62
+ -moz-osx-font-smoothing: grayscale;
63
+ text-align: center;
64
+ color: #2c3e50;
65
+ height: 100vh;
66
+ width: 100vw;
67
+ overflow: hidden;
68
+ }
69
+ #app {
70
+ height: 100%;
71
+ width: 100%;
72
+ }
73
+ .toolbar {
74
+ height: 40px;
75
+ width: 100%;
76
+ display: flex;
77
+ justify-content: center;
78
+ align-items: center;
79
+ background: #EBEEF3;
80
+ }
81
+ .toolbar-divider {
82
+ height: 30px;
83
+ width: 1px;
84
+ background: rgba(0, 0, 0, 0.1);
85
+ margin: 0 7px 0 9px;
86
+ }
87
+ .demo-entry {
88
+ position: absolute;
89
+ top: 0;
90
+ right: 0;
91
+ z-index: 2;
92
+ }
93
+ </style>
Binary file
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <div
3
+ ref="container"
4
+ class="container"
5
+ >
6
+ <div
7
+ ref="whiteboard"
8
+ :class="[
9
+ 'whiteboard',
10
+ {
11
+ 'cursor-crosshair': isCrosshairCursorActive
12
+ }
13
+ ]"
14
+ />
15
+ </div>
16
+ </template>
17
+
18
+ <script>
19
+ import Canvas from './functions/canvas';
20
+ import Properties from './functions/properties';
21
+ export default {
22
+ name: 'DrawingCanvas',
23
+ computed: {
24
+ canvas() {
25
+ return this.$refs.whiteboard
26
+ },
27
+ container() {
28
+ return this.$refs.container
29
+ },
30
+ isCrosshairCursorActive() {
31
+ return (Properties.isUsingDrawingTool && !Properties.isUsingText)
32
+ }
33
+ },
34
+ mounted() {
35
+ this.createStage();
36
+ },
37
+ beforeDestroy() {
38
+ this.destroyStage();
39
+ },
40
+ methods: {
41
+ createStage() {
42
+ Canvas.initialize(this.canvas, this.container)
43
+ },
44
+ destroyStage() {
45
+ Canvas.destroy()
46
+ }
47
+ }
48
+ }
49
+ </script>
50
+
51
+ <style scoped>
52
+ * {
53
+ margin: 0;
54
+ padding: 0;
55
+ }
56
+ .container {
57
+ width: 100%;
58
+ height: 100%;
59
+ }
60
+ .whiteboard {
61
+ background-color: yellow;
62
+ }
63
+ .cursor-crosshair {
64
+ cursor: crosshair;
65
+ }
66
+ </style>
@@ -0,0 +1,218 @@
1
+ <template>
2
+ <div class="property">
3
+ <div class="colors">
4
+ <div
5
+ class="color fill-color"
6
+ :style="fillColorStyle"
7
+ >
8
+ <input
9
+ class="color-picker"
10
+ type="color"
11
+ v-model="fillColorValue"
12
+ @contextmenu="removeFillColor"
13
+ />
14
+ </div>
15
+ <div
16
+ class="color stroke-color"
17
+ :style="{
18
+ borderColor: strokeColor
19
+ }"
20
+ >
21
+ <input
22
+ class="color-picker"
23
+ type="color"
24
+ v-model="strokeColor"
25
+ />
26
+ </div>
27
+ </div>
28
+ <div class="size">
29
+ <span>{{ size }}</span>
30
+ <select
31
+ v-if="isUsingText"
32
+ v-model="fontSize"
33
+ >
34
+ <option
35
+ v-for="fontSizeOptionName, fontSizeOptionValue in fontSizeOptions"
36
+ :value="`${fontSizeOptionValue}`"
37
+ :key="fontSizeOptionValue"
38
+ >
39
+ {{ fontSizeOptionName }}
40
+ </option>
41
+ </select>
42
+ <select
43
+ v-else
44
+ v-model="strokeWidth"
45
+ >
46
+ <option
47
+ v-for="strokeWidthOptionName, strokeWidthOptionValue in strokeWidthOptions"
48
+ :value="`${strokeWidthOptionValue}`"
49
+ :key="strokeWidthOptionValue"
50
+ >
51
+ {{ strokeWidthOptionName }}
52
+ </option>
53
+ </select>
54
+ </div>
55
+ </div>
56
+ </template>
57
+
58
+ <script>
59
+ import Properties from './functions/properties';
60
+ export default {
61
+ name: 'PropertiesPicker',
62
+ data() {
63
+ return {
64
+ fontSizeOptions: {
65
+ 15: 'S',
66
+ 20: 'M',
67
+ 35: 'L',
68
+ 50: 'XL'
69
+ },
70
+ strokeWidthOptions: {
71
+ 3: 'H',
72
+ 4: 'HB',
73
+ 5: 'B',
74
+ 6: '2B'
75
+ }
76
+ }
77
+ },
78
+ computed: {
79
+ fillColor: {
80
+ get() {
81
+ return Properties.fillColor
82
+ },
83
+ set(newColor) {
84
+ Properties.fillColor = newColor
85
+ }
86
+ },
87
+ strokeColor: {
88
+ get() {
89
+ return Properties.strokeColor
90
+ },
91
+ set(newColor) {
92
+ Properties.strokeColor = newColor
93
+ }
94
+ },
95
+ strokeWidth: {
96
+ get() {
97
+ return Properties.strokeWidth
98
+ },
99
+ set(newWidth) {
100
+ Properties.strokeWidth = parseInt(newWidth)
101
+ }
102
+ },
103
+ fontSize: {
104
+ get() {
105
+ return Properties.fontSize
106
+ },
107
+ set(newSize) {
108
+ Properties.fontSize = parseInt(newSize)
109
+ }
110
+ },
111
+ fillColorValue: {
112
+ get() {
113
+ if (this.fillColor === 'transparent') {
114
+ return '#ffffff'
115
+ }
116
+ return this.fillColor
117
+ },
118
+ set(newColor) {
119
+ this.fillColor = newColor
120
+ }
121
+ },
122
+ fillColorStyle() {
123
+ if (this.fillColor !== 'transparent') {
124
+ return {
125
+ background: this.fillColor
126
+ }
127
+ }
128
+ return {
129
+ backgroundImage: 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==)',
130
+ backgroundColor: 'white'
131
+ }
132
+ },
133
+ isUsingText() {
134
+ return Properties.isUsingText
135
+ },
136
+ size() {
137
+ if (Properties.isUsingText) {
138
+ return this.fontSizeOptions[this.fontSize]
139
+ }
140
+ return this.strokeWidthOptions[this.strokeWidth]
141
+ }
142
+ },
143
+ methods: {
144
+ removeFillColor(event) {
145
+ event.preventDefault()
146
+ this.fillColor = 'transparent'
147
+ }
148
+ }
149
+ }
150
+ </script>
151
+
152
+ <style scoped>
153
+ .property {
154
+ background-color: #fff;
155
+ border-radius: 17px;
156
+ height: 34px;
157
+ margin: 3px;
158
+ padding: 8px;
159
+ box-sizing: border-box;
160
+ display: flex;
161
+ }
162
+ .colors {
163
+ height: 18px;
164
+ position: relative;
165
+ width: 30px;
166
+ }
167
+ .color {
168
+ position: absolute;
169
+ width: 18px;
170
+ height: 18px;
171
+ top: 0;
172
+ border-radius: 10px;
173
+ border: 1px solid #eee;
174
+ box-sizing: border-box;
175
+ -webkit-font-smoothing: antialiased;
176
+ -moz-osx-font-smoothing: grayscale;
177
+ overflow: hidden;
178
+ left: 12px;
179
+ }
180
+ .stroke-color {
181
+ background: #fff;
182
+ left: 0;
183
+ border: 4px solid black;
184
+ }
185
+ .color-picker {
186
+ display: block;
187
+ width: 18px;
188
+ height: 18px;
189
+ opacity: 0;
190
+ margin: -1px 0 0 -1px;
191
+ cursor: pointer;
192
+ }
193
+ .stroke-color > .color-picker {
194
+ margin: -4px 0 0 -4px;
195
+ }
196
+ .size {
197
+ height: 18px;
198
+ width: 40px;
199
+ background: #ebeef3;
200
+ font-size: 12px;
201
+ line-height: 18px;
202
+ border-radius: 9px;
203
+ color: #333;
204
+ position: relative;
205
+ margin-left: 6px;
206
+ }
207
+ .size span {
208
+ display: block;
209
+ text-align: center;
210
+ position: absolute;
211
+ width: 40px;
212
+ }
213
+ .size select {
214
+ display: block;
215
+ position: absolute;
216
+ opacity: 0;
217
+ }
218
+ </style>
@@ -0,0 +1,125 @@
1
+ <template>
2
+ <div
3
+ :class="[
4
+ 'wrapper',
5
+ { active: isActive }
6
+ ]">
7
+ <button
8
+ :class="[
9
+ 'jellies-draw-tool',
10
+ `tool-${action}`
11
+ ]"
12
+ @click="applyAction"
13
+ />
14
+ <span>{{ shortCut }}</span>
15
+ </div>
16
+ </template>
17
+ <script>
18
+ export default {
19
+ name: 'ToolButton',
20
+ props: {
21
+ action: {
22
+ type: String,
23
+ default: 'selector'
24
+ },
25
+ shortCut: {
26
+ type: Number,
27
+ default: 1
28
+ },
29
+ isActive: {
30
+ type: Boolean,
31
+ default: false
32
+ }
33
+ },
34
+ methods: {
35
+ applyAction() {
36
+ this.$emit('action-applied', this.action)
37
+ }
38
+ }
39
+ }
40
+ </script>
41
+ <style scoped>
42
+ @font-face {
43
+ font-family: "jellies-draw";
44
+ src: url('../assets/jellies-draw-tool.ttf') format('truetype');
45
+ }
46
+ button {
47
+ border: none;
48
+ cursor: pointer;
49
+ padding: 0;
50
+ width: 100%;
51
+ height: 100%;
52
+ text-align: center;
53
+ color: inherit;
54
+ outline: none;
55
+ background-color: transparent;
56
+ font-family: "jellies-draw", sans-serif !important;
57
+ font-size: 16px;
58
+ font-style: normal;
59
+ -webkit-font-smoothing: antialiased;
60
+ -moz-osx-font-smoothing: grayscale;
61
+ }
62
+ .wrapper {
63
+ position: relative;
64
+ border-radius: 5px;
65
+ width: 34px;
66
+ height: 34px;
67
+ margin: 3px;
68
+ color: #555;
69
+ background-color: #fff;
70
+ }
71
+ .wrapper:hover {
72
+ box-shadow: 0 1px 0 0 rgba(30, 30, 30, 0.2);
73
+ margin-top: 2px;
74
+ }
75
+ .wrapper > span {
76
+ position: absolute;
77
+ bottom: 2px;
78
+ right: 4px;
79
+ font-size: 9px;
80
+ font-weight: bold;
81
+ color: #aaa;
82
+ pointer-events: none;
83
+ }
84
+ .wrapper.active {
85
+ background-color: #c6e2ff;
86
+ color: #399af4;
87
+ }
88
+ .wrapper.active:hover {
89
+ margin-top: 3px;
90
+ box-shadow: none;
91
+ }
92
+ .wrapper.active > span {
93
+ color: #399af4;
94
+ }
95
+ .tool-ellipse:before {
96
+ content: "\e654";
97
+ }
98
+ .tool-eraser:before {
99
+ content: "\e689";
100
+ }
101
+ .tool-text:before {
102
+ content: "\e69f";
103
+ }
104
+ .tool-image:before {
105
+ content: "\e6d8";
106
+ }
107
+ .tool-arrow:before {
108
+ content: "\e6f7";
109
+ }
110
+ .tool-line:before {
111
+ content: "\e70a";
112
+ }
113
+ .tool-selector:before {
114
+ content: "\e713";
115
+ }
116
+ .tool-pen:before {
117
+ content: "\e727";
118
+ }
119
+ .tool-rectangle:before {
120
+ content: "\e777";
121
+ }
122
+ .tool-clear:before {
123
+ content: "\e7a9";
124
+ }
125
+ </style>