@operato/scene-basic 1.2.5

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +0 -0
  3. package/demo/index.html +158 -0
  4. package/demo/things-scene-basic.html +6 -0
  5. package/dist/anchors/ellipse-anchors.d.ts +7 -0
  6. package/dist/anchors/ellipse-anchors.js +43 -0
  7. package/dist/anchors/ellipse-anchors.js.map +1 -0
  8. package/dist/audio.d.ts +25 -0
  9. package/dist/audio.js +141 -0
  10. package/dist/audio.js.map +1 -0
  11. package/dist/cloud.d.ts +13 -0
  12. package/dist/cloud.js +30 -0
  13. package/dist/cloud.js.map +1 -0
  14. package/dist/donut.d.ts +15 -0
  15. package/dist/donut.js +74 -0
  16. package/dist/donut.js.map +1 -0
  17. package/dist/ellipse.d.ts +24 -0
  18. package/dist/ellipse.js +72 -0
  19. package/dist/ellipse.js.map +1 -0
  20. package/dist/gif-view.d.ts +18 -0
  21. package/dist/gif-view.js +116 -0
  22. package/dist/gif-view.js.map +1 -0
  23. package/dist/image-view.d.ts +19 -0
  24. package/dist/image-view.js +180 -0
  25. package/dist/image-view.js.map +1 -0
  26. package/dist/index.d.ts +11 -0
  27. package/dist/index.js +15 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/outline/ellipse-outline.d.ts +2 -0
  30. package/dist/outline/ellipse-outline.js +11 -0
  31. package/dist/outline/ellipse-outline.js.map +1 -0
  32. package/dist/polygon.d.ts +19 -0
  33. package/dist/polygon.js +84 -0
  34. package/dist/polygon.js.map +1 -0
  35. package/dist/polyline.d.ts +18 -0
  36. package/dist/polyline.js +102 -0
  37. package/dist/polyline.js.map +1 -0
  38. package/dist/rect.d.ts +19 -0
  39. package/dist/rect.js +60 -0
  40. package/dist/rect.js.map +1 -0
  41. package/dist/star.d.ts +13 -0
  42. package/dist/star.js +80 -0
  43. package/dist/star.js.map +1 -0
  44. package/dist/templates/audio.d.ts +14 -0
  45. package/dist/templates/audio.js +15 -0
  46. package/dist/templates/audio.js.map +1 -0
  47. package/dist/templates/color-image.d.ts +22 -0
  48. package/dist/templates/color-image.js +23 -0
  49. package/dist/templates/color-image.js.map +1 -0
  50. package/dist/templates/donut.d.ts +22 -0
  51. package/dist/templates/donut.js +23 -0
  52. package/dist/templates/donut.js.map +1 -0
  53. package/dist/templates/ellipse.d.ts +21 -0
  54. package/dist/templates/ellipse.js +22 -0
  55. package/dist/templates/ellipse.js.map +1 -0
  56. package/dist/templates/gif-image.d.ts +14 -0
  57. package/dist/templates/gif-image.js +15 -0
  58. package/dist/templates/gif-image.js.map +1 -0
  59. package/dist/templates/gray-image.d.ts +22 -0
  60. package/dist/templates/gray-image.js +23 -0
  61. package/dist/templates/gray-image.js.map +1 -0
  62. package/dist/templates/index.d.ts +74 -0
  63. package/dist/templates/index.js +15 -0
  64. package/dist/templates/index.js.map +1 -0
  65. package/dist/templates/polygon.d.ts +22 -0
  66. package/dist/templates/polygon.js +25 -0
  67. package/dist/templates/polygon.js.map +1 -0
  68. package/dist/templates/polyline.d.ts +22 -0
  69. package/dist/templates/polyline.js +25 -0
  70. package/dist/templates/polyline.js.map +1 -0
  71. package/dist/templates/rect.d.ts +21 -0
  72. package/dist/templates/rect.js +22 -0
  73. package/dist/templates/rect.js.map +1 -0
  74. package/dist/templates/star.d.ts +23 -0
  75. package/dist/templates/star.js +24 -0
  76. package/dist/templates/star.js.map +1 -0
  77. package/dist/templates/text.d.ts +27 -0
  78. package/dist/templates/text.js +28 -0
  79. package/dist/templates/text.js.map +1 -0
  80. package/dist/templates/triangle.d.ts +23 -0
  81. package/dist/templates/triangle.js +24 -0
  82. package/dist/templates/triangle.js.map +1 -0
  83. package/dist/text.d.ts +6 -0
  84. package/dist/text.js +11 -0
  85. package/dist/text.js.map +1 -0
  86. package/dist/triangle.d.ts +14 -0
  87. package/dist/triangle.js +75 -0
  88. package/dist/triangle.js.map +1 -0
  89. package/icons/audio.png +0 -0
  90. package/icons/both-arrow.png +0 -0
  91. package/icons/color-image.png +0 -0
  92. package/icons/container.png +0 -0
  93. package/icons/dash.png +0 -0
  94. package/icons/donut.png +0 -0
  95. package/icons/ellipse.png +0 -0
  96. package/icons/gif-image.png +0 -0
  97. package/icons/global-reference.png +0 -0
  98. package/icons/gray-image.png +0 -0
  99. package/icons/humidity-sensor.png +0 -0
  100. package/icons/info-window.png +0 -0
  101. package/icons/line.png +0 -0
  102. package/icons/local-reference.png +0 -0
  103. package/icons/no-image.png +0 -0
  104. package/icons/ortholine.png +0 -0
  105. package/icons/person.png +0 -0
  106. package/icons/polygon.png +0 -0
  107. package/icons/polyline.png +0 -0
  108. package/icons/popup.png +0 -0
  109. package/icons/rect.png +0 -0
  110. package/icons/single-arrow.png +0 -0
  111. package/icons/star.png +0 -0
  112. package/icons/text.png +0 -0
  113. package/icons/triangle.png +0 -0
  114. package/package.json +61 -0
  115. package/src/anchors/ellipse-anchors.ts +46 -0
  116. package/src/audio.ts +173 -0
  117. package/src/cloud.ts +40 -0
  118. package/src/donut.ts +92 -0
  119. package/src/ellipse.ts +90 -0
  120. package/src/gif-view.ts +146 -0
  121. package/src/image-view.ts +215 -0
  122. package/src/index.ts +16 -0
  123. package/src/outline/ellipse-outline.ts +15 -0
  124. package/src/polygon.ts +103 -0
  125. package/src/polyline.ts +122 -0
  126. package/src/rect.ts +71 -0
  127. package/src/star.ts +104 -0
  128. package/src/templates/audio.ts +15 -0
  129. package/src/templates/color-image.ts +23 -0
  130. package/src/templates/donut.ts +23 -0
  131. package/src/templates/ellipse.ts +22 -0
  132. package/src/templates/gif-image.ts +15 -0
  133. package/src/templates/gray-image.ts +23 -0
  134. package/src/templates/index.ts +16 -0
  135. package/src/templates/polygon.ts +25 -0
  136. package/src/templates/polyline.ts +25 -0
  137. package/src/templates/rect.ts +22 -0
  138. package/src/templates/star.ts +24 -0
  139. package/src/templates/text.ts +28 -0
  140. package/src/templates/triangle.ts +24 -0
  141. package/src/text.ts +12 -0
  142. package/src/triangle.ts +87 -0
  143. package/test/basic-test.html +63 -0
  144. package/test/index.html +22 -0
  145. package/things-scene.config.js +5 -0
  146. package/tsconfig.json +23 -0
  147. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,215 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { error, Component, ComponentNature, Properties, RectPath, Shape } from '@hatiolab/things-scene'
