@twick/canvas 0.14.0 → 0.14.3
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/README.md +150 -130
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +39 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
- package/LICENSE +0 -197
package/README.md
CHANGED
|
@@ -1,130 +1,150 @@
|
|
|
1
|
-
# @twick/canvas
|
|
2
|
-
|
|
3
|
-
A React-based canvas library built with Fabric.js for video and image manipulation.
|
|
4
|
-
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
- `
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
- `
|
|
113
|
-
- `
|
|
114
|
-
- `
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
1
|
+
# @twick/canvas
|
|
2
|
+
|
|
3
|
+
A React-based canvas library built with Fabric.js for video and image manipulation.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides a comprehensive canvas solution for video and image editing, built on top of Fabric.js with React integration. It offers advanced manipulation capabilities for creating professional video editing applications.
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- Browser environment with Canvas and Video support
|
|
12
|
+
- React 18 or higher
|
|
13
|
+
- Fabric.js 6.6.2 or higher
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @twick/canvas
|
|
19
|
+
# or
|
|
20
|
+
pnpm add @twick/canvas
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Basic Canvas Setup
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { useTwickCanvas } from '@twick/canvas';
|
|
29
|
+
import { useRef, useEffect } from 'react';
|
|
30
|
+
|
|
31
|
+
function CustomCanvas() {
|
|
32
|
+
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
33
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
34
|
+
|
|
35
|
+
const { twickCanvas, buildCanvas, addElementToCanvas } = useTwickCanvas({
|
|
36
|
+
onCanvasReady: (canvas) => {
|
|
37
|
+
console.log("Canvas ready", canvas);
|
|
38
|
+
},
|
|
39
|
+
onCanvasOperation: (operation, data) => {
|
|
40
|
+
console.log("Canvas operation", operation, data);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const container = containerRef.current;
|
|
46
|
+
const canvasSize = {
|
|
47
|
+
width: container?.clientWidth,
|
|
48
|
+
height: container?.clientHeight,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
buildCanvas({
|
|
52
|
+
videoSize: {
|
|
53
|
+
width: 720,
|
|
54
|
+
height: 1280,
|
|
55
|
+
},
|
|
56
|
+
canvasSize,
|
|
57
|
+
canvasRef: canvasRef.current,
|
|
58
|
+
});
|
|
59
|
+
}, []);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div ref={containerRef}>
|
|
63
|
+
<canvas ref={canvasRef} />
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Adding Elements
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
// Add an image
|
|
73
|
+
const imageElement = {
|
|
74
|
+
type: "image",
|
|
75
|
+
id: "image-1",
|
|
76
|
+
frame: {
|
|
77
|
+
size: [400, 300],
|
|
78
|
+
},
|
|
79
|
+
props: {
|
|
80
|
+
src: "https://example.com/image.jpg",
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
addElementToCanvas({ element: imageElement, index: 0 });
|
|
85
|
+
|
|
86
|
+
// Add text
|
|
87
|
+
const textElement = {
|
|
88
|
+
type: "text",
|
|
89
|
+
id: "text-1",
|
|
90
|
+
props: {
|
|
91
|
+
x: 100,
|
|
92
|
+
y: 100,
|
|
93
|
+
text: "Hello World",
|
|
94
|
+
fontSize: 64,
|
|
95
|
+
fill: "#FFFFFF",
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
addElementToCanvas({ element: textElement, index: 1 });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## API Reference
|
|
103
|
+
|
|
104
|
+
### Hooks
|
|
105
|
+
|
|
106
|
+
- `useTwickCanvas`: Custom hook for canvas manipulation
|
|
107
|
+
|
|
108
|
+
### Helpers
|
|
109
|
+
|
|
110
|
+
- `createCanvas`: Create a new Fabric.js canvas instance
|
|
111
|
+
- `reorderElementsByZIndex`: Reorder canvas elements by z-index
|
|
112
|
+
- `getCurrentFrameEffect`: Get current frame effect
|
|
113
|
+
- `convertToCanvasPosition`: Convert video coordinates to canvas coordinates
|
|
114
|
+
- `convertToVideoPosition`: Convert canvas coordinates to video coordinates
|
|
115
|
+
|
|
116
|
+
### Types
|
|
117
|
+
|
|
118
|
+
- `CanvasProps`: Canvas configuration props
|
|
119
|
+
- `CanvasMetadata`: Canvas metadata interface
|
|
120
|
+
- `FrameEffect`: Frame effect interface
|
|
121
|
+
- `CanvasElement`: Canvas element interface
|
|
122
|
+
- `CanvasElementProps`: Canvas element props interface
|
|
123
|
+
- `CaptionProps`: Caption configuration props
|
|
124
|
+
|
|
125
|
+
For complete API documentation, refer to the generated documentation.
|
|
126
|
+
|
|
127
|
+
## Browser Support
|
|
128
|
+
|
|
129
|
+
This library requires a browser environment with support for:
|
|
130
|
+
- HTML5 Canvas
|
|
131
|
+
- HTML5 Video
|
|
132
|
+
- Modern JavaScript features (ES2020+)
|
|
133
|
+
|
|
134
|
+
The library will throw appropriate errors if used in an unsupported environment.
|
|
135
|
+
|
|
136
|
+
## Documentation
|
|
137
|
+
|
|
138
|
+
For complete documentation, refer to the project documentation site.
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
This package is licensed under the **Sustainable Use License (SUL) Version 1.0**.
|
|
143
|
+
|
|
144
|
+
- Free for use in commercial and non-commercial apps
|
|
145
|
+
- Can be modified and self-hosted
|
|
146
|
+
- Cannot be sold, rebranded, or distributed as a standalone SDK
|
|
147
|
+
|
|
148
|
+
For commercial licensing inquiries, contact: contact@kifferai.com
|
|
149
|
+
|
|
150
|
+
For full license terms, see the main LICENSE.md file in the project root.
|
package/dist/index.js
CHANGED
|
@@ -3,36 +3,61 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const fabric = require("fabric");
|
|
4
4
|
const react = require("react");
|
|
5
5
|
const DEFAULT_TEXT_PROPS = {
|
|
6
|
+
/** Font family for text elements */
|
|
6
7
|
family: "Poppins",
|
|
8
|
+
/** Font size in pixels */
|
|
7
9
|
size: 48,
|
|
10
|
+
/** Text fill color */
|
|
8
11
|
fill: "#FFFFFF",
|
|
12
|
+
/** Text stroke color */
|
|
9
13
|
stroke: "#000000",
|
|
14
|
+
/** Stroke line width */
|
|
10
15
|
lineWidth: 0
|
|
11
16
|
};
|
|
12
17
|
const DEFAULT_CAPTION_PROPS = {
|
|
18
|
+
/** Font family for caption elements */
|
|
13
19
|
family: "Poppins",
|
|
20
|
+
/** Font size in pixels */
|
|
14
21
|
size: 48,
|
|
22
|
+
/** Text fill color */
|
|
15
23
|
fill: "#FFFFFF",
|
|
24
|
+
/** Font weight */
|
|
16
25
|
fontWeight: 600,
|
|
26
|
+
/** Text stroke color */
|
|
17
27
|
stroke: "#000000",
|
|
28
|
+
/** Stroke line width */
|
|
18
29
|
lineWidth: 0.2,
|
|
30
|
+
/** Shadow color */
|
|
19
31
|
shadowColor: "#000000",
|
|
32
|
+
/** Shadow blur radius */
|
|
20
33
|
shadowBlur: 2,
|
|
34
|
+
/** Shadow offset [x, y] */
|
|
21
35
|
shadowOffset: [0, 0]
|
|
22
36
|
};
|
|
23
37
|
const CANVAS_OPERATIONS = {
|
|
38
|
+
/** An item has been selected on the canvas */
|
|
24
39
|
ITEM_SELECTED: "ITEM_SELECTED",
|
|
40
|
+
/** An item has been updated/modified on the canvas */
|
|
25
41
|
ITEM_UPDATED: "ITEM_UPDATED",
|
|
42
|
+
/** An item has been deleted from the canvas */
|
|
26
43
|
ITEM_DELETED: "ITEM_DELETED",
|
|
44
|
+
/** A new item has been added to the canvas */
|
|
27
45
|
ITEM_ADDED: "ITEM_ADDED",
|
|
46
|
+
/** Items have been grouped together */
|
|
28
47
|
ITEM_GROUPED: "ITEM_GROUPED",
|
|
48
|
+
/** Items have been ungrouped */
|
|
29
49
|
ITEM_UNGROUPED: "ITEM_UNGROUPED"
|
|
30
50
|
};
|
|
31
51
|
const ELEMENT_TYPES = {
|
|
52
|
+
/** Text element type */
|
|
32
53
|
TEXT: "text",
|
|
54
|
+
/** Caption element type */
|
|
33
55
|
CAPTION: "caption",
|
|
56
|
+
/** Image element type */
|
|
34
57
|
IMAGE: "image",
|
|
58
|
+
/** Video element type */
|
|
35
59
|
VIDEO: "video",
|
|
60
|
+
/** Rectangle element type */
|
|
36
61
|
RECT: "rect"
|
|
37
62
|
};
|
|
38
63
|
const isBrowser = typeof window !== "undefined";
|
|
@@ -135,14 +160,21 @@ const getCurrentFrameEffect = (item, seekTime) => {
|
|
|
135
160
|
return currentFrameEffect;
|
|
136
161
|
};
|
|
137
162
|
const disabledControl = new fabric.Control({
|
|
163
|
+
/** X position offset */
|
|
138
164
|
x: 0,
|
|
165
|
+
/** Y position offset */
|
|
139
166
|
y: -0.5,
|
|
167
|
+
/** Additional Y offset */
|
|
140
168
|
offsetY: 0,
|
|
169
|
+
/** Cursor style when hovering */
|
|
141
170
|
cursorStyle: "pointer",
|
|
171
|
+
/** Action handler that does nothing */
|
|
142
172
|
actionHandler: () => {
|
|
143
173
|
return true;
|
|
144
174
|
},
|
|
175
|
+
/** Name of the action */
|
|
145
176
|
actionName: "scale",
|
|
177
|
+
/** Render function for the control */
|
|
146
178
|
render: function(ctx, left, top) {
|
|
147
179
|
const size = 0;
|
|
148
180
|
ctx.save();
|
|
@@ -153,12 +185,19 @@ const disabledControl = new fabric.Control({
|
|
|
153
185
|
}
|
|
154
186
|
});
|
|
155
187
|
const rotateControl = new fabric.Control({
|
|
188
|
+
/** X position offset */
|
|
156
189
|
x: 0,
|
|
190
|
+
/** Y position offset */
|
|
157
191
|
y: -0.5,
|
|
192
|
+
/** Additional Y offset for positioning */
|
|
158
193
|
offsetY: -25,
|
|
194
|
+
/** Cursor style when hovering */
|
|
159
195
|
cursorStyle: "crosshair",
|
|
196
|
+
/** Action handler with rotation and snapping */
|
|
160
197
|
actionHandler: fabric.controlsUtils.rotationWithSnapping,
|
|
198
|
+
/** Name of the action */
|
|
161
199
|
actionName: "rotate",
|
|
200
|
+
/** Whether to show connection line */
|
|
162
201
|
withConnection: true
|
|
163
202
|
});
|
|
164
203
|
const getThumbnail = async (videoUrl, seekTime = 0.1, playbackRate = 1) => {
|