hy-app 0.4.10 → 0.4.12
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/components/hy-card/hy-card.vue +55 -27
- package/components/hy-card/index.scss +13 -5
- package/components/hy-flex/hy-flex.vue +3 -6
- package/components/hy-folding-panel/hy-folding-panel.vue +345 -111
- package/components/hy-folding-panel-item/hy-folding-panel-item.vue +228 -0
- package/components/hy-grid/hy-grid.vue +2 -2
- package/components/hy-qrcode/hy-qrcode.vue +1 -1
- package/components/hy-qrcode/qrcode.js +134 -0
- package/components/hy-search/hy-search.vue +13 -6
- package/components/hy-search/index.scss +4 -0
- package/components/hy-watermark/hy-watermark.vue +413 -17
- package/package.json +2 -2
- package/web-types.json +1 -1
|
@@ -38,7 +38,22 @@ defineOptions({});
|
|
|
38
38
|
|
|
39
39
|
// const props = withDefaults(defineProps<IProps>(), defaultProps)
|
|
40
40
|
const props = defineProps({
|
|
41
|
-
/**
|
|
41
|
+
/** 显示主标题 */
|
|
42
|
+
title: {
|
|
43
|
+
type: String,
|
|
44
|
+
default: "",
|
|
45
|
+
},
|
|
46
|
+
/** 主标题颜色 */
|
|
47
|
+
titleColor: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: "",
|
|
50
|
+
},
|
|
51
|
+
/** 主标题字体大小,单位px */
|
|
52
|
+
titleSize: {
|
|
53
|
+
type: Number,
|
|
54
|
+
default: 0,
|
|
55
|
+
},
|
|
56
|
+
/** 显示副标题内容 */
|
|
42
57
|
content: {
|
|
43
58
|
type: String,
|
|
44
59
|
default: "",
|
|
@@ -205,6 +220,7 @@ function doInit() {
|
|
|
205
220
|
image,
|
|
206
221
|
imageHeight,
|
|
207
222
|
imageWidth,
|
|
223
|
+
title
|
|
208
224
|
} = props;
|
|
209
225
|
|
|
210
226
|
// 创建水印
|
|
@@ -223,6 +239,7 @@ function doInit() {
|
|
|
223
239
|
image,
|
|
224
240
|
imageHeight,
|
|
225
241
|
imageWidth,
|
|
242
|
+
title
|
|
226
243
|
);
|
|
227
244
|
}
|
|
228
245
|
|
|
@@ -242,6 +259,7 @@ function doInit() {
|
|
|
242
259
|
* @param image canvas图片
|
|
243
260
|
* @param imageHeight canvas图片高度
|
|
244
261
|
* @param imageWidth canvas图片宽度
|
|
262
|
+
* @param title 标题
|
|
245
263
|
*/
|
|
246
264
|
function createWaterMark(
|
|
247
265
|
width: number,
|
|
@@ -258,12 +276,16 @@ function createWaterMark(
|
|
|
258
276
|
image: string,
|
|
259
277
|
imageHeight: number,
|
|
260
278
|
imageWidth: number,
|
|
279
|
+
title: string,
|
|
261
280
|
) {
|
|
262
281
|
const canvasHeight = (height + gutterY) * pixelRatio.value;
|
|
263
282
|
const canvasWidth = (width + gutterX) * pixelRatio.value;
|
|
264
283
|
const contentWidth = width * pixelRatio.value;
|
|
265
284
|
const contentHeight = height * pixelRatio.value;
|
|
266
285
|
const fontSize = size * pixelRatio.value;
|
|
286
|
+
// 标题字体大小:如果设置了titleSize则使用titleSize,否则使用size的1.2倍
|
|
287
|
+
const titleFontSize = props.titleSize > 0 ? props.titleSize * pixelRatio.value : fontSize * 1.2;
|
|
288
|
+
|
|
267
289
|
// #ifndef H5
|
|
268
290
|
if (canvasOffScreenable.value) {
|
|
269
291
|
createOffscreenCanvas(
|
|
@@ -281,6 +303,8 @@ function createWaterMark(
|
|
|
281
303
|
image,
|
|
282
304
|
imageHeight,
|
|
283
305
|
imageWidth,
|
|
306
|
+
title,
|
|
307
|
+
titleFontSize
|
|
284
308
|
);
|
|
285
309
|
} else {
|
|
286
310
|
createCanvas(
|
|
@@ -293,6 +317,8 @@ function createWaterMark(
|
|
|
293
317
|
image,
|
|
294
318
|
imageHeight,
|
|
295
319
|
imageWidth,
|
|
320
|
+
title,
|
|
321
|
+
titleFontSize
|
|
296
322
|
);
|
|
297
323
|
}
|
|
298
324
|
// #endif
|
|
@@ -312,6 +338,8 @@ function createWaterMark(
|
|
|
312
338
|
image,
|
|
313
339
|
imageHeight,
|
|
314
340
|
imageWidth,
|
|
341
|
+
title,
|
|
342
|
+
titleFontSize
|
|
315
343
|
);
|
|
316
344
|
// #endif
|
|
317
345
|
}
|
|
@@ -348,6 +376,8 @@ function createOffscreenCanvas(
|
|
|
348
376
|
image: string,
|
|
349
377
|
imageHeight: number,
|
|
350
378
|
imageWidth: number,
|
|
379
|
+
title: string,
|
|
380
|
+
titleFontSize: number
|
|
351
381
|
) {
|
|
352
382
|
// 创建离屏canvas
|
|
353
383
|
const canvas: any = uni.createOffscreenCanvas({
|
|
@@ -357,7 +387,29 @@ function createOffscreenCanvas(
|
|
|
357
387
|
});
|
|
358
388
|
const ctx: any = canvas.getContext("2d");
|
|
359
389
|
if (ctx) {
|
|
360
|
-
if (image) {
|
|
390
|
+
if (image && (title || content)) {
|
|
391
|
+
// 图片和文字同时显示
|
|
392
|
+
const img = canvas.createImage() as HTMLImageElement;
|
|
393
|
+
drawImageAndTextOffScreen(
|
|
394
|
+
ctx,
|
|
395
|
+
img,
|
|
396
|
+
image,
|
|
397
|
+
imageHeight,
|
|
398
|
+
imageWidth,
|
|
399
|
+
title,
|
|
400
|
+
content,
|
|
401
|
+
rotate,
|
|
402
|
+
contentWidth,
|
|
403
|
+
contentHeight,
|
|
404
|
+
fontSize,
|
|
405
|
+
titleFontSize,
|
|
406
|
+
fontFamily,
|
|
407
|
+
fontStyle,
|
|
408
|
+
fontWeight,
|
|
409
|
+
color,
|
|
410
|
+
canvas,
|
|
411
|
+
);
|
|
412
|
+
} else if (image) {
|
|
361
413
|
const img = canvas.createImage() as HTMLImageElement;
|
|
362
414
|
drawImageOffScreen(
|
|
363
415
|
ctx,
|
|
@@ -373,7 +425,7 @@ function createOffscreenCanvas(
|
|
|
373
425
|
} else {
|
|
374
426
|
drawTextOffScreen(
|
|
375
427
|
ctx,
|
|
376
|
-
|
|
428
|
+
title,
|
|
377
429
|
contentWidth,
|
|
378
430
|
contentHeight,
|
|
379
431
|
rotate,
|
|
@@ -383,6 +435,8 @@ function createOffscreenCanvas(
|
|
|
383
435
|
fontWeight,
|
|
384
436
|
color,
|
|
385
437
|
canvas,
|
|
438
|
+
content,
|
|
439
|
+
titleFontSize
|
|
386
440
|
);
|
|
387
441
|
}
|
|
388
442
|
} else {
|
|
@@ -413,10 +467,28 @@ function createCanvas(
|
|
|
413
467
|
image: string,
|
|
414
468
|
imageHeight: number,
|
|
415
469
|
imageWidth: number,
|
|
470
|
+
title: string,
|
|
471
|
+
titleFontSize: number
|
|
416
472
|
) {
|
|
417
473
|
const ctx = uni.createCanvasContext(canvasId.value);
|
|
418
474
|
if (ctx) {
|
|
419
|
-
if (image) {
|
|
475
|
+
if (image && (title || content)) {
|
|
476
|
+
// 图片和文字同时显示
|
|
477
|
+
drawImageAndTextOnScreen(
|
|
478
|
+
ctx,
|
|
479
|
+
image,
|
|
480
|
+
imageHeight,
|
|
481
|
+
imageWidth,
|
|
482
|
+
title,
|
|
483
|
+
content,
|
|
484
|
+
rotate,
|
|
485
|
+
contentWidth,
|
|
486
|
+
contentHeight,
|
|
487
|
+
fontSize,
|
|
488
|
+
titleFontSize,
|
|
489
|
+
color
|
|
490
|
+
);
|
|
491
|
+
} else if (image) {
|
|
420
492
|
drawImageOnScreen(
|
|
421
493
|
ctx,
|
|
422
494
|
image,
|
|
@@ -427,7 +499,7 @@ function createCanvas(
|
|
|
427
499
|
contentHeight,
|
|
428
500
|
);
|
|
429
501
|
} else {
|
|
430
|
-
drawTextOnScreen(ctx,
|
|
502
|
+
drawTextOnScreen(ctx, title, contentWidth, rotate, fontSize, color, content, titleFontSize);
|
|
431
503
|
}
|
|
432
504
|
} else {
|
|
433
505
|
console.error("无法获取canvas上下文,请确认当前环境是否支持canvas");
|
|
@@ -466,13 +538,37 @@ function createH5Canvas(
|
|
|
466
538
|
image: string,
|
|
467
539
|
imageHeight: number,
|
|
468
540
|
imageWidth: number,
|
|
541
|
+
title: string,
|
|
542
|
+
titleFontSize: number
|
|
469
543
|
) {
|
|
470
544
|
const canvas = document.createElement("canvas");
|
|
471
545
|
const ctx = canvas.getContext("2d");
|
|
472
546
|
canvas.setAttribute("width", `${canvasWidth}px`);
|
|
473
547
|
canvas.setAttribute("height", `${canvasHeight}px`);
|
|
474
548
|
if (ctx) {
|
|
475
|
-
if (image) {
|
|
549
|
+
if (image && (title || content)) {
|
|
550
|
+
// 图片和文字同时显示
|
|
551
|
+
const img = new Image();
|
|
552
|
+
drawImageAndTextOffScreen(
|
|
553
|
+
ctx,
|
|
554
|
+
img,
|
|
555
|
+
image,
|
|
556
|
+
imageHeight,
|
|
557
|
+
imageWidth,
|
|
558
|
+
title,
|
|
559
|
+
content,
|
|
560
|
+
rotate,
|
|
561
|
+
contentWidth,
|
|
562
|
+
contentHeight,
|
|
563
|
+
fontSize,
|
|
564
|
+
titleFontSize,
|
|
565
|
+
fontFamily,
|
|
566
|
+
fontStyle,
|
|
567
|
+
fontWeight,
|
|
568
|
+
color,
|
|
569
|
+
canvas,
|
|
570
|
+
);
|
|
571
|
+
} else if (image) {
|
|
476
572
|
const img = new Image();
|
|
477
573
|
drawImageOffScreen(
|
|
478
574
|
ctx,
|
|
@@ -488,7 +584,7 @@ function createH5Canvas(
|
|
|
488
584
|
} else {
|
|
489
585
|
drawTextOffScreen(
|
|
490
586
|
ctx,
|
|
491
|
-
|
|
587
|
+
title,
|
|
492
588
|
contentWidth,
|
|
493
589
|
contentHeight,
|
|
494
590
|
rotate,
|
|
@@ -498,6 +594,8 @@ function createH5Canvas(
|
|
|
498
594
|
fontWeight,
|
|
499
595
|
color,
|
|
500
596
|
canvas,
|
|
597
|
+
content,
|
|
598
|
+
titleFontSize
|
|
501
599
|
);
|
|
502
600
|
}
|
|
503
601
|
} else {
|
|
@@ -519,9 +617,32 @@ function createH5Canvas(
|
|
|
519
617
|
* @param color 水印字体颜色
|
|
520
618
|
* @param canvas canvas实例
|
|
521
619
|
*/
|
|
620
|
+
// 测量文本宽度并自动换行
|
|
621
|
+
function wrapText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number, fontSize: number) {
|
|
622
|
+
const words = text.split('');
|
|
623
|
+
const lines: string[] = [];
|
|
624
|
+
let currentLine = '';
|
|
625
|
+
|
|
626
|
+
for (let i = 0; i < words.length; i++) {
|
|
627
|
+
const testLine = currentLine + words[i];
|
|
628
|
+
const metrics = ctx.measureText(testLine);
|
|
629
|
+
const testWidth = metrics.width;
|
|
630
|
+
|
|
631
|
+
// 当文字宽度超过容器宽度的80%时换行
|
|
632
|
+
if (testWidth > maxWidth * 0.8 && currentLine !== '') {
|
|
633
|
+
lines.push(currentLine);
|
|
634
|
+
currentLine = words[i];
|
|
635
|
+
} else {
|
|
636
|
+
currentLine = testLine;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
lines.push(currentLine);
|
|
640
|
+
return lines;
|
|
641
|
+
}
|
|
642
|
+
|
|
522
643
|
function drawTextOffScreen(
|
|
523
644
|
ctx: CanvasRenderingContext2D,
|
|
524
|
-
|
|
645
|
+
title: string,
|
|
525
646
|
contentWidth: number,
|
|
526
647
|
contentHeight: number,
|
|
527
648
|
rotate: number,
|
|
@@ -531,15 +652,50 @@ function drawTextOffScreen(
|
|
|
531
652
|
fontWeight: string | number,
|
|
532
653
|
color: string,
|
|
533
654
|
canvas: HTMLCanvasElement,
|
|
655
|
+
content: string = '',
|
|
656
|
+
titleFontSize: number = 0
|
|
534
657
|
) {
|
|
535
|
-
console.log(fontSize, "离屏");
|
|
536
658
|
ctx.textBaseline = "middle";
|
|
537
659
|
ctx.textAlign = "center";
|
|
538
|
-
ctx.translate(contentWidth / 2,
|
|
660
|
+
ctx.translate(contentWidth / 2, contentHeight / 2);
|
|
539
661
|
ctx.rotate((Math.PI / 180) * rotate);
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
662
|
+
|
|
663
|
+
// 计算总高度
|
|
664
|
+
let totalTextHeight = titleFontSize;
|
|
665
|
+
if (content) {
|
|
666
|
+
totalTextHeight += fontSize + 5; // 标题和副标题之间的间距
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// 起始Y坐标
|
|
670
|
+
let startY = -totalTextHeight / 2;
|
|
671
|
+
|
|
672
|
+
// 绘制主标题(支持自动换行)
|
|
673
|
+
if (title) {
|
|
674
|
+
ctx.font = `${fontStyle} normal ${fontWeight} ${titleFontSize}px/${contentHeight}px ${fontFamily}`;
|
|
675
|
+
// 使用titleColor或默认color
|
|
676
|
+
ctx.fillStyle = props.titleColor || color;
|
|
677
|
+
const titleLines = wrapText(ctx, title, contentWidth, titleFontSize);
|
|
678
|
+
const titleLineHeight = titleFontSize * 1.2;
|
|
679
|
+
|
|
680
|
+
for (let i = 0; i < titleLines.length; i++) {
|
|
681
|
+
ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
startY += titleLines.length * titleLineHeight + 5;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// 绘制副标题(支持自动换行)
|
|
688
|
+
if (content) {
|
|
689
|
+
ctx.font = `${fontStyle} normal ${fontWeight} ${fontSize}px/${contentHeight}px ${fontFamily}`;
|
|
690
|
+
ctx.fillStyle = color;
|
|
691
|
+
const contentLines = wrapText(ctx, content, contentWidth, fontSize);
|
|
692
|
+
const contentLineHeight = fontSize * 1.2;
|
|
693
|
+
|
|
694
|
+
for (let i = 0; i < contentLines.length; i++) {
|
|
695
|
+
ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
543
699
|
ctx.restore();
|
|
544
700
|
waterMarkUrl.value = canvas.toDataURL();
|
|
545
701
|
}
|
|
@@ -553,21 +709,79 @@ function drawTextOffScreen(
|
|
|
553
709
|
* @param fontSize 水印字体大小
|
|
554
710
|
* @param color 水印字体颜色
|
|
555
711
|
*/
|
|
712
|
+
// 简化版本的文字换行(UniApp CanvasContext不支持measureText)
|
|
713
|
+
function simpleWrapText(text: string, maxLength: number) {
|
|
714
|
+
const lines: string[] = [];
|
|
715
|
+
let currentLine = '';
|
|
716
|
+
|
|
717
|
+
// 基于字符数估算换行(适用于UniApp CanvasContext)
|
|
718
|
+
for (let i = 0; i < text.length; i++) {
|
|
719
|
+
currentLine += text[i];
|
|
720
|
+
if (currentLine.length >= maxLength) {
|
|
721
|
+
lines.push(currentLine);
|
|
722
|
+
currentLine = '';
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (currentLine) {
|
|
726
|
+
lines.push(currentLine);
|
|
727
|
+
}
|
|
728
|
+
return lines;
|
|
729
|
+
}
|
|
730
|
+
|
|
556
731
|
function drawTextOnScreen(
|
|
557
732
|
ctx: UniApp.CanvasContext,
|
|
558
|
-
|
|
733
|
+
title: string,
|
|
559
734
|
contentWidth: number,
|
|
560
735
|
rotate: number,
|
|
561
736
|
fontSize: number,
|
|
562
737
|
color: string,
|
|
738
|
+
content: string = '',
|
|
739
|
+
titleFontSize: number = 0
|
|
563
740
|
) {
|
|
564
741
|
ctx.setTextBaseline("middle");
|
|
565
742
|
ctx.setTextAlign("center");
|
|
566
743
|
ctx.translate(contentWidth / 2, contentWidth / 2);
|
|
567
744
|
ctx.rotate((Math.PI / 180) * rotate);
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
745
|
+
|
|
746
|
+
// 估算每行最大字符数
|
|
747
|
+
const maxChars = Math.floor(contentWidth / (fontSize * 0.5));
|
|
748
|
+
|
|
749
|
+
// 计算总高度
|
|
750
|
+
let totalTextHeight = titleFontSize;
|
|
751
|
+
if (content) {
|
|
752
|
+
totalTextHeight += fontSize + 5;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// 起始Y坐标
|
|
756
|
+
let startY = -totalTextHeight / 2;
|
|
757
|
+
|
|
758
|
+
// 绘制主标题(支持自动换行)
|
|
759
|
+
if (title) {
|
|
760
|
+
// 使用titleColor或默认color
|
|
761
|
+
ctx.setFillStyle(props.titleColor || color);
|
|
762
|
+
ctx.setFontSize(titleFontSize);
|
|
763
|
+
const titleLines = simpleWrapText(title, maxChars);
|
|
764
|
+
const titleLineHeight = titleFontSize * 1.2;
|
|
765
|
+
|
|
766
|
+
for (let i = 0; i < titleLines.length; i++) {
|
|
767
|
+
ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
startY += titleLines.length * titleLineHeight + 5;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// 绘制副标题(支持自动换行)
|
|
774
|
+
if (content) {
|
|
775
|
+
ctx.setFillStyle(color);
|
|
776
|
+
ctx.setFontSize(fontSize);
|
|
777
|
+
const contentLines = simpleWrapText(content, maxChars);
|
|
778
|
+
const contentLineHeight = fontSize * 1.2;
|
|
779
|
+
|
|
780
|
+
for (let i = 0; i < contentLines.length; i++) {
|
|
781
|
+
ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
571
785
|
ctx.restore();
|
|
572
786
|
ctx.draw();
|
|
573
787
|
// #ifdef MP-DINGTALK
|
|
@@ -632,6 +846,188 @@ async function drawImageOffScreen(
|
|
|
632
846
|
};
|
|
633
847
|
}
|
|
634
848
|
|
|
849
|
+
// 绘制图片和文字(离屏)
|
|
850
|
+
async function drawImageAndTextOffScreen(
|
|
851
|
+
ctx: CanvasRenderingContext2D,
|
|
852
|
+
img: HTMLImageElement,
|
|
853
|
+
image: string,
|
|
854
|
+
imageHeight: number,
|
|
855
|
+
imageWidth: number,
|
|
856
|
+
title: string,
|
|
857
|
+
content: string,
|
|
858
|
+
rotate: number,
|
|
859
|
+
contentWidth: number,
|
|
860
|
+
contentHeight: number,
|
|
861
|
+
fontSize: number,
|
|
862
|
+
titleFontSize: number,
|
|
863
|
+
fontFamily: string,
|
|
864
|
+
fontStyle: string,
|
|
865
|
+
fontWeight: string | number,
|
|
866
|
+
color: string,
|
|
867
|
+
canvas: HTMLCanvasElement,
|
|
868
|
+
) {
|
|
869
|
+
ctx.translate(contentWidth / 2, contentHeight / 2);
|
|
870
|
+
ctx.rotate((Math.PI / 180) * Number(rotate));
|
|
871
|
+
img.crossOrigin = "anonymous";
|
|
872
|
+
img.referrerPolicy = "no-referrer";
|
|
873
|
+
|
|
874
|
+
const imgHeight = imageHeight * pixelRatio.value;
|
|
875
|
+
const imgWidth = imageWidth * pixelRatio.value;
|
|
876
|
+
|
|
877
|
+
img.src = image;
|
|
878
|
+
img.onload = () => {
|
|
879
|
+
// 计算总高度
|
|
880
|
+
let totalHeight = imgHeight;
|
|
881
|
+
const textSpacing = 10;
|
|
882
|
+
|
|
883
|
+
if (title) totalHeight += textSpacing + titleFontSize;
|
|
884
|
+
if (content) totalHeight += fontSize;
|
|
885
|
+
|
|
886
|
+
// 起始Y坐标
|
|
887
|
+
let startY = -totalHeight / 2;
|
|
888
|
+
|
|
889
|
+
// 绘制图片
|
|
890
|
+
ctx.drawImage(
|
|
891
|
+
img,
|
|
892
|
+
-imgWidth / 2,
|
|
893
|
+
startY,
|
|
894
|
+
imgWidth,
|
|
895
|
+
imgHeight,
|
|
896
|
+
);
|
|
897
|
+
|
|
898
|
+
startY += imgHeight + textSpacing;
|
|
899
|
+
|
|
900
|
+
// 设置文字样式
|
|
901
|
+
ctx.textBaseline = "top";
|
|
902
|
+
ctx.textAlign = "center";
|
|
903
|
+
|
|
904
|
+
// 绘制主标题
|
|
905
|
+
if (title) {
|
|
906
|
+
ctx.font = `${fontStyle} normal ${fontWeight} ${titleFontSize}px/${contentHeight}px ${fontFamily}`;
|
|
907
|
+
// 使用titleColor或默认color
|
|
908
|
+
ctx.fillStyle = props.titleColor || color;
|
|
909
|
+
const titleLines = wrapText(ctx, title, contentWidth * 0.9, titleFontSize);
|
|
910
|
+
const titleLineHeight = titleFontSize * 1.2;
|
|
911
|
+
|
|
912
|
+
for (let i = 0; i < titleLines.length; i++) {
|
|
913
|
+
ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
startY += titleLines.length * titleLineHeight + 5;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
// 绘制副标题
|
|
920
|
+
if (content) {
|
|
921
|
+
ctx.font = `${fontStyle} normal ${fontWeight} ${fontSize}px/${contentHeight}px ${fontFamily}`;
|
|
922
|
+
ctx.fillStyle = color;
|
|
923
|
+
const contentLines = wrapText(ctx, content, contentWidth * 0.9, fontSize);
|
|
924
|
+
const contentLineHeight = fontSize * 1.2;
|
|
925
|
+
|
|
926
|
+
for (let i = 0; i < contentLines.length; i++) {
|
|
927
|
+
ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
ctx.restore();
|
|
932
|
+
waterMarkUrl.value = canvas.toDataURL();
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
// 绘制图片和文字(在屏)
|
|
937
|
+
function drawImageAndTextOnScreen(
|
|
938
|
+
ctx: UniApp.CanvasContext,
|
|
939
|
+
image: string,
|
|
940
|
+
imageHeight: number,
|
|
941
|
+
imageWidth: number,
|
|
942
|
+
title: string,
|
|
943
|
+
content: string,
|
|
944
|
+
rotate: number,
|
|
945
|
+
contentWidth: number,
|
|
946
|
+
contentHeight: number,
|
|
947
|
+
fontSize: number,
|
|
948
|
+
titleFontSize: number,
|
|
949
|
+
color: string
|
|
950
|
+
) {
|
|
951
|
+
ctx.setTextBaseline("top");
|
|
952
|
+
ctx.setTextAlign("center");
|
|
953
|
+
ctx.translate(contentWidth / 2, contentWidth / 2);
|
|
954
|
+
ctx.rotate((Math.PI / 180) * Number(rotate));
|
|
955
|
+
|
|
956
|
+
const imgHeight = imageHeight * pixelRatio.value;
|
|
957
|
+
const imgWidth = imageWidth * pixelRatio.value;
|
|
958
|
+
const maxChars = Math.floor(contentWidth / (fontSize * 0.5));
|
|
959
|
+
|
|
960
|
+
// 计算总高度
|
|
961
|
+
let totalHeight = imgHeight;
|
|
962
|
+
const textSpacing = 10;
|
|
963
|
+
|
|
964
|
+
if (title) totalHeight += textSpacing + titleFontSize;
|
|
965
|
+
if (content) totalHeight += fontSize;
|
|
966
|
+
|
|
967
|
+
// 起始Y坐标
|
|
968
|
+
let startY = -totalHeight / 2;
|
|
969
|
+
|
|
970
|
+
// 绘制图片
|
|
971
|
+
ctx.drawImage(
|
|
972
|
+
image,
|
|
973
|
+
-imgWidth / 2,
|
|
974
|
+
startY,
|
|
975
|
+
imgWidth,
|
|
976
|
+
imgHeight,
|
|
977
|
+
);
|
|
978
|
+
|
|
979
|
+
startY += imgHeight + textSpacing;
|
|
980
|
+
|
|
981
|
+
// 绘制主标题
|
|
982
|
+
if (title) {
|
|
983
|
+
// 使用titleColor或默认color
|
|
984
|
+
ctx.setFillStyle(props.titleColor || color);
|
|
985
|
+
ctx.setFontSize(titleFontSize);
|
|
986
|
+
const titleLines = simpleWrapText(title, maxChars);
|
|
987
|
+
const titleLineHeight = titleFontSize * 1.2;
|
|
988
|
+
|
|
989
|
+
for (let i = 0; i < titleLines.length; i++) {
|
|
990
|
+
ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
startY += titleLines.length * titleLineHeight + 5;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// 绘制副标题
|
|
997
|
+
if (content) {
|
|
998
|
+
ctx.setFillStyle(color);
|
|
999
|
+
ctx.setFontSize(fontSize);
|
|
1000
|
+
const contentLines = simpleWrapText(content, maxChars);
|
|
1001
|
+
const contentLineHeight = fontSize * 1.2;
|
|
1002
|
+
|
|
1003
|
+
for (let i = 0; i < contentLines.length; i++) {
|
|
1004
|
+
ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
ctx.restore();
|
|
1009
|
+
ctx.draw(false, () => {
|
|
1010
|
+
// #ifdef MP-DINGTALK
|
|
1011
|
+
// 钉钉小程序的canvasToTempFilePath接口与其他平台不一样
|
|
1012
|
+
(ctx as any).toTempFilePath({
|
|
1013
|
+
success(res: any) {
|
|
1014
|
+
showCanvas.value = false;
|
|
1015
|
+
waterMarkUrl.value = res.filePath;
|
|
1016
|
+
},
|
|
1017
|
+
});
|
|
1018
|
+
// #endif
|
|
1019
|
+
// #ifndef MP-DINGTALK
|
|
1020
|
+
uni.canvasToTempFilePath({
|
|
1021
|
+
canvasId: canvasId.value,
|
|
1022
|
+
success: (res) => {
|
|
1023
|
+
showCanvas.value = false;
|
|
1024
|
+
waterMarkUrl.value = res.tempFilePath;
|
|
1025
|
+
},
|
|
1026
|
+
});
|
|
1027
|
+
// #endif
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
|
|
635
1031
|
/**
|
|
636
1032
|
* 绘制在屏图片canvas
|
|
637
1033
|
* @param ctx canvas上下文
|