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 +11 -9
- package/dist/index.d.mts +22 -12
- package/dist/index.mjs +96 -105
- package/package.json +1 -1
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,
|
|
69
|
-
tileGap: 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,
|
|
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` |
|
|
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
|
-
|
|
167
|
+
错位排列效果,支持数值 (0-100) 或对象配置:
|
|
168
|
+
- `tileStagger: 50` = 水平方向(x)相邻行偏移 50%
|
|
169
|
+
- `{ type: 'y', offset: 50 }` = 垂直方向(y)相邻列偏移 50%
|
|
167
170
|
- `0` = 无错位
|
|
168
|
-
- `
|
|
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,
|
|
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?:
|
|
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
|
-
|
|
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?:
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
136
|
-
|
|
135
|
+
_tileContent = "";
|
|
136
|
+
_cachedUrl;
|
|
137
|
+
_cachedBounds;
|
|
137
138
|
setTileContent(value) {
|
|
138
139
|
this._tileContent = value;
|
|
139
|
-
this.
|
|
140
|
+
return this.regenerateImage();
|
|
140
141
|
}
|
|
141
|
-
_tileMode;
|
|
142
|
+
_tileMode = true;
|
|
142
143
|
setTileMode(value) {
|
|
143
144
|
this._tileMode = value;
|
|
144
|
-
this.
|
|
145
|
+
this.updateFill();
|
|
145
146
|
}
|
|
146
|
-
_tileSize;
|
|
147
|
+
_tileSize = 100;
|
|
147
148
|
setTileSize(value) {
|
|
148
149
|
this._tileSize = value;
|
|
149
|
-
this.
|
|
150
|
+
this.updateFill();
|
|
150
151
|
}
|
|
151
|
-
_tileGap;
|
|
152
|
+
_tileGap = 0;
|
|
152
153
|
setTileGap(value) {
|
|
153
154
|
this._tileGap = value;
|
|
154
|
-
this.
|
|
155
|
+
this.updateFill();
|
|
155
156
|
}
|
|
156
|
-
_tileStagger;
|
|
157
|
+
_tileStagger = 0;
|
|
157
158
|
setTileStagger(value) {
|
|
158
159
|
this._tileStagger = value;
|
|
159
|
-
this.
|
|
160
|
+
this.updateFill();
|
|
160
161
|
}
|
|
161
|
-
_tileRotation;
|
|
162
|
+
_tileRotation = 0;
|
|
162
163
|
setTileRotation(value) {
|
|
163
164
|
this._tileRotation = value;
|
|
164
|
-
this.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
const { fill, ...cleanData } = data;
|
|
273
|
-
return cleanData;
|
|
263
|
+
constructor(data) {
|
|
264
|
+
super(data);
|
|
274
265
|
}
|
|
275
266
|
};
|
|
276
267
|
__decorateClass([
|