leafer-x-watermark 1.0.0 → 1.1.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/README.md CHANGED
@@ -64,9 +64,9 @@ const watermark = new Watermark({
64
64
  fill: 'rgba(255, 0, 0, 0.1)',
65
65
  fontSize: 20,
66
66
  }),
67
- tileMode: true, // 开启平铺
68
- tileSize: 100, // 100% 原始大小
69
- tileGap: 20, // 20% 间距
67
+ tileMode: true, // 开启平铺
68
+ tileSize: 100, // 100% 原始大小
69
+ tileGap: 20, // 20% 间距
70
70
  tileRotation: -30, // 旋转 -30 度
71
71
  width: 800,
72
72
  height: 600,
@@ -84,7 +84,7 @@ const watermark = new Watermark({
84
84
  fontSize: 14,
85
85
  }),
86
86
  tileMode: true,
87
- tileStagger: 50, // 50% 错位偏移
87
+ tileStagger: 50, // 50% 错位偏移
88
88
  tileGap: 10,
89
89
  width: 800,
90
90
  height: 600,
@@ -121,8 +121,8 @@ const watermark = new Watermark({
121
121
  | `tileContent` | string | - | 水印内容,LeaferJS 元素的 JSON 字符串 |
122
122
  | `tileMode` | boolean | `true` | 平铺模式:`true` 平铺,`false` 拉伸 |
123
123
  | `tileSize` | number | `100` | 显示比例(%),100 为原始大小 |
124
- | `tileGap` | number | `0` | 间距比例(%),基于显示尺寸计算 |
125
- | `tileStagger` | number | `0` | 错位偏移比例(0-100),控制相邻行的水平偏移 |
124
+ | `tileGap` | `number \| { x?: number, y?: number }` | `0` | 间距比例(%),支持统一数值或分别设置 x/y 间距 |
125
+ | `tileStagger` | `number \| { type?: 'x' \| 'y', offset: number }` | `0` | 错位偏移,支持数值(0-100)或详细配置 |
126
126
  | `tileRotation` | number | `0` | 水印旋转角度(度) |
127
127
 
128
128
  ### 属性说明
@@ -160,13 +160,15 @@ JSON.stringify({
160
160
 
161
161
  间距基于显示尺寸的百分比计算:
162
162
  - `tileGap: 10` 表示间距为水印宽/高的 10%
163
+ - 支持分别设置:`{ x: 20, y: 10 }`
163
164
 
164
165
  #### tileStagger
165
166
 
166
- 错位排列效果,值为 0-100
167
+ 错位排列效果,支持数值 (0-100) 或对象配置:
168
+ - `tileStagger: 50` = 水平方向(x)相邻行偏移 50%
169
+ - `{ type: 'y', offset: 50 }` = 垂直方向(y)相邻列偏移 50%
167
170
  - `0` = 无错位
168
- - `50` = 相邻行偏移 50%
169
- - `100` = 相邻行偏移 100%(等于一个完整水印宽度)
171
+ - `100` = 完全错位(等于一个完整水印尺寸)
170
172
 
171
173
  ## 💡 使用场景
172
174
 
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { IRectData, IUI, IRectInputData, IJSONOptions, IUIJSONData, IObject } from '@leafer-ui/interface';
1
+ import { IRectData, IUI, IRectInputData, IObject, IJSONOptions } from '@leafer-ui/interface';
2
2
  import { RectData, Rect } from '@leafer-ui/core';
3
3
 
4
4
  type IStaggerType = 'x' | 'y';
@@ -33,9 +33,16 @@ interface IProcessDataType extends IRectData {
33
33
  _tileContent?: string;
34
34
  _tileMode?: boolean;
35
35
  _tileSize?: number;
36
- _tileGap?: number;
37
- _tileStagger?: number;
36
+ _tileGap?: number | ITileGap;
37
+ _tileStagger?: IStagger;
38
38
  _tileRotation?: number;
39
+ _cachedUrl?: string;
40
+ _cachedBounds?: {
41
+ width: number;
42
+ height: number;
43
+ };
44
+ updateFill: () => void;
45
+ regenerateImage: () => Promise<void>;
39
46
  }
40
47
  interface IWatermark extends IWatermarkAttrData, IUI {
41
48
  __: IProcessDataType;
@@ -45,19 +52,27 @@ interface IWatermarkInputData extends IWatermarkAttrData, IRectInputData {
45
52
  declare class ProcessorData extends RectData implements IProcessDataType {
46
53
  __leaf: Watermark;
47
54
  _tileContent?: string;
48
- setTileContent(value: string): void;
55
+ _cachedUrl?: string;
56
+ _cachedBounds?: {
57
+ width: number;
58
+ height: number;
59
+ };
60
+ setTileContent(value: string): Promise<void>;
49
61
  _tileMode?: boolean;
50
62
  setTileMode(value: boolean): void;
51
63
  _tileSize?: number;
52
64
  setTileSize(value: number): void;
53
- _tileGap?: number;
65
+ _tileGap?: number | ITileGap;
54
66
  setTileGap(value: number): void;
55
- _tileStagger?: number;
67
+ _tileStagger?: IStagger;
56
68
  setTileStagger(value: number): void;
57
69
  _tileRotation?: number;
58
70
  setTileRotation(value: number): void;
71
+ updateFill(): void;
59
72
  __getData(): IObject;
60
73
  __getInputData(names?: string[] | IObject, options?: IJSONOptions): IObject;
74
+ private createTileItem;
75
+ regenerateImage(): Promise<void>;
61
76
  }
62
77
  declare class Watermark<TConstructorData = IWatermarkInputData> extends Rect<TConstructorData> implements IWatermark {
63
78
  get __tag(): string;
@@ -73,13 +88,8 @@ declare class Watermark<TConstructorData = IWatermarkInputData> extends Rect<TCo
73
88
  tileRotation: number;
74
89
  width: number;
75
90
  height: number;
76
- private _cachedUrl?;
77
- private _cachedBounds?;
91
+ get tileURL(): string;
78
92
  constructor(data?: TConstructorData);
79
- private createTileItem;
80
- regenerateImage(): void;
81
- updateFill(): void;
82
- toJSON(options?: IJSONOptions): IUIJSONData;
83
93
  }
84
94
 
85
95
  declare function normalizeStagger(stagger: IStagger): INormalizedStagger;
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { MatrixHelper, MathHelper, PaintImage, Platform, Debug, dataProcessor, boundsType, registerUI, Plugin, RectData, Rect, UICreator, isObject } from '@leafer-ui/core';
1
+ import { MatrixHelper, MathHelper, PaintImage, Platform, Debug, dataProcessor, boundsType, registerUI, Plugin, RectData, isObject, UICreator, Rect } from '@leafer-ui/core';
2
2
 
3
3
  const { get, scale, copy } = MatrixHelper;
4
4
  const { getFloorScale } = MathHelper;
@@ -132,145 +132,136 @@ var __decorateClass = (decorators, target, key, kind) => {
132
132
  installStaggerPattern();
133
133
  const debug = Debug.get("leafer-x-watermark");
134
134
  class ProcessorData extends RectData {
135
- __leaf;
136
- _tileContent;
135
+ _tileContent = "";
136
+ _cachedUrl;
137
+ _cachedBounds;
137
138
  setTileContent(value) {
138
139
  this._tileContent = value;
139
- this.__leaf.regenerateImage();
140
+ return this.regenerateImage();
140
141
  }
141
- _tileMode;
142
+ _tileMode = true;
142
143
  setTileMode(value) {
143
144
  this._tileMode = value;
144
- this.__leaf.updateFill();
145
+ this.updateFill();
145
146
  }
146
- _tileSize;
147
+ _tileSize = 100;
147
148
  setTileSize(value) {
148
149
  this._tileSize = value;
149
- this.__leaf.updateFill();
150
+ this.updateFill();
150
151
  }
151
- _tileGap;
152
+ _tileGap = 0;
152
153
  setTileGap(value) {
153
154
  this._tileGap = value;
154
- this.__leaf.updateFill();
155
+ this.updateFill();
155
156
  }
156
- _tileStagger;
157
+ _tileStagger = 0;
157
158
  setTileStagger(value) {
158
159
  this._tileStagger = value;
159
- this.__leaf.updateFill();
160
+ this.updateFill();
160
161
  }
161
- _tileRotation;
162
+ _tileRotation = 0;
162
163
  setTileRotation(value) {
163
164
  this._tileRotation = value;
164
- this.__leaf.updateFill();
165
+ this.updateFill();
166
+ }
167
+ updateFill() {
168
+ const leaf = this.__leaf;
169
+ const { _tileMode, _tileSize, _tileGap, _tileStagger, _tileRotation } = this;
170
+ if (!this._cachedUrl || !this._cachedBounds || _tileSize <= 0) {
171
+ leaf.fill = void 0;
172
+ return;
173
+ }
174
+ const { width: boundsWidth, height: boundsHeight } = this._cachedBounds;
175
+ if (!_tileMode) {
176
+ leaf.fill = {
177
+ type: "image",
178
+ url: this._cachedUrl,
179
+ mode: "stretch"
180
+ };
181
+ } else {
182
+ const scale = _tileSize / 100;
183
+ const sizeWidth = boundsWidth * scale;
184
+ const sizeHeight = boundsHeight * scale;
185
+ let xGap, yGap;
186
+ if (isObject(_tileGap)) {
187
+ xGap = _tileGap.x;
188
+ yGap = _tileGap.y;
189
+ } else {
190
+ xGap = yGap = _tileGap;
191
+ }
192
+ const gapX = xGap / 100 * sizeWidth;
193
+ const gapY = yGap / 100 * sizeHeight;
194
+ leaf.fill = {
195
+ type: "image",
196
+ url: this._cachedUrl,
197
+ mode: "repeat",
198
+ gap: { x: gapX, y: gapY },
199
+ size: { width: sizeWidth, height: sizeHeight },
200
+ stagger: _tileStagger,
201
+ rotation: _tileRotation,
202
+ align: "center"
203
+ };
204
+ }
165
205
  }
166
206
  __getData() {
167
207
  const data = super.__getData();
168
- if (data.url)
169
- delete data.fill;
208
+ delete data.fill;
170
209
  return data;
171
210
  }
172
211
  __getInputData(names, options) {
173
212
  const data = super.__getInputData(names, options);
174
- if (data.url)
175
- delete data.fill;
213
+ delete data.fill;
176
214
  return data;
177
215
  }
178
- }
179
- let Watermark = class extends Rect {
180
- get __tag() {
181
- return "Watermark";
182
- }
183
- // 缓存导出的图片和尺寸信息
184
- _cachedUrl;
185
- _cachedBounds;
186
- constructor(data) {
187
- super(data);
188
- this.regenerateImage();
189
- }
190
216
  createTileItem(itemData) {
191
217
  return UICreator.get("Group", {
192
218
  children: [itemData],
193
- // rotation: this.tileRotation,
194
219
  around: "center"
195
220
  });
196
221
  }
197
- regenerateImage() {
198
- Platform.requestRender(async () => {
199
- const { tileContent, width, height } = this;
200
- if (!tileContent) {
201
- this._cachedUrl = void 0;
202
- this._cachedBounds = void 0;
203
- this.fill = void 0;
204
- return;
205
- }
206
- let itemData;
207
- try {
208
- itemData = JSON.parse(tileContent);
209
- } catch (e) {
210
- debug.error("Invalid tileContent JSON:", e);
211
- return;
212
- }
213
- const tempItem = this.createTileItem(itemData);
214
- const bounds = tempItem.getBounds("box", "local");
215
- if (!width || !height) {
216
- this.width = bounds.width;
217
- this.height = bounds.height;
218
- }
219
- const exportWidth = 1e3;
220
- const { data: url } = await tempItem.export("png", {
221
- blob: false,
222
- size: { width: exportWidth }
223
- });
224
- this._cachedUrl = url;
225
- this._cachedBounds = { width: bounds.width, height: bounds.height };
226
- tempItem.destroy();
227
- this.updateFill();
222
+ async regenerateImage() {
223
+ const leaf = this.__leaf;
224
+ const { _tileContent } = this;
225
+ const { width, height } = leaf;
226
+ if (!_tileContent) {
227
+ this._cachedUrl = void 0;
228
+ this._cachedBounds = void 0;
229
+ leaf.fill = void 0;
230
+ return;
231
+ }
232
+ let itemData;
233
+ try {
234
+ itemData = JSON.parse(_tileContent);
235
+ } catch (e) {
236
+ debug.error("Invalid tileContent JSON:", e);
237
+ return;
238
+ }
239
+ const tempItem = this.createTileItem(itemData);
240
+ const bounds = tempItem.getBounds("box", "local");
241
+ if (!width || !height) {
242
+ leaf.width = bounds.width;
243
+ leaf.height = bounds.height;
244
+ }
245
+ const exportWidth = 1e3;
246
+ const { data: url } = await tempItem.export("png", {
247
+ blob: false,
248
+ size: { width: exportWidth }
228
249
  });
250
+ this._cachedUrl = url;
251
+ this._cachedBounds = { width: bounds.width, height: bounds.height };
252
+ tempItem.destroy();
253
+ this.updateFill();
229
254
  }
230
- updateFill() {
231
- Platform.requestRender(() => {
232
- const { tileMode, tileSize, tileGap, tileStagger } = this;
233
- if (!this._cachedUrl || !this._cachedBounds || tileSize <= 0) {
234
- this.fill = void 0;
235
- return;
236
- }
237
- const { width: boundsWidth, height: boundsHeight } = this._cachedBounds;
238
- if (!tileMode) {
239
- this.fill = {
240
- type: "image",
241
- url: this._cachedUrl,
242
- mode: "stretch"
243
- };
244
- } else {
245
- const scale = tileSize / 100;
246
- const sizeWidth = boundsWidth * scale;
247
- const sizeHeight = boundsHeight * scale;
248
- let xGap, yGap;
249
- if (isObject(tileGap)) {
250
- xGap = tileGap.x;
251
- yGap = tileGap.y;
252
- } else {
253
- xGap = yGap = tileGap;
254
- }
255
- const gapX = xGap / 100 * sizeWidth;
256
- const gapY = yGap / 100 * sizeHeight;
257
- this.fill = {
258
- type: "image",
259
- url: this._cachedUrl,
260
- mode: "repeat",
261
- gap: { x: gapX, y: gapY },
262
- size: { width: sizeWidth, height: sizeHeight },
263
- stagger: tileStagger,
264
- rotation: this.tileRotation,
265
- align: "center"
266
- };
267
- }
268
- });
255
+ }
256
+ let Watermark = class extends Rect {
257
+ get __tag() {
258
+ return "Watermark";
259
+ }
260
+ get tileURL() {
261
+ return this.__._cachedUrl;
269
262
  }
270
- toJSON(options) {
271
- const data = super.toJSON(options);
272
- const { fill, ...cleanData } = data;
273
- return cleanData;
263
+ constructor(data) {
264
+ super(data);
274
265
  }
275
266
  };
276
267
  __decorateClass([
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "leafer-x-watermark",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "1.1.1",
5
5
  "packageManager": "pnpm@10.14.0",
6
6
  "description": "Leafer 水印插件",
7
7
  "author": "XiaDeYu <1579883916@qq.com>",