6
+
7
+ const NATURE: ComponentNature = {
8
+ mutable: false,
9
+ resizable: true,
10
+ rotatable: true,
11
+ properties: [
12
+ {
13
+ type: 'image-selector',
14
+ label: 'image-src',
15
+ name: 'src',
16
+ property: {
17
+ displayField: 'id',
18
+ displayFullUrl: true,
19
+ baseUrlAlias: '$base_url',
20
+ defaultStorage: 'scene-image',
21
+ storageFilters: {
22
+ type: Array,
23
+ value: [
24
+ {
25
+ name: 'category',
26
+ value: 'image'
27
+ }
28
+ ]
29
+ },
30
+ useUpload: true
31
+ }
32
+ },
33
+ {
34
+ type: 'select',
35
+ label: 'cross-origin',
36
+ name: 'crossOrigin',
37
+ property: {
38
+ options: ['', 'anonymous', 'use-credentials']
39
+ }
40
+ }
41
+ ],
42
+ 'value-property': 'src',
43
+ help: 'scene/component/image-view'
44
+ }
45
+
46
+ const NOIMAGE_DATA_URI =
47
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABIBAMAAAD7Se1QAAAAIVBMVEUAAABHcEwBAQEREREBAQEEBAQGBgYLCwsDAwMDAwMICAi6HF9tAAAAC3RSTlNNAEAERiMYCS41Eac10lYAAAEgSURBVHhe7dY9asQwEAXgh7DNertNiJy48pIitY3SB7bYdk0ukL1BDDmA9gZecoH4pmFQ3MQayUMguPBrNPD4wD9TCMvJmt3M/AtYwXOlXiWgqADVCUBD46MAnGhMBaCiUQmAm8VA/Eh/eWl9Fn5WcxD+OLuRrUYJDKLluwH2InACUgkoACSdADxQc50Bytadb9RkM0CT13TcvlCT1HFg8UTHvasuUVACCa3El6u2UdD8LFTlKhUFFgA+d3dj10aABkUN72N3jAADCrJq7PIIsPidcxBoTHIIAjMFmyCwmGYIAA1P9gFgfCANAOsDSccCDW+uLDB+kLGg94OkZoAGkwsDDAe2DOg5oPxAg03rBR88OHpBz4N8UVeHFSwma74BTW6Ge4rIRa4AAAAASUVORK5CYII='
48
+
49
+ export default class ImageView extends RectPath(Shape) {
50
+ static NOIMAGE?: any
51
+
52
+ static get noimage() {
53
+ if (!ImageView.NOIMAGE) {
54
+ ImageView.NOIMAGE = new Image()
55
+ ImageView.NOIMAGE.src = NOIMAGE_DATA_URI
56
+ }
57
+
58
+ return ImageView.NOIMAGE
59
+ }
60
+
61
+ _offcanvas?: HTMLCanvasElement
62
+ _image?: any
63
+
64
+ dispose() {
65
+ super.dispose()
66
+ delete this._offcanvas
67
+ delete this._image
68
+ }
69
+
70
+ render(ctx: CanvasRenderingContext2D) {
71
+ var { left, top, width, height, isGray = false, alpha = 1, src } = this.state
72
+
73
+ this.prepareIf(!this._image && src)
74
+
75
+ // 박스 그리기
76
+ ctx.beginPath()
77
+ ctx.globalAlpha *= alpha
78
+
79
+ if (this._image && this._image.complete) {
80
+ if (isGray && this._offcanvas) {
81
+ ctx.drawImage(this._offcanvas, left, top, width, height)
82
+ } else {
83
+ try {
84
+ ctx.drawImage(this._image, left, top, width, height)
85
+ } catch (e) {
86
+ ctx.drawImage(ImageView.noimage, left, top, width, height)
87
+ }
88
+ }
89
+ } else {
90
+ !this.app.isViewMode && ctx.drawImage(ImageView.noimage, left, top, width, height)
91
+ }
92
+ }
93
+
94
+ get nature() {
95
+ return NATURE
96
+ }
97
+
98
+ get hasTextProperty() {
99
+ return false
100
+ }
101
+
102
+ ready() {
103
+ super.ready()
104
+ this.prepareIf(!this._image && this.state.src)
105
+ }
106
+
107
+ prepare(resolve: (ret?: any) => void, reject: (e?: any) => void) {
108
+ var { src, crossOrigin } = this.state
109
+
110
+ if (!src) {
111
+ resolve(this)
112
+ return
113
+ }
114
+
115
+ this._image = new Image()
116
+
117
+ try {
118
+ if (crossOrigin) {
119
+ this._image.crossOrigin = crossOrigin
120
+ }
121
+
122
+ this._image.src = this.app.url(src) || ''
123
+ } catch (e) {
124
+ reject(e)
125
+ return
126
+ }
127
+
128
+ this._image.onload = () => {
129
+ if (this.get('isGray')) {
130
+ let width = this._image.width
131
+ let height = this._image.height
132
+
133
+ this._offcanvas = Component.createCanvas(width, height)
134
+
135
+ let offcontext = this._offcanvas!.getContext('2d') as CanvasRenderingContext2D
136
+ offcontext!.drawImage(this._image, 0, 0)
137
+
138
+ let imageData = makeGrayImage(offcontext, width, height)
139
+ offcontext!.putImageData(imageData!, 0, 0)
140
+ }
141
+
142
+ resolve(this)
143
+ }
144
+
145
+ this._image.onerror = (e: any) => {
146
+ if (this._image && !this._image.currentSrc) this._image = null
147
+ reject(e)
148
+ }
149
+ }
150
+
151
+ get src() {
152
+ return this.get('src')
153
+ }
154
+
155
+ set src(src) {
156
+ this.set('src', src)
157
+ }
158
+
159
+ onchange(after: Properties, before: Properties) {
160
+ if (after.hasOwnProperty('src') || after.hasOwnProperty('isGray')) {
161
+ delete this._offcanvas
162
+ delete this._image
163
+ this.prepareIf(after.src)
164
+ }
165
+ }
166
+
167
+ ondropfile(transfered: DataTransferItemList, files: FileList) {
168
+ for (let i = 0; i < transfered.length; i++) {
169
+ if (transfered[i].type.startsWith('image/')) {
170
+ this.src = files[i]
171
+ return
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ function makeGrayImage(ctx: CanvasRenderingContext2D, width: number, height: number) {
178
+ try {
179
+ var img = ctx.getImageData(0, 0, width, height)
180
+ } catch (e: any) {
181
+ error('Get Image Data Error: ' + e.message)
182
+ return null
183
+ }
184
+
185
+ var data = img.data
186
+ // Loop through data.
187
+ for (let i = 0; i < width * height * 4; i += 4) {
188
+ // First bytes are red bytes.
189
+ // Get red value.
190
+ let red = data[i]
191
+
192
+ // Second bytes are green bytes.
193
+ // Get green value.
194
+ let green = data[i + 1]
195
+
196
+ // Third bytes are blue bytes.
197
+ // Get blue value.
198
+ let blue = data[i + 2]
199
+
200
+ // Fourth bytes are alpha bytes
201
+ // We don't care about alpha here.
202
+ // Add the three values and divide by three.
203
+ // Make it an integer.
204
+ let gray = parseInt(String((red + green + blue) / 3))
205
+
206
+ // Assign average to red, green, and blue.
207
+ img.data[i] = gray
208
+ img.data[i + 1] = gray
209
+ img.data[i + 2] = gray
210
+ }
211
+
212
+ return img
213
+ }
214
+
215
+ Component.register('image-view', ImageView)
package/src/index.ts ADDED
@@ -0,0 +1,16 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ export { default as Ellipse } from './ellipse'
6
+ export { default as Rect } from './rect'
7
+ export { default as Polygon } from './polygon'
8
+ export { default as Polyline } from './polyline'
9
+ export { default as ImageView } from './image-view'
10
+ export { default as GifView } from './gif-view'
11
+ export { default as AudioPlayer } from './audio'
12
+ export { default as Text } from './text'
13
+
14
+ export { default as Triangle } from './triangle'
15
+ export { default as Donut } from './donut'
16
+ export { default as Star } from './star'
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { Component } from '@hatiolab/things-scene'
6
+
7
+ export default function ellipseOutline(component: Component, progress: number) {
8
+ var { cx, cy, rx, ry } = component.model
9
+ var theta = Math.PI * 2 * progress
10
+
11
+ var x = cx + rx * Math.cos(theta)
12
+ var y = cy + ry * Math.sin(theta)
13
+
14
+ return component.transcoordS2T(x, y)
15
+ }
package/src/polygon.ts ADDED
@@ -0,0 +1,103 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { Component, ComponentNature, DIMENSION, POSITION, Properties, RectPath, Shape } from '@hatiolab/things-scene'
6
+
7
+ var controlHandler = {
8
+ ondragstart: function (point: POSITION, index: number, component: Component) {
9
+ component.mutatePath(null, function (path: Array<DIMENSION>) {
10
+ path.splice(index + 1, 0, point)
11
+ })
12
+ },
13
+
14
+ ondragmove: function (point: POSITION, index: number, component: Component) {
15
+ component.mutatePath(null, function (path: Array<DIMENSION>) {
16
+ path[index + 1] = point
17
+ })
18
+ },
19
+
20
+ ondragend: function (point: POSITION, index: number, component: Component) {}
21
+ }
22
+
23
+ const NATURE: ComponentNature = {
24
+ mutable: true,
25
+ resizable: false,
26
+ rotatable: true,
27
+ properties: [
28
+ {
29
+ type: 'number',
30
+ label: 'round',
31
+ name: 'round',
32
+ property: {
33
+ min: 0,
34
+ max: 100,
35
+ step: 1
36
+ }
37
+ }
38
+ ],
39
+ help: 'scene/component/polygon'
40
+ }
41
+
42
+ export default class Polygon extends Shape {
43
+ is3dish() {
44
+ return true
45
+ }
46
+
47
+ get mutable() {
48
+ return true
49
+ }
50
+
51
+ get pathExtendable() {
52
+ return true
53
+ }
54
+
55
+ get path() {
56
+ return this.state.path
57
+ }
58
+
59
+ set path(path) {
60
+ this.set('path', path)
61
+ }
62
+
63
+ contains(x: number, y: number) {
64
+ var path = this.state.path as Array<DIMENSION>
65
+ var result = false
66
+
67
+ path.forEach((p, idx) => {
68
+ let j = (idx + path.length + 1) % path.length
69
+
70
+ let x1 = p.x
71
+ let y1 = p.y
72
+ let x2 = path[j].x
73
+ let y2 = path[j].y
74
+
75
+ if (y1 > y != y2 > y && x < ((x2 - x1) * (y - y1)) / (y2 - y1) + x1) result = !result
76
+ })
77
+
78
+ return result
79
+ }
80
+
81
+ get controls() {
82
+ // 폴리곤에서의 control은 새로운 path를 추가하는 포인트이다.
83
+ var path = this.path as Array<DIMENSION>
84
+
85
+ return path.map((p1, i) => {
86
+ let p2 = path[i + 1 >= path.length ? 0 : i + 1]
87
+
88
+ return {
89
+ x: (p1.x + p2.x) / 2,
90
+ y: (p1.y + p2.y) / 2,
91
+ handler: controlHandler
92
+ }
93
+ })
94
+ }
95
+
96
+ get nature() {
97
+ return NATURE
98
+ }
99
+ }
100
+
101
+ Component.memoize(Polygon.prototype, 'controls', false)
102
+
103
+ Component.register('polygon', Polygon)
@@ -0,0 +1,122 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import { Component, ComponentNature, Properties, Line, POSITION } from '@hatiolab/things-scene'
5
+
6
+ var controlHandler = {
7
+ ondragstart: function (point: POSITION, index: number, component: Component) {
8
+ component.mutatePath(null, function (path) {
9
+ path.splice(index, 0, point) // array.insert(index, point) 의 의미임.
10
+ })
11
+ },
12
+
13
+ ondragmove: function (point: POSITION, index: number, component: Component) {
14
+ component.mutatePath(null, function (path) {
15
+ path[index] = point
16
+ })
17
+ },
18
+
19
+ ondragend: function (point: POSITION, index: number, component: Component) {}
20
+ }
21
+
22
+ const NATURE: ComponentNature = {
23
+ mutable: false,
24
+ resizable: false,
25
+ rotatable: false,
26
+ properties: [
27
+ {
28
+ type: 'number',
29
+ label: 'round',
30
+ name: 'round',
31
+ property: {
32
+ min: 0,
33
+ max: 100,
34
+ step: 1
35
+ }
36
+ }
37
+ ],
38
+ help: 'scene/component/polyline'
39
+ }
40
+
41
+ export default class Polyline extends Line {
42
+ _fromEnd: any
43
+ _toEnd: any
44
+
45
+ get pathExtendable() {
46
+ return true
47
+ }
48
+
49
+ get path() {
50
+ const { from, to } = this.state
51
+ const { path } = this.state
52
+
53
+ return [
54
+ this.fromEnd?.position || from?.position || path[0],
55
+ ...path.slice(1, -1),
56
+ this.toEnd?.position || to?.position || path[path.length - 1]
57
+ ]
58
+ }
59
+
60
+ set path(path) {
61
+ const { from, to } = this.state
62
+
63
+ delete this._fromEnd
64
+ delete this._toEnd
65
+
66
+ this.set({
67
+ from: {
68
+ ...from,
69
+ position: path[0]
70
+ },
71
+ to: {
72
+ ...to,
73
+ position: path[path.length - 1]
74
+ },
75
+ path
76
+ })
77
+ }
78
+
79
+ get controls() {
80
+ // 폴리라인에서의 control은 새로운 path를 추가하는 포인트이다.
81
+ var path = this.path
82
+ var controls = []
83
+
84
+ for (let i = 0; i < path.length - 1; i++) {
85
+ let p1 = path[i]
86
+ let p2 = path[i + 1]
87
+
88
+ if (i == 0) {
89
+ controls.push({
90
+ x: p1.x,
91
+ y: p1.y,
92
+ handler: controlHandler
93
+ })
94
+ }
95
+
96
+ controls.push({
97
+ x: (p1.x + p2.x) / 2,
98
+ y: (p1.y + p2.y) / 2,
99
+ handler: controlHandler
100
+ })
101
+
102
+ if (i == path.length - 2) {
103
+ controls.push({
104
+ x: p2.x,
105
+ y: p2.y,
106
+ handler: controlHandler
107
+ })
108
+ }
109
+ }
110
+
111
+ return controls
112
+ }
113
+
114
+ get nature() {
115
+ return NATURE
116
+ }
117
+ }
118
+
119
+ /* target anchor의 움직임이 반영되지 못하므로, 일단 controls memoize를 제거함. */
120
+ // Component.memoize(Polyline.prototype, 'controls', false)
121
+
122
+ Component.register('polyline', Polyline)
package/src/rect.ts ADDED
@@ -0,0 +1,71 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { Component, ComponentNature, Connectable, POSITION, Properties, RectPath, Shape } from '@hatiolab/things-scene'
6
+
7
+ const NATURE: ComponentNature = {
8
+ mutable: false,
9
+ resizable: true,
10
+ rotatable: true,
11
+ properties: [
12
+ {
13
+ type: 'number',
14
+ label: 'round',
15
+ name: 'round',
16
+ property: {
17
+ min: 0
18
+ }
19
+ }
20
+ ],
21
+ help: 'scene/component/rect'
22
+ }
23
+
24
+ var controlHandler = {
25
+ ondragmove: function (point: POSITION, index: number, component: Component) {
26
+ var { left, top, width, height } = component.model
27
+
28
+ var transcoorded = component.transcoordP2S(point.x, point.y)
29
+ var round = ((transcoorded.x - left) / (width / 2)) * 100
30
+
31
+ round = safeRound(round, width, height)
32
+
33
+ component.set({
34
+ round
35
+ })
36
+ }
37
+ }
38
+
39
+ function safeRound(round: number, width: number, height: number) {
40
+ var max = width > height ? (height / width) * 100 : 100
41
+
42
+ if (round >= max) round = max
43
+ else if (round <= 0) round = 0
44
+
45
+ return round
46
+ }
47
+
48
+ export default class Rect extends Connectable(RectPath(Shape)) {
49
+ is3dish() {
50
+ return true
51
+ }
52
+
53
+ get controls() {
54
+ var { left, top, width, round, height } = this.state
55
+ round = round == undefined ? 0 : safeRound(round, width, height)
56
+
57
+ return [
58
+ {
59
+ x: left + (width / 2) * (round / 100),
60
+ y: top,
61
+ handler: controlHandler
62
+ }
63
+ ]
64
+ }
65
+
66
+ get nature() {
67
+ return NATURE
68
+ }
69
+ }
70
+
71
+ Component.register('rect', Rect)
package/src/star.ts ADDED
@@ -0,0 +1,104 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import { Component, ComponentNature, Ellipse, POSITION } from '@hatiolab/things-scene'
6
+
7
+ const NATURE: ComponentNature = {
8
+ mutable: false,
9
+ resizable: true,
10
+ rotatable: true,
11
+ properties: [
12
+ {
13
+ type: 'number',
14
+ label: 'ratio',
15
+ name: 'ratio',
16
+ property: 'ratio'
17
+ },
18
+ {
19
+ type: 'number',
20
+ label: 'wing',
21
+ name: 'wing',
22
+ property: 'wing'
23
+ }
24
+ ],
25
+ help: 'scene/component/star'
26
+ }
27
+
28
+ var controlHandler = {
29
+ ondragmove: function (point: POSITION, index: number, component: Component) {
30
+ var controls = component.controls
31
+ var { cy, ry } = component.model
32
+
33
+ var transcoorded = component.transcoordP2S(point.x, point.y)
34
+
35
+ var ratio = ((transcoorded.y - cy) / ry) * 100 + 100
36
+
37
+ if (ratio >= 100) ratio = 100
38
+ else if (ratio <= 0) ratio = 0
39
+
40
+ component.set({ ratio }) // ratio: ratio => ratio
41
+ }
42
+ }
43
+
44
+ export default class Star extends Ellipse {
45
+ is3dish() {
46
+ return false
47
+ }
48
+
49
+ render(ctx: CanvasRenderingContext2D) {
50
+ var { ratio = 30, wing = 5, cx, cy, rx, ry, startAngle, endAngle, anticlockwise } = this.state
51
+
52
+ // 박스 그리기
53
+
54
+ if (wing < 3) return
55
+
56
+ const RADIAN = 1.5707963267948966 // 90도 뒤틀기
57
+ var a = (Math.PI * 2) / wing
58
+ var xRatio = rx - (ratio / 100) * rx
59
+ var yRatio = ry - (ratio / 100) * ry
60
+
61
+ ctx.save()
62
+ ctx.beginPath()
63
+
64
+ ctx.translate(cx, cy)
65
+
66
+ ctx.moveTo(rx * Math.cos(-RADIAN), ry * Math.sin(-RADIAN))
67
+ ctx.lineTo(
68
+ ((rx - xRatio) * (Math.cos(a - RADIAN) + Math.cos(0 - RADIAN))) / 2,
69
+ ((ry - yRatio) * (Math.sin(a - RADIAN) + Math.sin(0 - RADIAN))) / 2
70
+ )
71
+
72
+ for (var i = 1; i < wing; i++) {
73
+ ctx.lineTo(rx * Math.cos(a * i - RADIAN), ry * Math.sin(a * i - RADIAN))
74
+
75
+ ctx.lineTo(
76
+ ((rx - xRatio) * (Math.cos(a * (i + 1) - RADIAN) + Math.cos(a * i - RADIAN))) / 2,
77
+ ((ry - yRatio) * (Math.sin(a * (i + 1) - RADIAN) + Math.sin(a * i - RADIAN))) / 2
78
+ )
79
+ }
80
+ // ratio /= 1.5;
81
+ ctx.closePath()
82
+ ctx.restore()
83
+ }
84
+
85
+ get controls() {
86
+ var { cx, cy, ry, ratio } = this.state
87
+
88
+ return [
89
+ {
90
+ x: cx,
91
+ y: cy - ry + ry * (ratio / 100),
92
+ handler: controlHandler
93
+ }
94
+ ]
95
+ }
96
+
97
+ get nature() {
98
+ return NATURE
99
+ }
100
+ }
101
+
102
+ Component.memoize(Star.prototype, 'controls', false)
103
+
104
+ Component.register('star', Star)
@@ -0,0 +1,15 @@
1
+ const audio = new URL('../../icons/audio.png', import.meta.url).href
2
+
3
+ export default {
4
+ type: 'audio',
5
+ description: 'audio',
6
+ icon: audio,
7
+ group: 'textAndMedia',
8
+ model: {
9
+ type: 'audio',
10
+ left: 100,
11
+ top: 100,
12
+ width: 100,
13
+ height: 100
14
+ }
15
+ }
@@ -0,0 +1,23 @@
1
+ const colorImage = new URL('../../icons/color-image.png', import.meta.url).href
2
+
3
+ export default {
4
+ type: 'color image',
5
+ description: 'color image',
6
+ icon: colorImage,
7
+ group: 'textAndMedia',
8
+ model: {
9
+ type: 'image-view',
10
+ left: 100,
11
+ top: 100,
12
+ width: 100,
13
+ height: 100,
14
+ isGray: false,
15
+ fillStyle: '#fff',
16
+ strokeStyle: '#000',
17
+ alpha: 1,
18
+ hidden: false,
19
+ lineWidth: 1,
20
+ lineDash: 'solid',
21
+ lineCap: 'butt'
22
+ }
23
+ }
@@ -0,0 +1,23 @@
1
+ const donut = new URL('../../icons/donut.png', import.meta.url).href
2
+
3
+ export default {
4
+ type: 'donut',
5
+ description: 'donut shape',
6
+ icon: donut,
7
+ group: 'shape',
8
+ model: {
9
+ type: 'donut',
10
+ rx: 50,
11
+ ry: 50,
12
+ cx: 150,
13
+ cy: 150,
14
+ ratio: 30,
15
+ fillStyle: '#fff',
16
+ strokeStyle: '#000',
17
+ alpha: 1,
18
+ hidden: false,
19
+ lineWidth: 1,
20
+ lineDash: 'solid',
21
+ lineCap: 'butt'
22
+ }
23
+ }