@cs-open/react-fabric 0.0.12 → 0.0.14
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 +18 -13
- package/dist/cjs/components/BackgroundImage/index.cjs +1 -1
- package/dist/cjs/components/BackgroundImage/index.cjs.map +1 -1
- package/dist/cjs/components/IText/index.cjs.map +1 -1
- package/dist/cjs/components/Objects/index.cjs.map +1 -1
- package/dist/cjs/components/Text/index.cjs +1 -1
- package/dist/cjs/components/Text/index.cjs.map +1 -1
- package/dist/cjs/container/ReactFabric/index.cjs +1 -1
- package/dist/cjs/container/ReactFabric/index.cjs.map +1 -1
- package/dist/esm/components/BackgroundImage/index.mjs +1 -1
- package/dist/esm/components/BackgroundImage/index.mjs.map +1 -1
- package/dist/esm/components/IText/index.mjs +1 -1
- package/dist/esm/components/IText/index.mjs.map +1 -1
- package/dist/esm/components/Objects/index.mjs.map +1 -1
- package/dist/esm/components/Text/index.mjs +1 -1
- package/dist/esm/components/Text/index.mjs.map +1 -1
- package/dist/esm/container/ReactFabric/index.mjs +1 -1
- package/dist/esm/container/ReactFabric/index.mjs.map +1 -1
- package/dist/types/components/BackgroundImage/index.d.ts +5 -1
- package/dist/types/components/BackgroundImage/index.d.ts.map +1 -1
- package/dist/types/components/Objects/index.d.ts.map +1 -1
- package/dist/types/components/Text/index.d.ts +6 -2
- package/dist/types/components/Text/index.d.ts.map +1 -1
- package/dist/types/container/ReactFabric/index.d.ts +105 -22
- package/dist/types/container/ReactFabric/index.d.ts.map +1 -1
- package/dist/types/types/canvas.d.ts +3 -2
- package/dist/types/types/canvas.d.ts.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
React 组件库,基于 Fabric.js 构建,提供强大的 Canvas 绘图功能。
|
|
4
4
|
|
|
5
|
+
<img width="1770" height="1478" alt="react-fabric demo" src="https://github.com/user-attachments/assets/02ff8152-bad3-4e99-82db-13eefc5413b0" />
|
|
6
|
+
|
|
5
7
|
## 安装
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -12,19 +14,6 @@ yarn add @cs-open/react-fabric
|
|
|
12
14
|
pnpm add @cs-open/react-fabric
|
|
13
15
|
```
|
|
14
16
|
|
|
15
|
-
## 依赖要求
|
|
16
|
-
|
|
17
|
-
### 必需依赖
|
|
18
|
-
|
|
19
|
-
以下依赖会自动安装:
|
|
20
|
-
|
|
21
|
-
- `fabric` - Fabric.js 核心库
|
|
22
|
-
- `react` - React 框架
|
|
23
|
-
- `react-dom` - React DOM 渲染器
|
|
24
|
-
- `zustand` - 状态管理
|
|
25
|
-
- `@floating-ui/core` - 浮动 UI 组件
|
|
26
|
-
- `use-sync-external-store` - 同步外部存储
|
|
27
|
-
|
|
28
17
|
### 可选依赖
|
|
29
18
|
|
|
30
19
|
某些插件需要额外的依赖才能正常工作:
|
|
@@ -130,3 +119,19 @@ DOM control
|
|
|
130
119
|
## 许可证
|
|
131
120
|
|
|
132
121
|
MIT
|
|
122
|
+
|
|
123
|
+
```jsx
|
|
124
|
+
pnpm run changeset // 修改 changeset.md
|
|
125
|
+
全选 changed & unchanged enter
|
|
126
|
+
不选 enter major
|
|
127
|
+
不选 enter minor
|
|
128
|
+
Summary 随便写
|
|
129
|
+
desired changeset ? true
|
|
130
|
+
pnpm run version-packages // 修改 package.json 的 version
|
|
131
|
+
pnpm install // 修改 lock 文件
|
|
132
|
+
git add .
|
|
133
|
+
git commit -m 'chore(core): version bump'
|
|
134
|
+
git push
|
|
135
|
+
提交pr到main
|
|
136
|
+
通过 github action 自动发布到 npm
|
|
137
|
+
```
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var f=require("fabric"),c=require("react"),q=require("../../hooks/useDidUpdate.cjs"),w=require("../../hooks/useStore.cjs");const A=a=>({width:a.width,height:a.height}),E=c.forwardRef(({src:a,onLoad:S,onScaling:j,onError:T,scaleToFit:l,scaleToCover:g,...d},k)=>{const t=c.useRef(null),o=w.useStoreApi(),h=c.useRef(a),{width:p,height:I}=w.useStore(A),m=c.useCallback(i=>{const{canvas:r,manualZoom:e=1,defaultCentered:n}=o.getState();if(!t.current)return;if(!r){console.warn("updateViewport: !canvas");return}if(!r.backgroundImage){console.warn("updateViewport: !canvas.backgroundImage");return}const u=i.scaleToFit?f.util.findScaleToFit(t.current,r):i.scaleToCover?f.util.findScaleToCover(t.current,r):1,s=u*e;r.setViewportTransform([s,0,0,s,0,0]);let v=0,b=0;if(n&&r.backgroundImage){const R=r.backgroundImage.width||0,C=r.backgroundImage.height||0;v=(r.width-R*s)/2,b=(r.height-C*s)/2}const F=[s,0,0,s,v,b];r.setViewportTransform(F),r.requestRenderAll(),o.setState({fitZoom:u,manualZoom:e,zoom:s})},[o]);return c.useEffect(()=>{m({scaleToFit:l,scaleToCover:g})},[p,I,l,g,m,o]),c.useEffect(()=>{if(!a){console.warn("ReactFabricBackgroundImage: !src");return}const{domNode:i,setLoading:r}=o.getState();return r(!0),h.current=a,f.FabricImage.fromURL(a,{crossOrigin:"anonymous"}).then(e=>{if(S?.(e),e.getSrc()!==h.current)return;const{canvas:n}=o.getState();if(n){const u={...d,angle:0};if(e.set({...u,objectCaching:!1}),n.getContext().imageSmoothingEnabled=!0,n.getContext().imageSmoothingQuality="high",n.backgroundImage=e,t.current=e,requestAnimationFrame(()=>{m({scaleToFit:l,scaleToCover:g})}),!n.viewportTransform){console.warn("!viewport");return}}else console.warn("ReactFabric:BackgroundImage: !canvas",n)}).catch(e=>{T?.(e),console.error("[ReactFabric] BackgroundImage: fromURL error",e)}).finally(()=>{i&&(i.dataset.src=a),r(!1)}),()=>{const{canvas:e}=o.getState();e?.backgroundImage&&(e.backgroundImage=void 0,e.remove(t.current),t.current=null,e.renderAll())}},[a]),q.useDidUpdate(()=>{const{canvas:i}=o.getState();t.current&&(Object.entries(d).forEach(([r,e])=>{r==="angle"?t.current?.rotate(e):t.current?.set(r,e)}),i?.requestRenderAll())},[d,o]),c.useImperativeHandle(k,()=>({instance:t.current})),null});var L=c.memo(E);exports.default=L;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/components/BackgroundImage/index.tsx"],"sourcesContent":["import type {\n BasicTransformEvent,\n ImageProps,\n ObjectEvents,\n SerializedImageProps,\n TDegree,\n TPointerEvent,\n} from 'fabric'\nimport { FabricImage, util } from 'fabric'\nimport { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef } from 'react'\nimport { useDidUpdate } from '../../hooks/useDidUpdate'\nimport { useStore, useStoreApi } from '../../hooks/useStore'\nimport type { ReactFabricState } from '../../types/store'\n\nexport type Handle = {}\n\ntype ScaleMode = {\n scaleToFit?: boolean\n scaleToCover?: boolean\n}\nexport type BackgroundImageProps = Partial<ImageProps> & {\n src: string\n onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void\n onScaling?: (scale: BasicTransformEvent<TPointerEvent>) => void\n\n /** 自动缩放至容器宽高 */\n} & ScaleMode\n\nconst selector = (s: ReactFabricState) => ({\n width: s.width,\n height: s.height,\n})\n\nconst BackgroundImage = forwardRef<Handle, BackgroundImageProps>(\n ({ src, onLoad, onScaling, scaleToFit, scaleToCover, ...options }, ref) => {\n const backgroundImageRef = useRef<FabricImage | null>(null)\n\n const store = useStoreApi()\n\n const { width, height } = useStore(selector)\n\n const updateViewport = useCallback(\n (params: { scaleToFit?: boolean; scaleToCover?: boolean }) => {\n const { canvas, manualZoom = 1, defaultCentered } = store.getState()\n if (!backgroundImageRef.current) {\n return\n }\n if (!canvas) {\n console.warn('updateViewport: !canvas')\n return\n }\n if (!canvas.backgroundImage) {\n console.warn('updateViewport: !canvas.backgroundImage')\n return\n }\n\n // 1. 计算缩放\n const fitZoom = params.scaleToFit\n ? util.findScaleToFit(backgroundImageRef.current, canvas)\n : params.scaleToCover\n ? util.findScaleToCover(backgroundImageRef.current, canvas)\n : 1\n\n const combinedZoom = fitZoom * manualZoom\n\n // 2. 先应用基础缩放\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n\n // 3. 如果需要居中,计算偏移量\n let deltaX = 0\n let deltaY = 0\n\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n // const canvasCenter = {\n // x: canvas.width! / 2,\n // y: canvas.height! / 2,\n // }\n // const bgCenter = {\n // x:\n // (canvas.backgroundImage.left! + (canvas.backgroundImage.width! * canvas.backgroundImage.scaleX!) / 2) *\n // combinedZoom,\n // y:\n // (canvas.backgroundImage.top! + (canvas.backgroundImage.height! * canvas.backgroundImage.scaleY!) / 2) *\n // combinedZoom,\n // }\n // deltaX = canvasCenter.x - bgCenter.x\n // deltaY = canvasCenter.y - bgCenter.y\n }\n\n // 4. 应用最终变换\n const finalTransform: [number, number, number, number, number, number] = [\n combinedZoom,\n 0,\n 0,\n combinedZoom,\n deltaX,\n deltaY,\n ]\n\n canvas.setViewportTransform(finalTransform)\n canvas.requestRenderAll()\n\n // 5. 更新 store\n store.setState({\n fitZoom,\n manualZoom,\n zoom: combinedZoom,\n })\n },\n [store],\n )\n\n // 监听 width, height 的变化\n useEffect(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n }, [width, height, scaleToFit, scaleToCover, updateViewport, store])\n\n useEffect(() => {\n if (!src) {\n console.warn('ReactFabricBackgroundImage: !src')\n return\n }\n const { domNode, setLoading } = store.getState()\n setLoading(true)\n FabricImage.fromURL(src, { crossOrigin: 'anonymous' })\n .then(imageSource => {\n const currentSrc = imageSource.getSrc()\n const latestSrc = backgroundImageRef.current?.getSrc()\n\n if (latestSrc && currentSrc !== latestSrc) {\n return\n }\n\n const { canvas } = store.getState()\n if (canvas) {\n // 初始化时角度的旋转,一定要放到 updateViewport 之后;先画正图片,再进行旋转\n const removeAngleOptions = { ...options, angle: 0 }\n imageSource.set({\n ...removeAngleOptions,\n objectCaching: false,\n })\n canvas.getContext().imageSmoothingEnabled = true\n canvas.getContext().imageSmoothingQuality = 'high'\n canvas.backgroundImage = imageSource\n backgroundImageRef.current = imageSource\n\n requestAnimationFrame(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n })\n\n const viewport = canvas.viewportTransform\n if (!viewport) {\n console.warn('!viewport')\n return\n }\n\n // imageSource.angle = options.angle || 0\n onLoad?.(imageSource)\n } else {\n console.warn('ReactFabric:BackgroundImage: !canvas', canvas)\n }\n })\n .catch(console.error)\n .finally(() => {\n if (domNode) domNode.dataset.src = src\n setLoading(false)\n })\n\n return () => {\n const { canvas } = store.getState()\n if (canvas?.backgroundImage) {\n canvas.backgroundImage = undefined\n canvas.remove(backgroundImageRef.current!)\n backgroundImageRef.current = null\n canvas.renderAll()\n }\n }\n }, [src])\n\n useDidUpdate(() => {\n const { canvas } = store.getState()\n\n if (backgroundImageRef.current) {\n Object.entries(options).forEach(([key, value]) => {\n if (key === 'angle') {\n backgroundImageRef.current?.rotate(value as TDegree)\n } else {\n backgroundImageRef.current?.set(key, value)\n }\n })\n canvas?.requestRenderAll()\n }\n }, [options, store])\n\n useImperativeHandle(ref, () => ({\n // 是最新的?\n instance: backgroundImageRef.current,\n }))\n\n return null\n },\n)\n\nexport default memo(BackgroundImage)\n"],"names":["selector","s","BackgroundImage","forwardRef","src","onLoad","onScaling","scaleToFit","scaleToCover","options","ref","backgroundImageRef","useRef","store","useStoreApi","width","height","useStore","updateViewport","useCallback","params","canvas","manualZoom","defaultCentered","fitZoom","util","combinedZoom","deltaX","deltaY","bgWidth","bgHeight","finalTransform","useEffect","domNode","setLoading","FabricImage","imageSource","currentSrc","latestSrc","removeAngleOptions","useDidUpdate","key","value","useImperativeHandle","memo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/BackgroundImage/index.tsx"],"sourcesContent":["import type {\n BasicTransformEvent,\n ImageProps,\n ObjectEvents,\n SerializedImageProps,\n TDegree,\n TPointerEvent,\n} from 'fabric'\nimport { FabricImage, util } from 'fabric'\nimport { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef } from 'react'\nimport { useDidUpdate } from '../../hooks/useDidUpdate'\nimport { useStore, useStoreApi } from '../../hooks/useStore'\nimport type { ReactFabricState } from '../../types/store'\n\nexport type Handle = {\n instance: FabricImage | null\n}\n\ntype ScaleMode = {\n scaleToFit?: boolean\n scaleToCover?: boolean\n}\nexport type BackgroundImageProps = Partial<ImageProps> & {\n src: string\n onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void\n onScaling?: (scale: BasicTransformEvent<TPointerEvent>) => void\n onError?: (e: any) => void\n\n /** 自动缩放至容器宽高 */\n} & ScaleMode\n\nconst selector = (s: ReactFabricState) => ({\n width: s.width,\n height: s.height,\n})\n\nconst BackgroundImage = forwardRef<Handle, BackgroundImageProps>(\n ({ src, onLoad, onScaling, onError, scaleToFit, scaleToCover, ...options }, ref) => {\n const backgroundImageRef = useRef<FabricImage | null>(null)\n\n const store = useStoreApi()\n const newestSrcRef = useRef(src)\n\n const { width, height } = useStore(selector)\n\n const updateViewport = useCallback(\n (params: { scaleToFit?: boolean; scaleToCover?: boolean }) => {\n const { canvas, manualZoom = 1, defaultCentered } = store.getState()\n if (!backgroundImageRef.current) {\n return\n }\n if (!canvas) {\n console.warn('updateViewport: !canvas')\n return\n }\n if (!canvas.backgroundImage) {\n console.warn('updateViewport: !canvas.backgroundImage')\n return\n }\n\n // 1. 计算缩放\n const fitZoom = params.scaleToFit\n ? util.findScaleToFit(backgroundImageRef.current, canvas)\n : params.scaleToCover\n ? util.findScaleToCover(backgroundImageRef.current, canvas)\n : 1\n\n const combinedZoom = fitZoom * manualZoom\n\n // 2. 先应用基础缩放\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n\n // 3. 如果需要居中,计算偏移量\n let deltaX = 0\n let deltaY = 0\n\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n // const canvasCenter = {\n // x: canvas.width! / 2,\n // y: canvas.height! / 2,\n // }\n // const bgCenter = {\n // x:\n // (canvas.backgroundImage.left! + (canvas.backgroundImage.width! * canvas.backgroundImage.scaleX!) / 2) *\n // combinedZoom,\n // y:\n // (canvas.backgroundImage.top! + (canvas.backgroundImage.height! * canvas.backgroundImage.scaleY!) / 2) *\n // combinedZoom,\n // }\n // deltaX = canvasCenter.x - bgCenter.x\n // deltaY = canvasCenter.y - bgCenter.y\n }\n\n // 4. 应用最终变换\n const finalTransform: [number, number, number, number, number, number] = [\n combinedZoom,\n 0,\n 0,\n combinedZoom,\n deltaX,\n deltaY,\n ]\n\n canvas.setViewportTransform(finalTransform)\n canvas.requestRenderAll()\n\n // 5. 更新 store\n store.setState({\n fitZoom,\n manualZoom,\n zoom: combinedZoom,\n })\n },\n [store],\n )\n\n // 监听 width, height 的变化\n useEffect(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n }, [width, height, scaleToFit, scaleToCover, updateViewport, store])\n\n useEffect(() => {\n if (!src) {\n console.warn('ReactFabricBackgroundImage: !src')\n return\n }\n const { domNode, setLoading } = store.getState()\n setLoading(true)\n newestSrcRef.current = src\n\n FabricImage.fromURL(src, { crossOrigin: 'anonymous' })\n .then(imageSource => {\n onLoad?.(imageSource)\n const currentSrc = imageSource.getSrc()\n\n if (currentSrc !== newestSrcRef.current) {\n return\n }\n\n const { canvas } = store.getState()\n if (canvas) {\n // 初始化时角度的旋转,一定要放到 updateViewport 之后;先画正图片,再进行旋转\n const removeAngleOptions = { ...options, angle: 0 }\n imageSource.set({\n ...removeAngleOptions,\n objectCaching: false,\n })\n canvas.getContext().imageSmoothingEnabled = true\n canvas.getContext().imageSmoothingQuality = 'high'\n canvas.backgroundImage = imageSource\n backgroundImageRef.current = imageSource\n\n requestAnimationFrame(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n })\n\n const viewport = canvas.viewportTransform\n if (!viewport) {\n console.warn('!viewport')\n return\n }\n\n // imageSource.angle = options.angle || 0\n } else {\n console.warn('ReactFabric:BackgroundImage: !canvas', canvas)\n }\n })\n .catch(e => {\n onError?.(e)\n console.error('[ReactFabric] BackgroundImage: fromURL error', e)\n })\n .finally(() => {\n if (domNode) domNode.dataset.src = src\n setLoading(false)\n })\n\n return () => {\n const { canvas } = store.getState()\n if (canvas?.backgroundImage) {\n canvas.backgroundImage = undefined\n canvas.remove(backgroundImageRef.current!)\n backgroundImageRef.current = null\n canvas.renderAll()\n }\n }\n }, [src])\n\n useDidUpdate(() => {\n const { canvas } = store.getState()\n\n if (backgroundImageRef.current) {\n Object.entries(options).forEach(([key, value]) => {\n if (key === 'angle') {\n backgroundImageRef.current?.rotate(value as TDegree)\n } else {\n backgroundImageRef.current?.set(key, value)\n }\n })\n canvas?.requestRenderAll()\n }\n }, [options, store])\n\n useImperativeHandle(ref, () => ({\n // 是最新的?\n instance: backgroundImageRef.current,\n }))\n\n return null\n },\n)\n\nexport default memo(BackgroundImage)\n"],"names":["selector","s","BackgroundImage","forwardRef","src","onLoad","onScaling","onError","scaleToFit","scaleToCover","options","ref","backgroundImageRef","useRef","store","useStoreApi","newestSrcRef","width","height","useStore","updateViewport","useCallback","params","canvas","manualZoom","defaultCentered","fitZoom","util","combinedZoom","deltaX","deltaY","bgWidth","bgHeight","finalTransform","useEffect","domNode","setLoading","FabricImage","imageSource","removeAngleOptions","useDidUpdate","key","value","useImperativeHandle","memo"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/components/IText/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { IText, util, Point } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type ITextProps<T = unknown> = Partial<ConstructorParameters<typeof IText>[1] & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n children?: ReactNode\n} & T\n\nIText.prototype.set({\n _getNonTransformedDimensions() {\n // Object dimensions\n return new Point(this.width, this.height).scalarAdd(this.padding)\n },\n _calculateCurrentDimensions() {\n // Controls dimensions\n return util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true)\n },\n})\n\nconst ITextBox = forwardRef<IText | undefined, ITextProps>(({ group, text, children, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: IText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n})\n\nexport default memo(ITextBox)\n"],"names":["IText","Point","util","ITextBox","forwardRef","group","text","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","useImperativeHandle","useInstancePosition","
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/IText/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { IText, util, Point } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type ITextProps<T = unknown> = Partial<ConstructorParameters<typeof IText>[1] & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n children?: ReactNode\n} & T\n\nIText.prototype.set({\n _getNonTransformedDimensions() {\n // Object dimensions\n return new Point(this.width, this.height).scalarAdd(this.padding)\n },\n _calculateCurrentDimensions() {\n // Controls dimensions\n return util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true)\n },\n})\n\nconst ITextBox = forwardRef<IText | undefined, ITextProps>(({ group, text, children, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: IText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n})\n\nexport default memo(ITextBox)\n"],"names":["IText","Point","util","ITextBox","forwardRef","group","text","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","useImperativeHandle","useInstancePosition","a","memo"],"mappings":"wPAcAA,EAAAA,MAAM,UAAU,IAAI,CAClB,8BAA+B,CAE7B,OAAO,IAAIC,EAAM,MAAA,KAAK,MAAO,KAAK,MAAM,EAAE,UAAU,KAAK,OAAO,CAClE,EACA,6BAA8B,CAE5B,OAAOC,EAAAA,KAAK,eAAe,KAAK,4BAA6B,KAAK,uBAAwB,EAAI,CAChG,CACF,CAAC,EAED,MAAMC,EAAWC,EAA0C,WAAA,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAM,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACvG,KAAM,CAACC,EAAWC,CAAU,EAAIC,gBAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,gBAAA,CAC/B,YAAad,EACb,MAAA,MAAOM,EACP,WAAAK,EACA,MAAAN,EACA,UAAAK,CACF,CAAC,EAED,OAAAK,sBAAoBN,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5CG,EAAoBH,oBAAAA,EAAUN,CAAQ,CAC/C,CAAC,EAED,IAAAU,EAAeC,EAAAA,KAAKf,CAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/components/Objects/index.tsx"],"sourcesContent":["import { memo } from 'react'\nimport Path from '../Path'\nimport Text from '../Text'\nimport Rect from '../Rect'\nimport Line from '../Line'\nimport IText from '../IText'\n\nexport type ObjectsProps = {\n objects: { type: string;[index: string]: any }[]\n}\n\nconst Objects = ({ objects }: ObjectsProps) => {\n const components = {\n rect: Rect,\n path: Path,\n text: Text,\n line: Line,\n 'i-text': Text,\n itext: IText,\n }\n\n if (!objects) return null\n return (\n <>\n {objects?.map(({ type, ...options }) => {\n const Component = components[type.toLowerCase() as keyof typeof components]\n if (!Component) {\n return null\n }\n return <Component {...options} />\n })}\n </>\n )\n}\n\nexport default memo(Objects)\n"],"names":["Objects","objects","components","Rect","Path","Text","Line","IText","jsx","Fragment","type","options","Component","memo"],"mappings":"sRAWA,MAAMA,EAAU,CAAC,CAAE,QAAAC,CAAQ,IAAoB,CAC7C,MAAMC,EAAa,CACjB,KAAMC,EAAAA,QACN,KAAMC,UACN,KAAMC,UACN,KAAMC,EACN,QAAA,SAAUD,EAAAA,QACV,MAAOE,EAAAA,OACT,EAEA,OAAKN,EAEHO,EAAAA,IAAAC,EAAAA,SAAA,CACG,SAAAR,GAAS,IAAI,CAAC,CAAE,KAAAS,EAAM,GAAGC,CAAQ,IAAM,CACtC,MAAMC,EAAYV,EAAWQ,EAAK,YAAwC,CAAA,EAC1E,OAAKE,EAGEJ,EAAAA,IAACI,EAAA,CAAW,
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/Objects/index.tsx"],"sourcesContent":["import { memo } from 'react'\nimport Path from '../Path'\nimport Text from '../Text'\nimport Rect from '../Rect'\nimport Line from '../Line'\nimport IText from '../IText'\n\nexport type ObjectsProps = {\n objects: { type: string; [index: string]: any }[]\n}\n\nconst Objects = ({ objects }: ObjectsProps) => {\n const components = {\n rect: Rect,\n path: Path,\n text: Text,\n line: Line,\n 'i-text': Text,\n itext: IText,\n }\n\n if (!objects) return null\n return (\n <>\n {objects?.map(({ type, ...options }) => {\n const Component = components[type.toLowerCase() as keyof typeof components]\n if (!Component) {\n return null\n }\n return <Component {...(options as any)} />\n })}\n </>\n )\n}\n\nexport default memo(Objects)\n"],"names":["Objects","objects","components","Rect","Path","Text","Line","IText","jsx","Fragment","type","options","Component","memo"],"mappings":"sRAWA,MAAMA,EAAU,CAAC,CAAE,QAAAC,CAAQ,IAAoB,CAC7C,MAAMC,EAAa,CACjB,KAAMC,EAAAA,QACN,KAAMC,UACN,KAAMC,UACN,KAAMC,EACN,QAAA,SAAUD,EAAAA,QACV,MAAOE,EAAAA,OACT,EAEA,OAAKN,EAEHO,EAAAA,IAAAC,EAAAA,SAAA,CACG,SAAAR,GAAS,IAAI,CAAC,CAAE,KAAAS,EAAM,GAAGC,CAAQ,IAAM,CACtC,MAAMC,EAAYV,EAAWQ,EAAK,YAAwC,CAAA,EAC1E,OAAKE,EAGEJ,EAAAA,IAACI,EAAA,CAAW,GAAID,EAAiB,EAF/B,IAGX,CAAC,CACH,CAAA,EAVmB,IAYvB,EAEA,IAAeE,EAAAA,EAAAA,KAAKb,CAAO"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("fabric"),i=require("react"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("fabric"),i=require("react"),p=require("../../hooks/useCreateObject.cjs"),h=require("../../hooks/useSplitProps.cjs"),v=require("../../hooks/useStore.cjs"),F=require("fontfaceobserver"),y=require("../../hooks/useInstancePosition.cjs");t.FabricText.prototype.set({_getNonTransformedDimensions(){return new t.Point(this.width,this.height).scalarAdd(this.padding)},_calculateCurrentDimensions(){return t.util.transformPoint(this._getTransformedDimensions(),this.getViewportTransform(),!0)}});const s=i.forwardRef(({group:a,text:n,children:o,...u},c)=>{const l=v.useStoreApi(),[f,e]=h.useSplitProps(u),r=p.useCreateObject({Constructor:t.FabricText,param:n,attributes:e,group:a,listeners:f});return i.useEffect(()=>{const{canvas:m}=l.getState();!e.fontFamily||!r||new F(e.fontFamily).load().then(()=>{r.set({fontFamily:e.fontFamily}),m?.requestRenderAll()}).catch(d=>{console.error(`ReactFabric: \u5B57\u4F53\u52A0\u8F7D\u5931\u8D25: ${e.fontFamily}`,d)})},[e.fontFamily,r]),i.useImperativeHandle(c,()=>r,[r]),y.useInstancePosition(r,o)});s.displayName="Text";var b=i.memo(s);exports.default=b;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/components/Text/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { FabricText, Point, util } from 'fabric'\nimport { forwardRef, memo, useEffect, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport { useStoreApi } from '../../hooks/useStore'\nimport type { AllObjectEvents } from '../../types/object'\nimport FontFaceObserver from 'fontfaceobserver'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type Handle = FabricText | undefined\n\nexport type TextProps<T = unknown> = Partial<
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/Text/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { FabricText, Point, util } from 'fabric'\nimport { forwardRef, memo, useEffect, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport { useStoreApi } from '../../hooks/useStore'\nimport type { AllObjectEvents } from '../../types/object'\nimport FontFaceObserver from 'fontfaceobserver'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type Handle = FabricText | undefined\n\nexport type TextProps<T = unknown> = Partial<FabricText & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n children?: ReactNode\n} & T\n\nFabricText.prototype.set({\n _getNonTransformedDimensions() {\n // Object dimensions\n return new Point(this.width, this.height).scalarAdd(this.padding)\n },\n _calculateCurrentDimensions() {\n // Controls dimensions\n return util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true)\n },\n})\n\nconst Text = forwardRef<Handle, TextProps>(({ group, text, children, ...props }, ref) => {\n const store = useStoreApi()\n\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: FabricText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n /**\n * 字体只有被使用了才会加载;先由 Text 使用一次, 监听加载完成,之后再 set 一次\n */\n useEffect(() => {\n const { canvas } = store.getState()\n if (!attributes.fontFamily || !instance) return\n const font = new FontFaceObserver(attributes.fontFamily)\n font\n .load()\n .then(() => {\n instance.set({\n fontFamily: attributes.fontFamily,\n })\n canvas?.requestRenderAll()\n })\n .catch(error => {\n // 加载失败\n console.error(`ReactFabric: 字体加载失败: ${attributes.fontFamily}`, error)\n })\n }, [attributes.fontFamily, instance])\n\n useImperativeHandle(ref, () => instance, [instance])\n return useInstancePosition(instance, children)\n})\n\nText.displayName = 'Text'\nexport default memo(Text)\n"],"names":["FabricText","Point","util","Text","forwardRef","group","text","children","props","ref","store","useStoreApi","listeners","attributes","useSplitProps","instance","useCreateObject","useEffect","canvas","FontFaceObserver","error","useImperativeHandle","useInstancePosition","memo"],"mappings":"4TAkBAA,EAAAA,WAAW,UAAU,IAAI,CACvB,8BAA+B,CAE7B,OAAO,IAAIC,EAAAA,MAAM,KAAK,MAAO,KAAK,MAAM,EAAE,UAAU,KAAK,OAAO,CAClE,EACA,6BAA8B,CAE5B,OAAOC,EAAAA,KAAK,eAAe,KAAK,4BAA6B,KAAK,qBAAA,EAAwB,EAAI,CAChG,CACF,CAAC,EAED,MAAMC,EAAOC,EAAAA,WAA8B,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAM,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACvF,MAAMC,EAAQC,EAAAA,cAER,CAACC,EAAWC,CAAU,EAAIC,EAAcN,cAAAA,CAAK,EAE7CO,EAAWC,EAAAA,gBAAgB,CAC/B,YAAahB,EAAAA,WACb,MAAOM,EACP,WAAAO,EACA,MAAAR,EACA,UAAAO,CACF,CAAC,EAKD,OAAAK,EAAAA,UAAU,IAAM,CACd,KAAM,CAAE,OAAAC,CAAO,EAAIR,EAAM,SAAA,EACrB,CAACG,EAAW,YAAc,CAACE,GAClB,IAAII,EAAiBN,EAAW,UAAU,EAEpD,KAAK,EACL,KAAK,IAAM,CACVE,EAAS,IAAI,CACX,WAAYF,EAAW,UACzB,CAAC,EACDK,GAAQ,iBACV,CAAA,CAAC,EACA,MAAME,GAAS,CAEd,QAAQ,MAAM,sDAAwBP,EAAW,UAAU,GAAIO,CAAK,CACtE,CAAC,CACL,EAAG,CAACP,EAAW,WAAYE,CAAQ,CAAC,EAEpCM,EAAAA,oBAAoBZ,EAAK,IAAMM,EAAU,CAACA,CAAQ,CAAC,EAC5CO,EAAAA,oBAAoBP,EAAUR,CAAQ,CAC/C,CAAC,EAEDJ,EAAK,YAAc,OACnB,IAAeoB,EAAAA,EAAAA,KAAKpB,CAAI"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),r=require("react"),q=require("./Wrapper.cjs"),Z=require("../../components/Canvas/index.cjs"),D=require("../../components/StoreUpdater/index.cjs"),y=require("../../components/Loading/index.cjs");const W={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0},z=r.forwardRef(({minManualZoom:n,maxManualZoom:i,className:t,children:u,width:a,height:o,selection:d,style:s,onMouseWheel:m,onMouseDown:h,onMouseMove:c,onMouseUp:f,zoomable:M,panAble:x,defaultSelection:p,defaultCentered:v,defaultDraggable:b,manualZoom:g,...w},j)=>e.jsx("div",{style:{...W,...s},ref:j,className:`react-fabric ${t||""}`,children:e.jsxs(q.Wrapper,{width:a,height:o,children:[e.jsx(D.StoreUpdater,{minManualZoom:n,maxManualZoom:i,zoomable:M,panAble:x,defaultCentered:v,selection:d,defaultSelection:p,defaultDraggable:b,manualZoom:g,width:a,height:o}),e.jsx(Z.default,{onMouseDown:h,onMouseMove:c,onMouseUp:f,onMouseWheel:m,...w,children:u}),e.jsx(y.default,{})]})})),l=r.memo(z);l.displayName="ReactFabric",exports.default=l;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/container/ReactFabric/index.tsx"],"sourcesContent":["import type { CSSProperties } from 'react'\nimport { forwardRef, memo } from 'react'\nimport { Wrapper } from './Wrapper'\nimport Canvas from '../../components/Canvas'\nimport { StoreUpdater } from '../../components/StoreUpdater'\nimport Loading from '../../components/Loading'\n\n//
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/container/ReactFabric/index.tsx"],"sourcesContent":["import type { CSSProperties } from 'react'\nimport { forwardRef, memo } from 'react'\nimport { Wrapper } from './Wrapper'\nimport Canvas, { type CanvasProps } from '../../components/Canvas'\nimport { StoreUpdater } from '../../components/StoreUpdater'\nimport Loading from '../../components/Loading'\n\n// 重新定义 CanvasProps,不再从 components/Canvas 导入\ntype BaseCanvasProps = {\n width?: number\n height?: number\n selection?: boolean\n children?: React.ReactNode\n // 添加其他必要的 Canvas 属性\n}\n\nconst wrapperStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n position: 'relative',\n zIndex: 0,\n}\n\nexport type ReactFabricProps = BaseCanvasProps &\n CanvasProps & {\n style?: CSSProperties\n className?: string\n zoomable?: boolean\n panAble?: boolean\n manualZoom?: number\n minManualZoom?: number\n maxManualZoom?: number\n /** 背景图是否默认居中显示\n * @default false\n */\n defaultCentered?: boolean\n /** 是否启用选择功能\n * @default true\n * */\n defaultSelection?: boolean\n /**\n * 是否默认可拖拽\n */\n defaultDraggable?: boolean\n }\n\nconst ForwardReactFabric = forwardRef<HTMLDivElement, ReactFabricProps>(\n (\n {\n minManualZoom,\n maxManualZoom,\n className,\n children,\n width,\n height,\n selection,\n style,\n onMouseWheel,\n onMouseDown,\n onMouseMove,\n onMouseUp,\n zoomable,\n panAble,\n defaultSelection,\n defaultCentered,\n defaultDraggable,\n manualZoom,\n ...rest\n },\n ref,\n ) => {\n return (\n <div style={{ ...wrapperStyle, ...style }} ref={ref} className={`react-fabric ${className || ''}`}>\n <Wrapper width={width} height={height}>\n <StoreUpdater\n minManualZoom={minManualZoom}\n maxManualZoom={maxManualZoom}\n zoomable={zoomable}\n panAble={panAble}\n defaultCentered={defaultCentered}\n selection={selection}\n defaultSelection={defaultSelection}\n defaultDraggable={defaultDraggable}\n manualZoom={manualZoom}\n width={width}\n height={height}\n />\n\n <Canvas\n onMouseDown={onMouseDown}\n onMouseMove={onMouseMove}\n onMouseUp={onMouseUp}\n onMouseWheel={onMouseWheel}\n {...rest}\n >\n {children}\n </Canvas>\n <Loading />\n </Wrapper>\n </div>\n )\n },\n)\n\ntype ReactFabricComponent = React.MemoExoticComponent<typeof ForwardReactFabric>\n\nconst ReactFabric: ReactFabricComponent = memo(ForwardReactFabric)\nReactFabric.displayName = 'ReactFabric'\n\nexport default ReactFabric\n"],"names":["wrapperStyle","ForwardReactFabric","forwardRef","minManualZoom","maxManualZoom","className","children","width","height","selection","style","onMouseWheel","onMouseDown","onMouseMove","onMouseUp","zoomable","panAble","defaultSelection","defaultCentered","defaultDraggable","manualZoom","rest","ref","jsx","jsxs","Wrapper","StoreUpdater","Canvas","Loading","ReactFabric","memo"],"mappings":"ySAgBA,MAAMA,EAA8B,CAClC,MAAO,OACP,OAAQ,OACR,SAAU,SACV,SAAU,WACV,OAAQ,CACV,EAyBMC,EAAqBC,EACzB,WAAA,CACE,CACE,cAAAC,EACA,cAAAC,EACA,UAAAC,EACA,SAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,MAAAC,EACA,aAAAC,EACA,YAAAC,EACA,YAAAC,EACA,UAAAC,EACA,SAAAC,EACA,QAAAC,EACA,iBAAAC,EACA,gBAAAC,EACA,iBAAAC,EACA,WAAAC,EACA,GAAGC,CACL,EACAC,IAGEC,EAAAA,IAAC,OAAI,MAAO,CAAE,GAAGvB,EAAc,GAAGU,CAAM,EAAG,IAAKY,EAAK,UAAW,gBAAgBjB,GAAa,EAAE,GAC7F,SAAAmB,OAACC,EAAA,QAAA,CAAQ,MAAOlB,EAAO,OAAQC,EAC7B,SAAA,CAAAe,EAACG,IAAAA,EAAAA,aAAA,CACC,cAAevB,EACf,cAAeC,EACf,SAAUW,EACV,QAASC,EACT,gBAAiBE,EACjB,UAAWT,EACX,iBAAkBQ,EAClB,iBAAkBE,EAClB,WAAYC,EACZ,MAAOb,EACP,OAAQC,CACV,CAAA,EAEAe,EAAAA,IAACI,EAAAA,QAAA,CACC,YAAaf,EACb,YAAaC,EACb,UAAWC,EACX,aAAcH,EACb,GAAGU,EAEH,SAAAf,CACH,CAAA,EACAiB,EAACK,IAAAA,EAAAA,QAAA,CAAQ,CAAA,CACX,CAAA,CAAA,CAAA,CACF,CAGN,EAIMC,EAAoCC,EAAAA,KAAK7B,CAAkB,EACjE4B,EAAY,YAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{util as
|
|
1
|
+
"use client";import{util as v,FabricImage as A}from"fabric";import{forwardRef as L,useRef as b,useCallback as x,useEffect as w,useImperativeHandle as E,memo as V}from"react";import{useDidUpdate as j}from"../../hooks/useDidUpdate.mjs";import{useStoreApi as q,useStore as y}from"../../hooks/useStore.mjs";const B=o=>({width:o.width,height:o.height}),U=L(({src:o,onLoad:p,onScaling:H,onError:S,scaleToFit:u,scaleToCover:l,...g},T)=>{const t=b(null),a=q(),d=b(o),{width:k,height:I}=y(B),m=x(c=>{const{canvas:r,manualZoom:e=1,defaultCentered:n}=a.getState();if(!t.current)return;if(!r){console.warn("updateViewport: !canvas");return}if(!r.backgroundImage){console.warn("updateViewport: !canvas.backgroundImage");return}const s=c.scaleToFit?v.findScaleToFit(t.current,r):c.scaleToCover?v.findScaleToCover(t.current,r):1,i=s*e;r.setViewportTransform([i,0,0,i,0,0]);let f=0,h=0;if(n&&r.backgroundImage){const C=r.backgroundImage.width||0,R=r.backgroundImage.height||0;f=(r.width-C*i)/2,h=(r.height-R*i)/2}const F=[i,0,0,i,f,h];r.setViewportTransform(F),r.requestRenderAll(),a.setState({fitZoom:s,manualZoom:e,zoom:i})},[a]);return w(()=>{m({scaleToFit:u,scaleToCover:l})},[k,I,u,l,m,a]),w(()=>{if(!o){console.warn("ReactFabricBackgroundImage: !src");return}const{domNode:c,setLoading:r}=a.getState();return r(!0),d.current=o,A.fromURL(o,{crossOrigin:"anonymous"}).then(e=>{if(p?.(e),e.getSrc()!==d.current)return;const{canvas:n}=a.getState();if(n){const s={...g,angle:0};if(e.set({...s,objectCaching:!1}),n.getContext().imageSmoothingEnabled=!0,n.getContext().imageSmoothingQuality="high",n.backgroundImage=e,t.current=e,requestAnimationFrame(()=>{m({scaleToFit:u,scaleToCover:l})}),!n.viewportTransform){console.warn("!viewport");return}}else console.warn("ReactFabric:BackgroundImage: !canvas",n)}).catch(e=>{S?.(e),console.error("[ReactFabric] BackgroundImage: fromURL error",e)}).finally(()=>{c&&(c.dataset.src=o),r(!1)}),()=>{const{canvas:e}=a.getState();e?.backgroundImage&&(e.backgroundImage=void 0,e.remove(t.current),t.current=null,e.renderAll())}},[o]),j(()=>{const{canvas:c}=a.getState();t.current&&(Object.entries(g).forEach(([r,e])=>{r==="angle"?t.current?.rotate(e):t.current?.set(r,e)}),c?.requestRenderAll())},[g,a]),E(T,()=>({instance:t.current})),null});var Z=V(U);export{Z as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/components/BackgroundImage/index.tsx"],"sourcesContent":["import type {\n BasicTransformEvent,\n ImageProps,\n ObjectEvents,\n SerializedImageProps,\n TDegree,\n TPointerEvent,\n} from 'fabric'\nimport { FabricImage, util } from 'fabric'\nimport { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef } from 'react'\nimport { useDidUpdate } from '../../hooks/useDidUpdate'\nimport { useStore, useStoreApi } from '../../hooks/useStore'\nimport type { ReactFabricState } from '../../types/store'\n\nexport type Handle = {}\n\ntype ScaleMode = {\n scaleToFit?: boolean\n scaleToCover?: boolean\n}\nexport type BackgroundImageProps = Partial<ImageProps> & {\n src: string\n onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void\n onScaling?: (scale: BasicTransformEvent<TPointerEvent>) => void\n\n /** 自动缩放至容器宽高 */\n} & ScaleMode\n\nconst selector = (s: ReactFabricState) => ({\n width: s.width,\n height: s.height,\n})\n\nconst BackgroundImage = forwardRef<Handle, BackgroundImageProps>(\n ({ src, onLoad, onScaling, scaleToFit, scaleToCover, ...options }, ref) => {\n const backgroundImageRef = useRef<FabricImage | null>(null)\n\n const store = useStoreApi()\n\n const { width, height } = useStore(selector)\n\n const updateViewport = useCallback(\n (params: { scaleToFit?: boolean; scaleToCover?: boolean }) => {\n const { canvas, manualZoom = 1, defaultCentered } = store.getState()\n if (!backgroundImageRef.current) {\n return\n }\n if (!canvas) {\n console.warn('updateViewport: !canvas')\n return\n }\n if (!canvas.backgroundImage) {\n console.warn('updateViewport: !canvas.backgroundImage')\n return\n }\n\n // 1. 计算缩放\n const fitZoom = params.scaleToFit\n ? util.findScaleToFit(backgroundImageRef.current, canvas)\n : params.scaleToCover\n ? util.findScaleToCover(backgroundImageRef.current, canvas)\n : 1\n\n const combinedZoom = fitZoom * manualZoom\n\n // 2. 先应用基础缩放\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n\n // 3. 如果需要居中,计算偏移量\n let deltaX = 0\n let deltaY = 0\n\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n // const canvasCenter = {\n // x: canvas.width! / 2,\n // y: canvas.height! / 2,\n // }\n // const bgCenter = {\n // x:\n // (canvas.backgroundImage.left! + (canvas.backgroundImage.width! * canvas.backgroundImage.scaleX!) / 2) *\n // combinedZoom,\n // y:\n // (canvas.backgroundImage.top! + (canvas.backgroundImage.height! * canvas.backgroundImage.scaleY!) / 2) *\n // combinedZoom,\n // }\n // deltaX = canvasCenter.x - bgCenter.x\n // deltaY = canvasCenter.y - bgCenter.y\n }\n\n // 4. 应用最终变换\n const finalTransform: [number, number, number, number, number, number] = [\n combinedZoom,\n 0,\n 0,\n combinedZoom,\n deltaX,\n deltaY,\n ]\n\n canvas.setViewportTransform(finalTransform)\n canvas.requestRenderAll()\n\n // 5. 更新 store\n store.setState({\n fitZoom,\n manualZoom,\n zoom: combinedZoom,\n })\n },\n [store],\n )\n\n // 监听 width, height 的变化\n useEffect(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n }, [width, height, scaleToFit, scaleToCover, updateViewport, store])\n\n useEffect(() => {\n if (!src) {\n console.warn('ReactFabricBackgroundImage: !src')\n return\n }\n const { domNode, setLoading } = store.getState()\n setLoading(true)\n FabricImage.fromURL(src, { crossOrigin: 'anonymous' })\n .then(imageSource => {\n const currentSrc = imageSource.getSrc()\n const latestSrc = backgroundImageRef.current?.getSrc()\n\n if (latestSrc && currentSrc !== latestSrc) {\n return\n }\n\n const { canvas } = store.getState()\n if (canvas) {\n // 初始化时角度的旋转,一定要放到 updateViewport 之后;先画正图片,再进行旋转\n const removeAngleOptions = { ...options, angle: 0 }\n imageSource.set({\n ...removeAngleOptions,\n objectCaching: false,\n })\n canvas.getContext().imageSmoothingEnabled = true\n canvas.getContext().imageSmoothingQuality = 'high'\n canvas.backgroundImage = imageSource\n backgroundImageRef.current = imageSource\n\n requestAnimationFrame(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n })\n\n const viewport = canvas.viewportTransform\n if (!viewport) {\n console.warn('!viewport')\n return\n }\n\n // imageSource.angle = options.angle || 0\n onLoad?.(imageSource)\n } else {\n console.warn('ReactFabric:BackgroundImage: !canvas', canvas)\n }\n })\n .catch(console.error)\n .finally(() => {\n if (domNode) domNode.dataset.src = src\n setLoading(false)\n })\n\n return () => {\n const { canvas } = store.getState()\n if (canvas?.backgroundImage) {\n canvas.backgroundImage = undefined\n canvas.remove(backgroundImageRef.current!)\n backgroundImageRef.current = null\n canvas.renderAll()\n }\n }\n }, [src])\n\n useDidUpdate(() => {\n const { canvas } = store.getState()\n\n if (backgroundImageRef.current) {\n Object.entries(options).forEach(([key, value]) => {\n if (key === 'angle') {\n backgroundImageRef.current?.rotate(value as TDegree)\n } else {\n backgroundImageRef.current?.set(key, value)\n }\n })\n canvas?.requestRenderAll()\n }\n }, [options, store])\n\n useImperativeHandle(ref, () => ({\n // 是最新的?\n instance: backgroundImageRef.current,\n }))\n\n return null\n },\n)\n\nexport default memo(BackgroundImage)\n"],"names":["selector","s","BackgroundImage","forwardRef","src","onLoad","onScaling","scaleToFit","scaleToCover","options","ref","backgroundImageRef","useRef","store","useStoreApi","width","height","useStore","updateViewport","useCallback","params","canvas","manualZoom","defaultCentered","fitZoom","util","combinedZoom","deltaX","deltaY","bgWidth","bgHeight","finalTransform","useEffect","domNode","setLoading","FabricImage","imageSource","currentSrc","latestSrc","removeAngleOptions","useDidUpdate","key","value","useImperativeHandle","memo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/BackgroundImage/index.tsx"],"sourcesContent":["import type {\n BasicTransformEvent,\n ImageProps,\n ObjectEvents,\n SerializedImageProps,\n TDegree,\n TPointerEvent,\n} from 'fabric'\nimport { FabricImage, util } from 'fabric'\nimport { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef } from 'react'\nimport { useDidUpdate } from '../../hooks/useDidUpdate'\nimport { useStore, useStoreApi } from '../../hooks/useStore'\nimport type { ReactFabricState } from '../../types/store'\n\nexport type Handle = {\n instance: FabricImage | null\n}\n\ntype ScaleMode = {\n scaleToFit?: boolean\n scaleToCover?: boolean\n}\nexport type BackgroundImageProps = Partial<ImageProps> & {\n src: string\n onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void\n onScaling?: (scale: BasicTransformEvent<TPointerEvent>) => void\n onError?: (e: any) => void\n\n /** 自动缩放至容器宽高 */\n} & ScaleMode\n\nconst selector = (s: ReactFabricState) => ({\n width: s.width,\n height: s.height,\n})\n\nconst BackgroundImage = forwardRef<Handle, BackgroundImageProps>(\n ({ src, onLoad, onScaling, onError, scaleToFit, scaleToCover, ...options }, ref) => {\n const backgroundImageRef = useRef<FabricImage | null>(null)\n\n const store = useStoreApi()\n const newestSrcRef = useRef(src)\n\n const { width, height } = useStore(selector)\n\n const updateViewport = useCallback(\n (params: { scaleToFit?: boolean; scaleToCover?: boolean }) => {\n const { canvas, manualZoom = 1, defaultCentered } = store.getState()\n if (!backgroundImageRef.current) {\n return\n }\n if (!canvas) {\n console.warn('updateViewport: !canvas')\n return\n }\n if (!canvas.backgroundImage) {\n console.warn('updateViewport: !canvas.backgroundImage')\n return\n }\n\n // 1. 计算缩放\n const fitZoom = params.scaleToFit\n ? util.findScaleToFit(backgroundImageRef.current, canvas)\n : params.scaleToCover\n ? util.findScaleToCover(backgroundImageRef.current, canvas)\n : 1\n\n const combinedZoom = fitZoom * manualZoom\n\n // 2. 先应用基础缩放\n canvas.setViewportTransform([combinedZoom, 0, 0, combinedZoom, 0, 0])\n\n // 3. 如果需要居中,计算偏移量\n let deltaX = 0\n let deltaY = 0\n\n if (defaultCentered && canvas.backgroundImage) {\n const bgWidth = canvas.backgroundImage.width || 0\n const bgHeight = canvas.backgroundImage.height || 0\n deltaX = (canvas.width! - bgWidth * combinedZoom) / 2\n deltaY = (canvas.height! - bgHeight * combinedZoom) / 2\n // const canvasCenter = {\n // x: canvas.width! / 2,\n // y: canvas.height! / 2,\n // }\n // const bgCenter = {\n // x:\n // (canvas.backgroundImage.left! + (canvas.backgroundImage.width! * canvas.backgroundImage.scaleX!) / 2) *\n // combinedZoom,\n // y:\n // (canvas.backgroundImage.top! + (canvas.backgroundImage.height! * canvas.backgroundImage.scaleY!) / 2) *\n // combinedZoom,\n // }\n // deltaX = canvasCenter.x - bgCenter.x\n // deltaY = canvasCenter.y - bgCenter.y\n }\n\n // 4. 应用最终变换\n const finalTransform: [number, number, number, number, number, number] = [\n combinedZoom,\n 0,\n 0,\n combinedZoom,\n deltaX,\n deltaY,\n ]\n\n canvas.setViewportTransform(finalTransform)\n canvas.requestRenderAll()\n\n // 5. 更新 store\n store.setState({\n fitZoom,\n manualZoom,\n zoom: combinedZoom,\n })\n },\n [store],\n )\n\n // 监听 width, height 的变化\n useEffect(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n }, [width, height, scaleToFit, scaleToCover, updateViewport, store])\n\n useEffect(() => {\n if (!src) {\n console.warn('ReactFabricBackgroundImage: !src')\n return\n }\n const { domNode, setLoading } = store.getState()\n setLoading(true)\n newestSrcRef.current = src\n\n FabricImage.fromURL(src, { crossOrigin: 'anonymous' })\n .then(imageSource => {\n onLoad?.(imageSource)\n const currentSrc = imageSource.getSrc()\n\n if (currentSrc !== newestSrcRef.current) {\n return\n }\n\n const { canvas } = store.getState()\n if (canvas) {\n // 初始化时角度的旋转,一定要放到 updateViewport 之后;先画正图片,再进行旋转\n const removeAngleOptions = { ...options, angle: 0 }\n imageSource.set({\n ...removeAngleOptions,\n objectCaching: false,\n })\n canvas.getContext().imageSmoothingEnabled = true\n canvas.getContext().imageSmoothingQuality = 'high'\n canvas.backgroundImage = imageSource\n backgroundImageRef.current = imageSource\n\n requestAnimationFrame(() => {\n updateViewport({\n scaleToFit,\n scaleToCover,\n })\n })\n\n const viewport = canvas.viewportTransform\n if (!viewport) {\n console.warn('!viewport')\n return\n }\n\n // imageSource.angle = options.angle || 0\n } else {\n console.warn('ReactFabric:BackgroundImage: !canvas', canvas)\n }\n })\n .catch(e => {\n onError?.(e)\n console.error('[ReactFabric] BackgroundImage: fromURL error', e)\n })\n .finally(() => {\n if (domNode) domNode.dataset.src = src\n setLoading(false)\n })\n\n return () => {\n const { canvas } = store.getState()\n if (canvas?.backgroundImage) {\n canvas.backgroundImage = undefined\n canvas.remove(backgroundImageRef.current!)\n backgroundImageRef.current = null\n canvas.renderAll()\n }\n }\n }, [src])\n\n useDidUpdate(() => {\n const { canvas } = store.getState()\n\n if (backgroundImageRef.current) {\n Object.entries(options).forEach(([key, value]) => {\n if (key === 'angle') {\n backgroundImageRef.current?.rotate(value as TDegree)\n } else {\n backgroundImageRef.current?.set(key, value)\n }\n })\n canvas?.requestRenderAll()\n }\n }, [options, store])\n\n useImperativeHandle(ref, () => ({\n // 是最新的?\n instance: backgroundImageRef.current,\n }))\n\n return null\n },\n)\n\nexport default memo(BackgroundImage)\n"],"names":["selector","s","BackgroundImage","forwardRef","src","onLoad","onScaling","onError","scaleToFit","scaleToCover","options","ref","backgroundImageRef","useRef","store","useStoreApi","newestSrcRef","width","height","useStore","updateViewport","useCallback","params","canvas","manualZoom","defaultCentered","fitZoom","util","combinedZoom","deltaX","deltaY","bgWidth","bgHeight","finalTransform","useEffect","domNode","setLoading","FabricImage","imageSource","removeAngleOptions","useDidUpdate","key","value","useImperativeHandle","memo"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{IText as r,Point as p,util as u}from"fabric";import{forwardRef as f,useImperativeHandle as d,memo as c}from"react";import{useCreateObject as h}from"../../hooks/useCreateObject.mjs";import{useSplitProps as l}from"../../hooks/useSplitProps.mjs";import{useInstancePosition as g}from"../../hooks/useInstancePosition.mjs";r.prototype.set({_getNonTransformedDimensions(){return new p(this.width,this.height).scalarAdd(this.padding)},_calculateCurrentDimensions(){return u.transformPoint(this._getTransformedDimensions(),this.getViewportTransform(),!0)}});const w=f(({group:e,text:o,children:s,...i},n)=>{const[a,m]=l(i),t=h({Constructor:r,param:o,attributes:m,group:e,listeners:a});return d(n,()=>t,[t]),g(t,s)});var
|
|
1
|
+
"use client";import{IText as r,Point as p,util as u}from"fabric";import{forwardRef as f,useImperativeHandle as d,memo as c}from"react";import{useCreateObject as h}from"../../hooks/useCreateObject.mjs";import{useSplitProps as l}from"../../hooks/useSplitProps.mjs";import{useInstancePosition as g}from"../../hooks/useInstancePosition.mjs";r.prototype.set({_getNonTransformedDimensions(){return new p(this.width,this.height).scalarAdd(this.padding)},_calculateCurrentDimensions(){return u.transformPoint(this._getTransformedDimensions(),this.getViewportTransform(),!0)}});const w=f(({group:e,text:o,children:s,...i},n)=>{const[a,m]=l(i),t=h({Constructor:r,param:o,attributes:m,group:e,listeners:a});return d(n,()=>t,[t]),g(t,s)});var P=c(w);export{P as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/components/IText/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { IText, util, Point } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type ITextProps<T = unknown> = Partial<ConstructorParameters<typeof IText>[1] & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n children?: ReactNode\n} & T\n\nIText.prototype.set({\n _getNonTransformedDimensions() {\n // Object dimensions\n return new Point(this.width, this.height).scalarAdd(this.padding)\n },\n _calculateCurrentDimensions() {\n // Controls dimensions\n return util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true)\n },\n})\n\nconst ITextBox = forwardRef<IText | undefined, ITextProps>(({ group, text, children, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: IText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n})\n\nexport default memo(ITextBox)\n"],"names":["IText","Point","util","ITextBox","forwardRef","group","text","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","useImperativeHandle","useInstancePosition","memo"],"mappings":"iVAcAA,EAAM,UAAU,IAAI,CAClB,8BAA+B,CAE7B,OAAO,IAAIC,EAAM,KAAK,MAAO,KAAK,MAAM,EAAE,UAAU,KAAK,OAAO,CAClE,EACA,6BAA8B,CAE5B,OAAOC,EAAK,eAAe,KAAK,4BAA6B,KAAK,uBAAwB,EAAI,CAChG,CACF,CAAC,EAED,MAAMC,EAAWC,EAA0C,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAM,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACvG,KAAM,CAACC,EAAWC,CAAU,EAAIC,EAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,CAC/B,YAAad,EACb,MAAOM,EACP,WAAAK,EACA,MAAAN,EACA,UAAAK,CACF,CAAC,EAED,OAAAK,EAAoBN,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5CG,EAAoBH,EAAUN,CAAQ,CAC/C,CAAC,EAED,
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/IText/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { IText, util, Point } from 'fabric'\nimport { forwardRef, memo, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport type { AllObjectEvents } from '../../types/object'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type ITextProps<T = unknown> = Partial<ConstructorParameters<typeof IText>[1] & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n children?: ReactNode\n} & T\n\nIText.prototype.set({\n _getNonTransformedDimensions() {\n // Object dimensions\n return new Point(this.width, this.height).scalarAdd(this.padding)\n },\n _calculateCurrentDimensions() {\n // Controls dimensions\n return util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true)\n },\n})\n\nconst ITextBox = forwardRef<IText | undefined, ITextProps>(({ group, text, children, ...props }, ref) => {\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: IText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n useImperativeHandle(ref, () => instance, [instance])\n\n return useInstancePosition(instance, children)\n})\n\nexport default memo(ITextBox)\n"],"names":["IText","Point","util","ITextBox","forwardRef","group","text","children","props","ref","listeners","attributes","useSplitProps","instance","useCreateObject","useImperativeHandle","useInstancePosition","a","memo"],"mappings":"iVAcAA,EAAM,UAAU,IAAI,CAClB,8BAA+B,CAE7B,OAAO,IAAIC,EAAM,KAAK,MAAO,KAAK,MAAM,EAAE,UAAU,KAAK,OAAO,CAClE,EACA,6BAA8B,CAE5B,OAAOC,EAAK,eAAe,KAAK,4BAA6B,KAAK,uBAAwB,EAAI,CAChG,CACF,CAAC,EAED,MAAMC,EAAWC,EAA0C,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAM,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACvG,KAAM,CAACC,EAAWC,CAAU,EAAIC,EAAcJ,CAAK,EAE7CK,EAAWC,EAAgB,CAC/B,YAAad,EACb,MAAOM,EACP,WAAAK,EACA,MAAAN,EACA,UAAAK,CACF,CAAC,EAED,OAAAK,EAAoBN,EAAK,IAAMI,EAAU,CAACA,CAAQ,CAAC,EAE5CG,EAAoBH,EAAUN,CAAQ,CAC/C,CAAC,EAED,IAAAU,EAAeC,EAAKf,CAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Objects/index.tsx"],"sourcesContent":["import { memo } from 'react'\nimport Path from '../Path'\nimport Text from '../Text'\nimport Rect from '../Rect'\nimport Line from '../Line'\nimport IText from '../IText'\n\nexport type ObjectsProps = {\n objects: { type: string;[index: string]: any }[]\n}\n\nconst Objects = ({ objects }: ObjectsProps) => {\n const components = {\n rect: Rect,\n path: Path,\n text: Text,\n line: Line,\n 'i-text': Text,\n itext: IText,\n }\n\n if (!objects) return null\n return (\n <>\n {objects?.map(({ type, ...options }) => {\n const Component = components[type.toLowerCase() as keyof typeof components]\n if (!Component) {\n return null\n }\n return <Component {...options} />\n })}\n </>\n )\n}\n\nexport default memo(Objects)\n"],"names":["Objects","objects","components","Rect","Path","Text","Line","IText","jsx","Fragment","type","options","Component","memo"],"mappings":"sQAWA,MAAMA,EAAU,CAAC,CAAE,QAAAC,CAAQ,IAAoB,CAC7C,MAAMC,EAAa,CACjB,KAAMC,EACN,KAAMC,EACN,KAAMC,EACN,KAAMC,EACN,SAAUD,EACV,MAAOE,CACT,EAEA,OAAKN,EAEHO,EAAAC,EAAA,CACG,SAAAR,GAAS,IAAI,CAAC,CAAE,KAAAS,EAAM,GAAGC,CAAQ,IAAM,CACtC,MAAMC,EAAYV,EAAWQ,EAAK,YAAwC,CAAA,EAC1E,OAAKE,EAGEJ,EAACI,EAAA,CAAW,
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Objects/index.tsx"],"sourcesContent":["import { memo } from 'react'\nimport Path from '../Path'\nimport Text from '../Text'\nimport Rect from '../Rect'\nimport Line from '../Line'\nimport IText from '../IText'\n\nexport type ObjectsProps = {\n objects: { type: string; [index: string]: any }[]\n}\n\nconst Objects = ({ objects }: ObjectsProps) => {\n const components = {\n rect: Rect,\n path: Path,\n text: Text,\n line: Line,\n 'i-text': Text,\n itext: IText,\n }\n\n if (!objects) return null\n return (\n <>\n {objects?.map(({ type, ...options }) => {\n const Component = components[type.toLowerCase() as keyof typeof components]\n if (!Component) {\n return null\n }\n return <Component {...(options as any)} />\n })}\n </>\n )\n}\n\nexport default memo(Objects)\n"],"names":["Objects","objects","components","Rect","Path","Text","Line","IText","jsx","Fragment","type","options","Component","memo"],"mappings":"sQAWA,MAAMA,EAAU,CAAC,CAAE,QAAAC,CAAQ,IAAoB,CAC7C,MAAMC,EAAa,CACjB,KAAMC,EACN,KAAMC,EACN,KAAMC,EACN,KAAMC,EACN,SAAUD,EACV,MAAOE,CACT,EAEA,OAAKN,EAEHO,EAAAC,EAAA,CACG,SAAAR,GAAS,IAAI,CAAC,CAAE,KAAAS,EAAM,GAAGC,CAAQ,IAAM,CACtC,MAAMC,EAAYV,EAAWQ,EAAK,YAAwC,CAAA,EAC1E,OAAKE,EAGEJ,EAACI,EAAA,CAAW,GAAID,EAAiB,EAF/B,IAGX,CAAC,CACH,CAAA,EAVmB,IAYvB,EAEA,IAAeE,EAAAA,EAAKb,CAAO"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{FabricText as r,Point as
|
|
1
|
+
"use client";import{FabricText as r,Point as c,util as d}from"fabric";import{forwardRef as h,useEffect as F,useImperativeHandle as g,memo as y}from"react";import{useCreateObject as w}from"../../hooks/useCreateObject.mjs";import{useSplitProps as D}from"../../hooks/useSplitProps.mjs";import{useStoreApi as P}from"../../hooks/useStore.mjs";import T from"fontfaceobserver";import{useInstancePosition as b}from"../../hooks/useInstancePosition.mjs";r.prototype.set({_getNonTransformedDimensions(){return new c(this.width,this.height).scalarAdd(this.padding)},_calculateCurrentDimensions(){return d.transformPoint(this._getTransformedDimensions(),this.getViewportTransform(),!0)}});const o=h(({group:i,text:n,children:s,...a},m)=>{const u=P(),[f,t]=D(a),e=w({Constructor:r,param:n,attributes:t,group:i,listeners:f});return F(()=>{const{canvas:l}=u.getState();!t.fontFamily||!e||new T(t.fontFamily).load().then(()=>{e.set({fontFamily:t.fontFamily}),l?.requestRenderAll()}).catch(p=>{console.error(`ReactFabric: \u5B57\u4F53\u52A0\u8F7D\u5931\u8D25: ${t.fontFamily}`,p)})},[t.fontFamily,e]),g(m,()=>e,[e]),b(e,s)});o.displayName="Text";var x=y(o);export{x as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Text/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { FabricText, Point, util } from 'fabric'\nimport { forwardRef, memo, useEffect, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport { useStoreApi } from '../../hooks/useStore'\nimport type { AllObjectEvents } from '../../types/object'\nimport FontFaceObserver from 'fontfaceobserver'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type Handle = FabricText | undefined\n\nexport type TextProps<T = unknown> = Partial<
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/Text/index.tsx"],"sourcesContent":["import type { Group as BaseGroup } from 'fabric'\nimport { FabricText, Point, util } from 'fabric'\nimport { forwardRef, memo, useEffect, useImperativeHandle, type ReactNode } from 'react'\nimport { useCreateObject } from '../../hooks/useCreateObject'\nimport { useSplitProps } from '../../hooks/useSplitProps'\nimport { useStoreApi } from '../../hooks/useStore'\nimport type { AllObjectEvents } from '../../types/object'\nimport FontFaceObserver from 'fontfaceobserver'\nimport { useInstancePosition } from '../../hooks/useInstancePosition'\n\nexport type Handle = FabricText | undefined\n\nexport type TextProps<T = unknown> = Partial<FabricText & AllObjectEvents> & {\n group?: BaseGroup\n text: string\n children?: ReactNode\n} & T\n\nFabricText.prototype.set({\n _getNonTransformedDimensions() {\n // Object dimensions\n return new Point(this.width, this.height).scalarAdd(this.padding)\n },\n _calculateCurrentDimensions() {\n // Controls dimensions\n return util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true)\n },\n})\n\nconst Text = forwardRef<Handle, TextProps>(({ group, text, children, ...props }, ref) => {\n const store = useStoreApi()\n\n const [listeners, attributes] = useSplitProps(props)\n\n const instance = useCreateObject({\n Constructor: FabricText,\n param: text,\n attributes,\n group,\n listeners,\n })\n\n /**\n * 字体只有被使用了才会加载;先由 Text 使用一次, 监听加载完成,之后再 set 一次\n */\n useEffect(() => {\n const { canvas } = store.getState()\n if (!attributes.fontFamily || !instance) return\n const font = new FontFaceObserver(attributes.fontFamily)\n font\n .load()\n .then(() => {\n instance.set({\n fontFamily: attributes.fontFamily,\n })\n canvas?.requestRenderAll()\n })\n .catch(error => {\n // 加载失败\n console.error(`ReactFabric: 字体加载失败: ${attributes.fontFamily}`, error)\n })\n }, [attributes.fontFamily, instance])\n\n useImperativeHandle(ref, () => instance, [instance])\n return useInstancePosition(instance, children)\n})\n\nText.displayName = 'Text'\nexport default memo(Text)\n"],"names":["FabricText","Point","util","Text","forwardRef","group","text","children","props","ref","store","useStoreApi","listeners","attributes","useSplitProps","instance","useCreateObject","useEffect","canvas","FontFaceObserver","error","useImperativeHandle","useInstancePosition","memo"],"mappings":"4bAkBAA,EAAW,UAAU,IAAI,CACvB,8BAA+B,CAE7B,OAAO,IAAIC,EAAM,KAAK,MAAO,KAAK,MAAM,EAAE,UAAU,KAAK,OAAO,CAClE,EACA,6BAA8B,CAE5B,OAAOC,EAAK,eAAe,KAAK,4BAA6B,KAAK,qBAAA,EAAwB,EAAI,CAChG,CACF,CAAC,EAED,MAAMC,EAAOC,EAA8B,CAAC,CAAE,MAAAC,EAAO,KAAAC,EAAM,SAAAC,EAAU,GAAGC,CAAM,EAAGC,IAAQ,CACvF,MAAMC,EAAQC,IAER,CAACC,EAAWC,CAAU,EAAIC,EAAcN,CAAK,EAE7CO,EAAWC,EAAgB,CAC/B,YAAahB,EACb,MAAOM,EACP,WAAAO,EACA,MAAAR,EACA,UAAAO,CACF,CAAC,EAKD,OAAAK,EAAU,IAAM,CACd,KAAM,CAAE,OAAAC,CAAO,EAAIR,EAAM,SAAA,EACrB,CAACG,EAAW,YAAc,CAACE,GAClB,IAAII,EAAiBN,EAAW,UAAU,EAEpD,KAAK,EACL,KAAK,IAAM,CACVE,EAAS,IAAI,CACX,WAAYF,EAAW,UACzB,CAAC,EACDK,GAAQ,iBACV,CAAA,CAAC,EACA,MAAME,GAAS,CAEd,QAAQ,MAAM,sDAAwBP,EAAW,UAAU,GAAIO,CAAK,CACtE,CAAC,CACL,EAAG,CAACP,EAAW,WAAYE,CAAQ,CAAC,EAEpCM,EAAoBZ,EAAK,IAAMM,EAAU,CAACA,CAAQ,CAAC,EAC5CO,EAAoBP,EAAUR,CAAQ,CAC/C,CAAC,EAEDJ,EAAK,YAAc,OACnB,IAAeoB,EAAAA,EAAKpB,CAAI"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{jsx as e,jsxs as v}from"react/jsx-runtime";import{forwardRef as D,memo as N}from"react";import{Wrapper as y}from"./Wrapper.mjs";import z from"../../components/Canvas/index.mjs";import{StoreUpdater as S}from"../../components/StoreUpdater/index.mjs";import U from"../../components/Loading/index.mjs";const W={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0},j=D(({minManualZoom:
|
|
1
|
+
"use client";import{jsx as e,jsxs as v}from"react/jsx-runtime";import{forwardRef as D,memo as N}from"react";import{Wrapper as y}from"./Wrapper.mjs";import z from"../../components/Canvas/index.mjs";import{StoreUpdater as S}from"../../components/StoreUpdater/index.mjs";import U from"../../components/Loading/index.mjs";const W={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0},j=D(({minManualZoom:l,maxManualZoom:n,className:r,children:i,width:o,height:a,selection:m,style:d,onMouseWheel:s,onMouseDown:u,onMouseMove:h,onMouseUp:f,zoomable:c,panAble:p,defaultSelection:M,defaultCentered:b,defaultDraggable:g,manualZoom:w,...x},Z)=>e("div",{style:{...W,...d},ref:Z,className:`react-fabric ${r||""}`,children:v(y,{width:o,height:a,children:[e(S,{minManualZoom:l,maxManualZoom:n,zoomable:c,panAble:p,defaultCentered:b,selection:m,defaultSelection:M,defaultDraggable:g,manualZoom:w,width:o,height:a}),e(z,{onMouseDown:u,onMouseMove:h,onMouseUp:f,onMouseWheel:s,...x,children:i}),e(U,{})]})})),t=N(j);t.displayName="ReactFabric";export{t as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/container/ReactFabric/index.tsx"],"sourcesContent":["import type { CSSProperties } from 'react'\nimport { forwardRef, memo } from 'react'\nimport { Wrapper } from './Wrapper'\nimport Canvas from '../../components/Canvas'\nimport { StoreUpdater } from '../../components/StoreUpdater'\nimport Loading from '../../components/Loading'\n\n//
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/container/ReactFabric/index.tsx"],"sourcesContent":["import type { CSSProperties } from 'react'\nimport { forwardRef, memo } from 'react'\nimport { Wrapper } from './Wrapper'\nimport Canvas, { type CanvasProps } from '../../components/Canvas'\nimport { StoreUpdater } from '../../components/StoreUpdater'\nimport Loading from '../../components/Loading'\n\n// 重新定义 CanvasProps,不再从 components/Canvas 导入\ntype BaseCanvasProps = {\n width?: number\n height?: number\n selection?: boolean\n children?: React.ReactNode\n // 添加其他必要的 Canvas 属性\n}\n\nconst wrapperStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n position: 'relative',\n zIndex: 0,\n}\n\nexport type ReactFabricProps = BaseCanvasProps &\n CanvasProps & {\n style?: CSSProperties\n className?: string\n zoomable?: boolean\n panAble?: boolean\n manualZoom?: number\n minManualZoom?: number\n maxManualZoom?: number\n /** 背景图是否默认居中显示\n * @default false\n */\n defaultCentered?: boolean\n /** 是否启用选择功能\n * @default true\n * */\n defaultSelection?: boolean\n /**\n * 是否默认可拖拽\n */\n defaultDraggable?: boolean\n }\n\nconst ForwardReactFabric = forwardRef<HTMLDivElement, ReactFabricProps>(\n (\n {\n minManualZoom,\n maxManualZoom,\n className,\n children,\n width,\n height,\n selection,\n style,\n onMouseWheel,\n onMouseDown,\n onMouseMove,\n onMouseUp,\n zoomable,\n panAble,\n defaultSelection,\n defaultCentered,\n defaultDraggable,\n manualZoom,\n ...rest\n },\n ref,\n ) => {\n return (\n <div style={{ ...wrapperStyle, ...style }} ref={ref} className={`react-fabric ${className || ''}`}>\n <Wrapper width={width} height={height}>\n <StoreUpdater\n minManualZoom={minManualZoom}\n maxManualZoom={maxManualZoom}\n zoomable={zoomable}\n panAble={panAble}\n defaultCentered={defaultCentered}\n selection={selection}\n defaultSelection={defaultSelection}\n defaultDraggable={defaultDraggable}\n manualZoom={manualZoom}\n width={width}\n height={height}\n />\n\n <Canvas\n onMouseDown={onMouseDown}\n onMouseMove={onMouseMove}\n onMouseUp={onMouseUp}\n onMouseWheel={onMouseWheel}\n {...rest}\n >\n {children}\n </Canvas>\n <Loading />\n </Wrapper>\n </div>\n )\n },\n)\n\ntype ReactFabricComponent = React.MemoExoticComponent<typeof ForwardReactFabric>\n\nconst ReactFabric: ReactFabricComponent = memo(ForwardReactFabric)\nReactFabric.displayName = 'ReactFabric'\n\nexport default ReactFabric\n"],"names":["wrapperStyle","ForwardReactFabric","forwardRef","minManualZoom","maxManualZoom","className","children","width","height","selection","style","onMouseWheel","onMouseDown","onMouseMove","onMouseUp","zoomable","panAble","defaultSelection","defaultCentered","defaultDraggable","manualZoom","rest","ref","jsx","jsxs","Wrapper","StoreUpdater","Canvas","Loading","ReactFabric","memo"],"mappings":"8TAgBA,MAAMA,EAA8B,CAClC,MAAO,OACP,OAAQ,OACR,SAAU,SACV,SAAU,WACV,OAAQ,CACV,EAyBMC,EAAqBC,EACzB,CACE,CACE,cAAAC,EACA,cAAAC,EACA,UAAAC,EACA,SAAAC,EACA,MAAAC,EACA,OAAAC,EACA,UAAAC,EACA,MAAAC,EACA,aAAAC,EACA,YAAAC,EACA,YAAAC,EACA,UAAAC,EACA,SAAAC,EACA,QAAAC,EACA,iBAAAC,EACA,gBAAAC,EACA,iBAAAC,EACA,WAAAC,EACA,GAAGC,CACL,EACAC,IAGEC,EAAC,OAAI,MAAO,CAAE,GAAGvB,EAAc,GAAGU,CAAM,EAAG,IAAKY,EAAK,UAAW,gBAAgBjB,GAAa,EAAE,GAC7F,SAAAmB,EAACC,EAAA,CAAQ,MAAOlB,EAAO,OAAQC,EAC7B,SAAA,CAAAe,EAACG,EAAA,CACC,cAAevB,EACf,cAAeC,EACf,SAAUW,EACV,QAASC,EACT,gBAAiBE,EACjB,UAAWT,EACX,iBAAkBQ,EAClB,iBAAkBE,EAClB,WAAYC,EACZ,MAAOb,EACP,OAAQC,CACV,CAAA,EAEAe,EAACI,EAAA,CACC,YAAaf,EACb,YAAaC,EACb,UAAWC,EACX,aAAcH,EACb,GAAGU,EAEH,SAAAf,CACH,CAAA,EACAiB,EAACK,EAAA,CAAQ,CAAA,CACX,CAAA,CAAA,CAAA,CACF,CAGN,EAIMC,EAAoCC,EAAK7B,CAAkB,EACjE4B,EAAY,YAAc"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { BasicTransformEvent, ImageProps, ObjectEvents, SerializedImageProps, TPointerEvent } from 'fabric';
|
|
2
2
|
import { FabricImage } from 'fabric';
|
|
3
|
-
export type Handle = {
|
|
3
|
+
export type Handle = {
|
|
4
|
+
instance: FabricImage | null;
|
|
5
|
+
};
|
|
4
6
|
type ScaleMode = {
|
|
5
7
|
scaleToFit?: boolean;
|
|
6
8
|
scaleToCover?: boolean;
|
|
@@ -9,11 +11,13 @@ export type BackgroundImageProps = Partial<ImageProps> & {
|
|
|
9
11
|
src: string;
|
|
10
12
|
onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void;
|
|
11
13
|
onScaling?: (scale: BasicTransformEvent<TPointerEvent>) => void;
|
|
14
|
+
onError?: (e: any) => void;
|
|
12
15
|
} & ScaleMode;
|
|
13
16
|
declare const _default: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Partial<ImageProps> & {
|
|
14
17
|
src: string;
|
|
15
18
|
onLoad?: (imageSource: FabricImage<Partial<ImageProps>, SerializedImageProps, ObjectEvents>) => void;
|
|
16
19
|
onScaling?: (scale: BasicTransformEvent<TPointerEvent>) => void;
|
|
20
|
+
onError?: (e: any) => void;
|
|
17
21
|
} & ScaleMode & import("react").RefAttributes<Handle>>>;
|
|
18
22
|
export default _default;
|
|
19
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/BackgroundImage/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,oBAAoB,EAEpB,aAAa,EACd,MAAM,QAAQ,CAAA;AACf,OAAO,EAAE,WAAW,EAAQ,MAAM,QAAQ,CAAA;AAM1C,MAAM,MAAM,MAAM,GAAG,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/BackgroundImage/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,oBAAoB,EAEpB,aAAa,EACd,MAAM,QAAQ,CAAA;AACf,OAAO,EAAE,WAAW,EAAQ,MAAM,QAAQ,CAAA;AAM1C,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED,KAAK,SAAS,GAAG;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AACD,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG;IACvD,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,oBAAoB,EAAE,YAAY,CAAC,KAAK,IAAI,CAAA;IACpG,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,aAAa,CAAC,KAAK,IAAI,CAAA;IAC/D,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAA;CAG3B,GAAG,SAAS,CAAA;;SANN,MAAM;aACF,CAAC,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,oBAAoB,EAAE,YAAY,CAAC,KAAK,IAAI;gBACxF,CAAC,KAAK,EAAE,mBAAmB,CAAC,aAAa,CAAC,KAAK,IAAI;cACrD,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI;;AAmM5B,wBAAoC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Objects/index.tsx"],"names":[],"mappings":"AAOA,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Objects/index.tsx"],"names":[],"mappings":"AAOA,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,EAAE,CAAA;CAClD,CAAA;0EAE6B,YAAY;AAwB1C,wBAA4B"}
|
|
@@ -3,11 +3,15 @@ import { FabricText } from 'fabric';
|
|
|
3
3
|
import { type ReactNode } from 'react';
|
|
4
4
|
import type { AllObjectEvents } from '../../types/object';
|
|
5
5
|
export type Handle = FabricText | undefined;
|
|
6
|
-
export type TextProps<T = unknown> = Partial<
|
|
6
|
+
export type TextProps<T = unknown> = Partial<FabricText & AllObjectEvents> & {
|
|
7
7
|
group?: BaseGroup;
|
|
8
8
|
text: string;
|
|
9
9
|
children?: ReactNode;
|
|
10
10
|
} & T;
|
|
11
|
-
declare const _default: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<
|
|
11
|
+
declare const _default: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Partial<FabricText<Partial<import("fabric").TextProps>, import("fabric").SerializedTextProps, import("fabric").ObjectEvents> & AllObjectEvents> & {
|
|
12
|
+
group?: BaseGroup;
|
|
13
|
+
text: string;
|
|
14
|
+
children?: ReactNode;
|
|
15
|
+
} & import("react").RefAttributes<Handle>>>;
|
|
12
16
|
export default _default;
|
|
13
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Text/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,UAAU,EAAe,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIxF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAIzD,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;AAE3C,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,OAAO,IAAI,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/Text/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,UAAU,EAAe,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIxF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAIzD,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;AAE3C,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,OAAO,IAAI,OAAO,CAAC,UAAU,GAAG,eAAe,CAAC,GAAG;IAC3E,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB,GAAG,CAAC,CAAA;;YAHK,SAAS;UACX,MAAM;eACD,SAAS;;AAqDtB,wBAAyB"}
|
|
@@ -1,23 +1,12 @@
|
|
|
1
1
|
import type { CSSProperties } from 'react';
|
|
2
|
-
type
|
|
3
|
-
e: Event;
|
|
4
|
-
pointer: {
|
|
5
|
-
x: number;
|
|
6
|
-
y: number;
|
|
7
|
-
};
|
|
8
|
-
target?: unknown;
|
|
9
|
-
subTargets?: unknown[];
|
|
10
|
-
button?: number;
|
|
11
|
-
isClick?: boolean;
|
|
12
|
-
transform?: unknown;
|
|
13
|
-
};
|
|
2
|
+
import { type CanvasProps } from '../../components/Canvas';
|
|
14
3
|
type BaseCanvasProps = {
|
|
15
4
|
width?: number;
|
|
16
5
|
height?: number;
|
|
17
6
|
selection?: boolean;
|
|
18
7
|
children?: React.ReactNode;
|
|
19
8
|
};
|
|
20
|
-
export type ReactFabricProps = BaseCanvasProps & {
|
|
9
|
+
export type ReactFabricProps = BaseCanvasProps & CanvasProps & {
|
|
21
10
|
style?: CSSProperties;
|
|
22
11
|
className?: string;
|
|
23
12
|
zoomable?: boolean;
|
|
@@ -37,12 +26,110 @@ export type ReactFabricProps = BaseCanvasProps & {
|
|
|
37
26
|
* 是否默认可拖拽
|
|
38
27
|
*/
|
|
39
28
|
defaultDraggable?: boolean;
|
|
40
|
-
onMouseDown?: (e: FabricEvent) => void;
|
|
41
|
-
onMouseMove?: (e: FabricEvent) => void;
|
|
42
|
-
onMouseUp?: (e: FabricEvent) => void;
|
|
43
|
-
onMouseWheel?: (e: FabricEvent) => void;
|
|
44
29
|
};
|
|
45
|
-
declare const ForwardReactFabric: import("react").ForwardRefExoticComponent<BaseCanvasProps & {
|
|
30
|
+
declare const ForwardReactFabric: import("react").ForwardRefExoticComponent<BaseCanvasProps & Partial<{
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
selection: boolean;
|
|
34
|
+
hoverCursor: CSSStyleDeclaration["cursor"];
|
|
35
|
+
moveCursor: CSSStyleDeclaration["cursor"];
|
|
36
|
+
perPixelTargetFind: boolean;
|
|
37
|
+
clipPath?: import("fabric").FabricObject | undefined;
|
|
38
|
+
includeDefaultValues: boolean;
|
|
39
|
+
backgroundColor: import("fabric").TFiller | string;
|
|
40
|
+
centeredRotation: boolean;
|
|
41
|
+
centeredScaling: boolean;
|
|
42
|
+
containerClass: string;
|
|
43
|
+
preserveObjectStacking: boolean;
|
|
44
|
+
controlsAboveOverlay: boolean;
|
|
45
|
+
allowTouchScrolling: boolean;
|
|
46
|
+
viewportTransform: import("fabric").TMat2D;
|
|
47
|
+
backgroundVpt: boolean;
|
|
48
|
+
backgroundImage?: import("fabric").FabricObject | undefined;
|
|
49
|
+
overlayVpt: boolean;
|
|
50
|
+
overlayColor: import("fabric").TFiller | string;
|
|
51
|
+
overlayImage?: import("fabric").FabricObject | undefined;
|
|
52
|
+
renderOnAddRemove: boolean;
|
|
53
|
+
skipOffscreen: boolean;
|
|
54
|
+
enableRetinaScaling: boolean;
|
|
55
|
+
imageSmoothingEnabled: boolean;
|
|
56
|
+
svgViewportTransformation: boolean;
|
|
57
|
+
uniformScaling: boolean;
|
|
58
|
+
uniScaleKey: import("fabric").TOptionalModifierKey;
|
|
59
|
+
centeredKey: import("fabric").TOptionalModifierKey;
|
|
60
|
+
altActionKey: import("fabric").TOptionalModifierKey;
|
|
61
|
+
selectionKey: import("fabric").TOptionalModifierKey | import("fabric").ModifierKey[];
|
|
62
|
+
altSelectionKey: import("fabric").TOptionalModifierKey;
|
|
63
|
+
selectionColor: string;
|
|
64
|
+
selectionDashArray: number[];
|
|
65
|
+
selectionBorderColor: string;
|
|
66
|
+
selectionLineWidth: number;
|
|
67
|
+
selectionFullyContained: boolean;
|
|
68
|
+
defaultCursor: CSSStyleDeclaration["cursor"];
|
|
69
|
+
freeDrawingCursor: CSSStyleDeclaration["cursor"];
|
|
70
|
+
notAllowedCursor: CSSStyleDeclaration["cursor"];
|
|
71
|
+
targetFindTolerance: number;
|
|
72
|
+
skipTargetFind: boolean;
|
|
73
|
+
stopContextMenu: boolean;
|
|
74
|
+
fireRightClick: boolean;
|
|
75
|
+
fireMiddleClick: boolean;
|
|
76
|
+
enablePointerEvents: boolean;
|
|
77
|
+
}> & Partial<{
|
|
78
|
+
onBeforePathCreated: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
79
|
+
onPathCreated: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
80
|
+
onErasingStart: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
81
|
+
onErasingEnd: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
82
|
+
onTextSelectionChanged: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
83
|
+
onTextChanged: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
84
|
+
onTextEditingEntered: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
85
|
+
onTextEditingExited: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
86
|
+
onCanvasCleared: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
87
|
+
onBeforeRender: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
88
|
+
onAfterRender: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
89
|
+
onObjectLayoutBefore: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
90
|
+
onObjectLayoutAfter: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
91
|
+
onObjectAdded: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
92
|
+
onObjectRemoved: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
93
|
+
onMouseDown: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
94
|
+
onMouseDownBefore: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
95
|
+
onMouseMove: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
96
|
+
onMouseMoveBefore: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
97
|
+
onMouseDblclick: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
98
|
+
onMouseTripleclick: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
99
|
+
onMouseUp: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
100
|
+
onMouseUpBefore: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
101
|
+
onMouseWheel: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
102
|
+
onMouseOver: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
103
|
+
onMouseOut: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
104
|
+
onDragEnter: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
105
|
+
onDragLeave: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
106
|
+
onDragstart: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
107
|
+
onDrag: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
108
|
+
onDragover: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
109
|
+
onDragenter: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
110
|
+
onDragleave: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
111
|
+
onDragend: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
112
|
+
onDropBefore: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
113
|
+
onDrop: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
114
|
+
onDropAfter: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
115
|
+
onContextmenuBefore: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
116
|
+
onContextmenu: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
117
|
+
onBeforeTransform: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
118
|
+
onObjectMoving: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
119
|
+
onObjectScaling: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
120
|
+
onObjectRotating: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
121
|
+
onObjectSkewing: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
122
|
+
onObjectResizing: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
123
|
+
onObjectModifyPoly: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
124
|
+
onObjectModifyPath: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
125
|
+
onObjectModified: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
126
|
+
onSelectionCreated: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
127
|
+
onSelectionUpdated: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
128
|
+
onBeforeSelectionCleared: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
129
|
+
onSelectionCleared: (opt: import("../../types/canvas").FabricPublicEvent) => void;
|
|
130
|
+
}> & {
|
|
131
|
+
children?: import("react").ReactNode | undefined;
|
|
132
|
+
} & {
|
|
46
133
|
style?: CSSProperties;
|
|
47
134
|
className?: string;
|
|
48
135
|
zoomable?: boolean;
|
|
@@ -62,10 +149,6 @@ declare const ForwardReactFabric: import("react").ForwardRefExoticComponent<Base
|
|
|
62
149
|
* 是否默认可拖拽
|
|
63
150
|
*/
|
|
64
151
|
defaultDraggable?: boolean;
|
|
65
|
-
onMouseDown?: (e: FabricEvent) => void;
|
|
66
|
-
onMouseMove?: (e: FabricEvent) => void;
|
|
67
|
-
onMouseUp?: (e: FabricEvent) => void;
|
|
68
|
-
onMouseWheel?: (e: FabricEvent) => void;
|
|
69
152
|
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
70
153
|
type ReactFabricComponent = React.MemoExoticComponent<typeof ForwardReactFabric>;
|
|
71
154
|
declare const ReactFabric: ReactFabricComponent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/container/ReactFabric/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/container/ReactFabric/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAG1C,OAAe,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAKlE,KAAK,eAAe,GAAG;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAE3B,CAAA;AAUD,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAC5C,WAAW,GAAG;IACZ,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;UAEM;IACN,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAA;AAEH,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YArBZ,aAAa;gBACT,MAAM;eACP,OAAO;cACR,OAAO;iBACJ,MAAM;oBACH,MAAM;oBACN,MAAM;IACtB;;OAEG;sBACe,OAAO;IACzB;;UAEM;uBACa,OAAO;IAC1B;;OAEG;uBACgB,OAAO;kDA2D7B,CAAA;AAED,KAAK,oBAAoB,GAAG,KAAK,CAAC,mBAAmB,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAEhF,QAAA,MAAM,WAAW,EAAE,oBAA+C,CAAA;AAGlE,eAAe,WAAW,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CanvasEvents } from 'fabric';
|
|
1
|
+
import type { CanvasEvents, TPointerEvent, TPointerEventInfo } from 'fabric';
|
|
2
2
|
import type { MyCapitalize } from './utils';
|
|
3
3
|
export type RawEventNames<Events extends Record<string, any>> = {
|
|
4
4
|
[K in keyof Events]: MyCapitalize<K & string>;
|
|
@@ -7,8 +7,9 @@ type InvertedEventType<T extends Record<string, string>> = {
|
|
|
7
7
|
[P in keyof T as T[P]]: P;
|
|
8
8
|
};
|
|
9
9
|
type InvertedEventNames<Events extends Record<string, any>> = InvertedEventType<RawEventNames<Events>>;
|
|
10
|
+
export type FabricPublicEvent = TPointerEventInfo<TPointerEvent | MouseEvent | WheelEvent | TouchEvent>;
|
|
10
11
|
export type AllEvents<Events extends Record<string, any>> = {
|
|
11
|
-
[K in keyof InvertedEventNames<Events>]: (opt:
|
|
12
|
+
[K in keyof InvertedEventNames<Events>]: (opt: FabricPublicEvent) => void;
|
|
12
13
|
};
|
|
13
14
|
export type AllCanvasEvents = AllEvents<CanvasEvents>;
|
|
14
15
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../../src/types/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../../src/types/canvas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAA;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,MAAM,MAAM,aAAa,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;KAC7D,CAAC,IAAI,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC;CAC9C,CAAA;AAGD,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI;KACxD,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;CAC1B,CAAA;AAGD,KAAK,kBAAkB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,iBAAiB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;AAGtG,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC,CAAA;AAGvG,MAAM,MAAM,SAAS,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;KACzD,CAAC,IAAI,MAAM,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI;CAC1E,CAAA;AAGD,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cs-open/react-fabric",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.14",
|
|
5
5
|
"description": "React Fabric",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"@cs-open/react-fabric",
|
|
@@ -88,9 +88,9 @@
|
|
|
88
88
|
"typescript-eslint": "^8.17.0",
|
|
89
89
|
"use-sync-external-store": "^1.4.0",
|
|
90
90
|
"zustand": "^4.0.0 || ^5.0.0",
|
|
91
|
-
"@cs-open/
|
|
92
|
-
"@cs-open/
|
|
93
|
-
"@cs-open/
|
|
91
|
+
"@cs-open/rollup-config": "0.0.11",
|
|
92
|
+
"@cs-open/eslint-config": "0.0.11",
|
|
93
|
+
"@cs-open/tsconfig": "0.0.11"
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
96
|
"es-toolkit": "^1.39.10",
|