@sunspots/core 0.0.1
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/dist/index.d.mts +194 -0
- package/dist/index.mjs +1 -0
- package/package.json +32 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import * as rxjs from 'rxjs';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
|
|
4
|
+
declare const Color: {
|
|
5
|
+
readonly Transparent: "rgba(0,0,0,0)";
|
|
6
|
+
readonly Black: "#000000";
|
|
7
|
+
readonly White: "#ffffff";
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
interface Vector2 {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
}
|
|
14
|
+
interface Box extends Vector2 {
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
}
|
|
18
|
+
declare enum Placement {
|
|
19
|
+
Horizontal = 0,
|
|
20
|
+
Vertical = 1
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 参考线,用于辅助对齐
|
|
24
|
+
*/
|
|
25
|
+
declare class ReferenceLine {
|
|
26
|
+
placement: Placement;
|
|
27
|
+
position: number;
|
|
28
|
+
constructor(placement: Placement, position: number);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface StageConfig {
|
|
32
|
+
readonly sceneCanvas: HTMLCanvasElement;
|
|
33
|
+
readonly draggableCanvas: HTMLCanvasElement;
|
|
34
|
+
readonly shadowCanvas: HTMLCanvasElement;
|
|
35
|
+
readonly draftCanvas: HTMLCanvasElement;
|
|
36
|
+
readonly canvasEvents: Observable<PointerEvent>;
|
|
37
|
+
readonly clientEvents: Observable<PointerEvent>;
|
|
38
|
+
dpr: number;
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
}
|
|
42
|
+
declare class Stage {
|
|
43
|
+
config: StageConfig;
|
|
44
|
+
private readonly anchors;
|
|
45
|
+
readonly shapes: Shape[];
|
|
46
|
+
private activatedShape;
|
|
47
|
+
private context;
|
|
48
|
+
private shadowContext;
|
|
49
|
+
private draggableContext;
|
|
50
|
+
readonly draftContext: CanvasRenderingContext2D;
|
|
51
|
+
private readonly events;
|
|
52
|
+
private readonly destroyed$;
|
|
53
|
+
constructor(config: StageConfig);
|
|
54
|
+
resize(config?: {
|
|
55
|
+
width?: number;
|
|
56
|
+
height?: number;
|
|
57
|
+
dpr?: number;
|
|
58
|
+
}): void;
|
|
59
|
+
add(...shapes: Shape[]): void;
|
|
60
|
+
remove(...shapes: Shape[]): void;
|
|
61
|
+
setActivatedShape(shape: Shape | null): void;
|
|
62
|
+
getActivatedShape(): Shape<ShapeConfig> | null;
|
|
63
|
+
render(): void;
|
|
64
|
+
private isActivatedShape;
|
|
65
|
+
private drawScene;
|
|
66
|
+
private draw;
|
|
67
|
+
private drawDraggable;
|
|
68
|
+
private drawTransformer;
|
|
69
|
+
private drawShadow;
|
|
70
|
+
private getColor;
|
|
71
|
+
private clear;
|
|
72
|
+
private emit;
|
|
73
|
+
on(type: StageEventName): Observable<StageEvent>;
|
|
74
|
+
destroy(): void;
|
|
75
|
+
toObject(): {
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
children: ({
|
|
79
|
+
type: string;
|
|
80
|
+
index: number;
|
|
81
|
+
x: number;
|
|
82
|
+
y: number;
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
fill: string | undefined;
|
|
86
|
+
stroke: string | undefined;
|
|
87
|
+
strokeWidth: number;
|
|
88
|
+
} & Record<string, unknown>)[];
|
|
89
|
+
};
|
|
90
|
+
toBlob(quality?: number): Promise<Blob>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
interface ShapeConfig {
|
|
94
|
+
x?: number;
|
|
95
|
+
y?: number;
|
|
96
|
+
width?: number;
|
|
97
|
+
height?: number;
|
|
98
|
+
fill?: string;
|
|
99
|
+
stroke?: string;
|
|
100
|
+
strokeWidth?: number;
|
|
101
|
+
}
|
|
102
|
+
declare abstract class Shape<T extends ShapeConfig = ShapeConfig> implements ShapeConfig, Vector2 {
|
|
103
|
+
protected config: T;
|
|
104
|
+
abstract type: string;
|
|
105
|
+
index: number;
|
|
106
|
+
key: string;
|
|
107
|
+
resizable: boolean;
|
|
108
|
+
stage: Stage;
|
|
109
|
+
private events;
|
|
110
|
+
get x(): number;
|
|
111
|
+
set x(value: number);
|
|
112
|
+
get y(): number;
|
|
113
|
+
set y(value: number);
|
|
114
|
+
get width(): number;
|
|
115
|
+
set width(value: number);
|
|
116
|
+
get height(): number;
|
|
117
|
+
set height(value: number);
|
|
118
|
+
fill?: string;
|
|
119
|
+
stroke?: string;
|
|
120
|
+
strokeWidth: number;
|
|
121
|
+
constructor(config: T);
|
|
122
|
+
abstract render(context: CanvasRenderingContext2D): void;
|
|
123
|
+
abstract boundingBox(): Box;
|
|
124
|
+
abstract innerBox(): Box;
|
|
125
|
+
renderShadow?(context: CanvasRenderingContext2D): void;
|
|
126
|
+
setWidth?(width: number): void;
|
|
127
|
+
setHeight?(height: number): void;
|
|
128
|
+
coord(): Vector2;
|
|
129
|
+
emit(event: ShapeEvent): void;
|
|
130
|
+
on(type: PointerEventName): rxjs.Observable<ShapeEvent>;
|
|
131
|
+
destroy(): void;
|
|
132
|
+
setAttrs(attrs: Partial<T>): void;
|
|
133
|
+
toObject(merge?: Record<string, unknown>): {
|
|
134
|
+
type: string;
|
|
135
|
+
index: number;
|
|
136
|
+
x: number;
|
|
137
|
+
y: number;
|
|
138
|
+
width: number;
|
|
139
|
+
height: number;
|
|
140
|
+
fill: string | undefined;
|
|
141
|
+
stroke: string | undefined;
|
|
142
|
+
strokeWidth: number;
|
|
143
|
+
} & Record<string, unknown>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
type PointerEventName = 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel';
|
|
147
|
+
type StageEventName = PointerEventName | 'add' | 'remove';
|
|
148
|
+
interface ShapeEvent {
|
|
149
|
+
type: PointerEventName;
|
|
150
|
+
}
|
|
151
|
+
interface StageEvent {
|
|
152
|
+
type: StageEventName;
|
|
153
|
+
target?: Shape;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* ```ts
|
|
157
|
+
* {
|
|
158
|
+
* type: 'pointerdown',
|
|
159
|
+
* clientX: event.clientX,
|
|
160
|
+
* clientY: event.clientY,
|
|
161
|
+
* offsetX: event.clientX - targetRect.left,
|
|
162
|
+
* offsetY: event.clientY - targetRect.top
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
interface PointerEvent {
|
|
167
|
+
type: PointerEventName;
|
|
168
|
+
/** 为零时,表示主键,例如鼠标左键 */
|
|
169
|
+
button?: number;
|
|
170
|
+
clientX: number;
|
|
171
|
+
clientY: number;
|
|
172
|
+
offsetX: number;
|
|
173
|
+
offsetY: number;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
declare enum ResizeDirection {
|
|
177
|
+
Top = 0,
|
|
178
|
+
Right = 1,
|
|
179
|
+
Bottom = 2,
|
|
180
|
+
Left = 3,
|
|
181
|
+
TopRight = 4,
|
|
182
|
+
BottomRight = 5,
|
|
183
|
+
BottomLeft = 6,
|
|
184
|
+
TopLeft = 7
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
declare function withDpr(value: number): number;
|
|
188
|
+
declare function withPixel(value: number): string;
|
|
189
|
+
declare function withHash(value: string): string;
|
|
190
|
+
declare function randomColor(): string;
|
|
191
|
+
declare function rgbToHex(r: number, g: number, b: number): string;
|
|
192
|
+
declare function rgba<R extends number, G extends number, B extends number, A extends number>(r: R, g: G, b: B, a?: A): `rgba(${R},${G},${B},${A})`;
|
|
193
|
+
|
|
194
|
+
export { type Box, Color, Placement, type PointerEvent, type PointerEventName, ReferenceLine, ResizeDirection, Shape, type ShapeConfig, type ShapeEvent, Stage, type StageConfig, type StageEvent, type StageEventName, type Vector2, randomColor, rgbToHex, rgba, withDpr, withHash, withPixel };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var U=Object.defineProperty;var g=(h,t)=>U(h,"name",{value:t,configurable:!0});var X="#",_="px";function H(h){return h*devicePixelRatio}g(H,"withDpr");function W(h){return h+_}g(W,"withPixel");function Y(h){return X+h}g(Y,"withHash");function z(){let h=(Math.random()*16777215<<0).toString(16);for(;h.length<6;)h=0+h;return X+h}g(z,"randomColor");function I(h,t,e){return((1<<24)+(h<<16)+(t<<8)+e).toString(16).slice(1)}g(I,"rgbToHex");function N(h,t,e,r=1){return`rgba(${h},${t},${e},${r})`}g(N,"rgba");var L={Transparent:N(0,0,0,0),Black:"#000000",White:"#ffffff"};var D=(e=>(e[e.Horizontal=0]="Horizontal",e[e.Vertical=1]="Vertical",e))(D||{}),R=class R{constructor(t,e){this.placement=t;this.position=e}};g(R,"ReferenceLine");var a=R;var J=(n=>(n[n.Top=0]="Top",n[n.Right=1]="Right",n[n.Bottom=2]="Bottom",n[n.Left=3]="Left",n[n.TopRight=4]="TopRight",n[n.BottomRight=5]="BottomRight",n[n.BottomLeft=6]="BottomLeft",n[n.TopLeft=7]="TopLeft",n))(J||{});import{Subject as K,filter as Q}from"rxjs";var T=new Map;var O=class O{constructor(t){this.config=t;this.index=0;this.resizable=!0;this.events=new K;this.strokeWidth=0;for(;;){let e=z();if(e&&!T.has(e)){this.key=e,T.set(e,this);break}}Object.assign(this,t)}get x(){var t;return(t=this.config.x)!=null?t:0}set x(t){this.config.x=t}get y(){var t;return(t=this.config.y)!=null?t:0}set y(t){this.config.y=t}get width(){var t;return(t=this.config.width)!=null?t:0}set width(t){this.config.width=t}get height(){var t;return(t=this.config.height)!=null?t:0}set height(t){this.config.height=t}coord(){return{x:this.x,y:this.y}}emit(t){this.events.next(t)}on(t){return this.events.pipe(Q(e=>e.type===t))}destroy(){this.events.complete()}setAttrs(t){Object.assign(this,t)}toObject(t={}){return Object.assign({type:this.type,index:this.index,x:this.x,y:this.y,width:this.width,height:this.height,fill:this.fill,stroke:this.stroke,strokeWidth:this.strokeWidth},t)}};g(O,"Shape");var E=O;import{Subject as G,animationFrames as Z,filter as B,merge as tt,takeUntil as M}from"rxjs";var $=class $ extends E{constructor(e){super({fill:"#ffffff",stroke:"#3b82f6",strokeWidth:2});this.direction=e;this.type="anchor";this.radius=5}render(e){let{x:r,y:c,radius:v,stroke:C,strokeWidth:u}=this;e.beginPath(),e.arc(r,c,v,0,Math.PI*2,!1),e.fill(),C&&(e.lineWidth=u!=null?u:1,e.stroke()),e.closePath()}innerBox(){return{x:this.x-this.radius,y:this.y-this.radius,width:this.radius*2,height:this.radius*2}}boundingBox(){var v;let e=this.innerBox(),r=(v=this.strokeWidth)!=null?v:0,c=r/2;return e.x-=c,e.y-=c,e.width+=r,e.height+=r,e}setWidth(e){this.width=e,this.radius=e/2}setHeight(e){this.height=e,this.radius=e/2}get x(){let e=this.target.boundingBox();switch(this.direction){case 0:case 2:return e.x+e.width/2;case 4:case 1:case 5:return e.x+e.width;case 7:case 6:case 3:return e.x}}set x(e){}get y(){let e=this.target.boundingBox();switch(this.direction){case 7:case 0:case 4:return e.y;case 1:case 3:return e.y+e.height/2;case 5:case 2:case 6:return e.y+e.height}}set y(e){}setTarget(e){this.target=e}};g($,"Anchor");var f=$,F=[new f(7),new f(0),new f(4),new f(1),new f(5),new f(2),new f(6),new f(3)];var j=class j{constructor(t){this.config=t;this.anchors=F;this.shapes=[];this.activatedShape=null;this.events=new G;this.destroyed$=new G;let{sceneCanvas:e,shadowCanvas:r,draggableCanvas:c,draftCanvas:v,canvasEvents:C,clientEvents:u}=t;this.context=e.getContext("2d"),this.shadowContext=r.getContext("2d",{willReadFrequently:!0}),this.draggableContext=c.getContext("2d"),this.draftContext=v.getContext("2d"),this.resize();let n,S,s,p,A=!1;C.pipe(B(d=>d.type==="pointerdown"),M(this.destroyed$)).subscribe(d=>{if(d.button!==void 0&&d.button!==0)return;A=!0,n=d.offsetX,S=d.offsetY;let P=H(d.offsetX),V=H(d.offsetY),x=this.getColor(P,V),o=T.get(x);if(!o){this.emit({type:"pointerdown"}),this.setActivatedShape(null);return}if(this.activatedShape=o,o.emit({type:"pointerdown"}),o instanceof f){s=o.target.innerBox(),p=o.target.coord(),this.drawScene();return}this.setActivatedShape(o),this.emit({type:"pointerdown",target:o}),s=o.innerBox(),p=o.coord(),this.drawDraggable(),this.drawScene()}),u.pipe(B(d=>d.type==="pointermove"),B(()=>A),M(this.destroyed$)).subscribe(d=>{let P=d.offsetX,V=d.offsetY,x=P-n,o=V-S;if(this.activatedShape instanceof f){let k=this.activatedShape,m=k.target,w=p.x,b=p.y,l=s.width,i=s.height;switch(k.direction){case 7:b=p.y+o,i=s.height-o,w=p.x+x,l=s.width-x;break;case 0:b=p.y+o,i=s.height-o;break;case 4:b=p.y+o,i=s.height-o,l=s.width+x;break;case 1:l=s.width+x;break;case 5:l=s.width+x,i=s.height+o;break;case 2:i=s.height+o;break;case 6:i=s.height+o,w=p.x+x,l=s.width-x;break;case 3:w=p.x+x,l=s.width-x;break}w=Math.round(w),b=Math.round(b),l=Math.round(l),i=Math.round(i),m.x=Math.min(p.x+s.width,w),m.y=Math.min(p.y+s.height,b),m.setWidth?m.setWidth(Math.max(1,l)):m.width=Math.max(1,l),m.setHeight?m.setHeight(Math.max(1,i)):m.height=Math.max(1,i)}else if(this.activatedShape){let k=Math.round(p.x+x),m=Math.round(p.y+o),w=1/0,b=1/0,l=[new a(0,0),new a(1,0),new a(0,this.config.height/2),new a(1,this.config.width/2),new a(0,this.config.height/2-this.activatedShape.height/2),new a(1,this.config.width/2-this.activatedShape.width/2),new a(0,this.config.height-this.activatedShape.height),new a(1,this.config.width-this.activatedShape.width)];for(let i of this.shapes)i!==this.activatedShape&&l.push(new a(0,i.y-this.activatedShape.height),i.height>this.activatedShape.height?new a(0,i.y-this.activatedShape.height/2):new a(0,i.y-this.activatedShape.height+i.height/2),new a(0,i.y),i.height>this.activatedShape.height?new a(0,i.y+i.height-this.activatedShape.height/2):new a(0,i.y-this.activatedShape.height+i.height),new a(0,i.y/2),new a(0,i.y+i.height),new a(1,i.x-this.activatedShape.width),i.width>this.activatedShape.width?new a(1,i.x-this.activatedShape.width/2):new a(1,i.x-this.activatedShape.width+i.width/2),new a(1,i.x),i.width>this.activatedShape.width?new a(1,i.x+i.width-this.activatedShape.width/2):new a(1,i.x-this.activatedShape.width+i.width),new a(1,i.x/2),new a(1,i.x+i.width));for(let i of l)switch(i.placement){case 0:{let y=Math.abs(i.position-m);y<=4&&y<b&&(m=i.position,b=y);break}case 1:{let y=Math.abs(i.position-k);y<=4&&y<w&&(k=i.position,w=y);break}}this.activatedShape.x=k,this.activatedShape.y=m}}),tt(u,u).pipe(B(d=>d.type==="pointerup"||d.type==="pointercancel"),M(this.destroyed$)).subscribe(()=>{this.render(),A=!1}),Z().pipe(B(()=>A&&!!this.activatedShape),M(this.destroyed$)).subscribe(()=>{this.drawDraggable()})}resize(t){Object.assign(this.config,t);let{sceneCanvas:e,shadowCanvas:r,draggableCanvas:c,draftCanvas:v,width:C,height:u,dpr:n}=this.config;for(let S of[e,r,c,v]){let s=S.getContext("2d");S.style.width=W(C),S.style.height=W(u),S.width=H(C),S.height=H(u),s.scale(n,n)}}add(...t){for(let e of t)e.index=this.shapes.length,e.stage=this,this.shapes.push(e),this.draw(e),this.emit({type:"add",target:e})}remove(...t){let e=this.getActivatedShape();for(let r of t){this.shapes.splice(this.shapes.indexOf(r),1);for(let c of this.shapes)c.index>r.index&&c.index--;e===r&&this.setActivatedShape(null),this.emit({type:"remove",target:r})}for(let r=0;r<this.shapes.length;r++){let c=this.shapes[r];c.index=r}}setActivatedShape(t){if(!t){this.activatedShape=null;return}for(let e of this.shapes)e.index>t.index&&e.index--;t.index=this.shapes.length;for(let e of this.anchors)e.target=t;this.activatedShape=t}getActivatedShape(){return this.activatedShape instanceof f?this.activatedShape.target:this.activatedShape}render(){this.activatedShape?this.drawDraggable():this.clear(this.draggableContext),this.drawScene()}isActivatedShape(t){let e=this.getActivatedShape();return t===e}drawScene(){this.clear(this.context),this.clear(this.shadowContext);for(let e of this.shapes.slice().sort((r,c)=>r.index-c.index))this.draw(e);let t=this.getActivatedShape();if(t&&t.resizable)for(let e of this.anchors)this.drawShadow(e)}draw(t){var e;this.drawShadow(t),!this.isActivatedShape(t)&&(this.context.save(),this.context.fillStyle=(e=t.fill)!=null?e:L.Transparent,t.stroke&&(this.context.lineWidth=t.strokeWidth,this.context.strokeStyle=t.stroke),this.context.beginPath(),t.render(this.context),this.context.stroke(),this.context.restore())}drawDraggable(){var e;let t=this.getActivatedShape();t&&(this.clear(this.draggableContext),this.draggableContext.save(),this.draggableContext.fillStyle=(e=t.fill)!=null?e:L.Transparent,t.stroke&&(this.draggableContext.lineWidth=t.strokeWidth,this.draggableContext.strokeStyle=t.stroke),this.draggableContext.beginPath(),t.render(this.draggableContext),this.draggableContext.stroke(),this.draggableContext.restore(),this.drawTransformer(t))}drawTransformer(t){let e=t.boundingBox();if(this.draggableContext.fillStyle="#ffffff",this.draggableContext.strokeStyle="#3b82f6",this.draggableContext.lineWidth=2,this.draggableContext.strokeRect(e.x,e.y,e.width,e.height),!!t.resizable)for(let r of this.anchors)r.render(this.draggableContext)}drawShadow(t){this.shadowContext.save(),this.shadowContext.fillStyle=t.fill?t.key:L.Transparent,this.shadowContext.strokeStyle=t.key,t.stroke&&(this.shadowContext.lineWidth=t.strokeWidth),this.shadowContext.beginPath(),t.renderShadow?t.renderShadow(this.shadowContext):t.render(this.shadowContext),this.shadowContext.stroke(),this.shadowContext.restore()}getColor(t,e){let{data:r}=this.shadowContext.getImageData(t,e,1,1);return Y(I(r[0],r[1],r[2]))}clear(t){t.clearRect(0,0,this.config.width,this.config.height)}emit(t){this.events.next(t)}on(t){return this.events.pipe(B(e=>e.type===t))}destroy(){this.destroyed$.next(),this.destroyed$.complete(),this.events.complete();for(let t of this.shapes)t.destroy()}toObject(){return{width:this.config.width,height:this.config.height,children:this.shapes.map(t=>t.toObject())}}toBlob(t=1){return this.setActivatedShape(null),this.render(),new Promise(e=>{this.config.sceneCanvas.toBlob(r=>e(r),"image/webp",t)})}};g(j,"Stage");var q=j;export{L as Color,D as Placement,a as ReferenceLine,J as ResizeDirection,E as Shape,q as Stage,z as randomColor,I as rgbToHex,N as rgba,H as withDpr,Y as withHash,W as withPixel};
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sunspots/core",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"module": "./dist/index.mjs",
|
|
6
|
+
"types": "./dist/index.d.mts",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.mts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"publish:dev": "yalc publish ."
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"rxjs": "^7.8.1"
|
|
30
|
+
},
|
|
31
|
+
"gitHead": "559cddb71cb7b7d7065ea79e4da732d6a2140fa4"
|
|
32
|
+
}
|