@galacean/effects-plugin-rich-text 2.7.0-alpha.2 → 2.7.0

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.mjs CHANGED
@@ -3,7 +3,7 @@
3
3
  * Description: Galacean Effects player rich text plugin
4
4
  * Author: Ant Group CO., Ltd.
5
5
  * Contributors: 云垣
6
- * Version: v2.7.0-alpha.2
6
+ * Version: v2.7.0
7
7
  */
8
8
 
9
9
  import * as EFFECTS from '@galacean/effects';
@@ -410,7 +410,7 @@ var RichTextComponent = /*#__PURE__*/ function(TextComponent) {
410
410
  _this = TextComponent.call(this, engine) || this;
411
411
  _this.processedTextOptions = [];
412
412
  // 字体高度的倍数(字体高度上下多出来的部分就是行间距)
413
- _this.singleLineHeight = 1.0;
413
+ _this.singleLineHeight = 1.571;
414
414
  _this.size = null;
415
415
  /**
416
416
  * 获取第一次渲染的 size
@@ -458,17 +458,31 @@ var RichTextComponent = /*#__PURE__*/ function(TextComponent) {
458
458
  program(text);
459
459
  };
460
460
  _proto.updateTexture = function updateTexture(flipY) {
461
- var _this = this;
462
461
  if (flipY === void 0) flipY = true;
463
462
  if (!this.isDirty || !this.context || !this.canvas) {
464
463
  return;
465
464
  }
465
+ // 根据 useLegacyRichText 字段来判断使用哪种渲染模式
466
+ var useLegacy = this.textLayout.useLegacyRichText === true;
467
+ this.singleLineHeight = useLegacy ? 1.571 : 1.0;
468
+ if (useLegacy) {
469
+ this.updateTextureLegacy(flipY);
470
+ } else {
471
+ this.updateTextureModern(flipY);
472
+ }
473
+ };
474
+ _proto.updateTextureLegacy = function updateTextureLegacy(flipY) {
475
+ var _this = this;
476
+ if (!this.isDirty || !this.context || !this.canvas) {
477
+ return;
478
+ }
466
479
  // 解析富文本
467
480
  this.generateTextProgram(this.text);
468
- var width = 0, height = 0;
469
481
  var _this1 = this, textLayout = _this1.textLayout, textStyle = _this1.textStyle;
470
482
  var overflow = textLayout.overflow, _textLayout_letterSpace = textLayout.letterSpace, letterSpace = _textLayout_letterSpace === void 0 ? 0 : _textLayout_letterSpace;
471
483
  var context = this.context;
484
+ var width = 0;
485
+ var height = 0;
472
486
  context.save();
473
487
  var charsInfo = [];
474
488
  var fontHeight = textStyle.fontSize * this.textStyle.fontScale;
@@ -477,15 +491,14 @@ var RichTextComponent = /*#__PURE__*/ function(TextComponent) {
477
491
  offsetX: [],
478
492
  width: 0,
479
493
  // 包括字体和上下行间距的高度
480
- lineHeight: fontHeight * (this.singleLineHeight + (this.textLayout.lineGap || 0)),
494
+ lineHeight: fontHeight * this.singleLineHeight,
481
495
  // 字体偏移高度(也就是行间距)
482
- offsetY: fontHeight * (this.singleLineHeight + (this.textLayout.lineGap || 0) - 1) / 2,
483
- chars: []
496
+ offsetY: fontHeight * (this.singleLineHeight - 1) / 2
484
497
  };
485
498
  // 遍历解析后的文本选项
486
499
  this.processedTextOptions.forEach(function(options) {
487
500
  var text = options.text, isNewLine = options.isNewLine, fontSize = options.fontSize;
488
- // 如果是新行,则将之前行的信息存入charsInfo并且初始化新行的charInfo
501
+ // 如果是新行,则将之前行的信息存入 charsInfo 并且初始化新行的 charInfo
489
502
  if (isNewLine) {
490
503
  charsInfo.push(charInfo);
491
504
  width = Math.max(width, charInfo.width);
@@ -493,23 +506,181 @@ var RichTextComponent = /*#__PURE__*/ function(TextComponent) {
493
506
  richOptions: [],
494
507
  offsetX: [],
495
508
  width: 0,
496
- lineHeight: fontHeight * (_this.singleLineHeight + (_this.textLayout.lineGap || 0)),
497
- offsetY: fontHeight * (_this.singleLineHeight + (_this.textLayout.lineGap || 0) - 1) / 2,
498
- chars: []
509
+ lineHeight: fontHeight * _this.singleLineHeight,
510
+ offsetY: fontHeight * (_this.singleLineHeight - 1) / 2
499
511
  };
500
- // 管理行的总高度调整canvas尺寸
512
+ // 管理行的总高度调整 canvas 尺寸
501
513
  height += charInfo.lineHeight;
502
514
  }
503
515
  // 恢复默认设置
504
516
  context.font = (options.fontWeight || textStyle.textWeight) + " 10px " + (options.fontFamily || textStyle.fontFamily);
505
- var textHeight = fontSize * (_this.singleLineHeight + (_this.textLayout.lineGap || 0)) * _this.textStyle.fontScale;
517
+ // 计算得到每个字段的宽度 textWidth
518
+ var textMetrics = context.measureText(text);
519
+ var textWidth = textMetrics.width;
520
+ if (textMetrics.actualBoundingBoxLeft !== undefined && textMetrics.actualBoundingBoxRight !== undefined) {
521
+ var actualWidth = textMetrics.actualBoundingBoxLeft + textMetrics.actualBoundingBoxRight;
522
+ if (actualWidth > 0) {
523
+ textWidth = Math.max(textWidth, actualWidth);
524
+ }
525
+ }
526
+ var textHeight = fontSize * _this.singleLineHeight * _this.textStyle.fontScale;
506
527
  if (textHeight > charInfo.lineHeight) {
507
528
  height += textHeight - charInfo.lineHeight;
508
529
  charInfo.lineHeight = textHeight;
509
- charInfo.offsetY = fontSize * _this.textStyle.fontScale * (_this.singleLineHeight + (_this.textLayout.lineGap || 0) - 1) / 2;
530
+ charInfo.offsetY = fontSize * _this.textStyle.fontScale * (_this.singleLineHeight - 1) / 2;
510
531
  }
511
532
  charInfo.offsetX.push(charInfo.width);
512
- //逐字计算宽度以实现字符间距
533
+ // 计算字段宽度*富文本字体大小*缩放因子*整体文本大小+每个字符的间距(每个字符间距存疑,因为实际测量的宽度已经包含了间距)
534
+ charInfo.width += (textWidth <= 0 ? 0 : textWidth) * fontSize * _this.SCALE_FACTOR * _this.textStyle.fontScale + text.length * letterSpace;
535
+ // 将富文本数据存入 charInfo
536
+ charInfo.richOptions.push(options);
537
+ });
538
+ // 存储最后一行的字符信息,并且更新最终的宽度和高度用于确定 canvas 尺寸
539
+ charsInfo.push(charInfo);
540
+ width = Math.max(width, charInfo.width);
541
+ height += charInfo.lineHeight;
542
+ if (width === 0 || height === 0) {
543
+ this.isDirty = false;
544
+ context.restore();
545
+ return;
546
+ }
547
+ if (this.size === undefined || this.size === null) {
548
+ this.size = this.item.transform.size.clone();
549
+ }
550
+ var _this_size = this.size, _this_size_x = _this_size.x, x = _this_size_x === void 0 ? 1 : _this_size_x, _this_size_y = _this_size.y, y = _this_size_y === void 0 ? 1 : _this_size_y;
551
+ // 首次渲染时初始化 canvas 尺寸和组件变换
552
+ if (!this.initialized) {
553
+ this.canvasSize = !this.canvasSize ? new math.Vector2(width, height) : this.canvasSize;
554
+ var _this_canvasSize = this.canvasSize, canvasWidth = _this_canvasSize.x, canvasHeight = _this_canvasSize.y;
555
+ this.item.transform.size.set(x * canvasWidth * this.SCALE_FACTOR * this.SCALE_FACTOR, y * canvasHeight * this.SCALE_FACTOR * this.SCALE_FACTOR);
556
+ this.size = this.item.transform.size.clone();
557
+ this.initialized = true;
558
+ }
559
+ assertExist(this.canvasSize);
560
+ var _this_canvasSize1 = this.canvasSize, canvasWidth1 = _this_canvasSize1.x, canvasHeight1 = _this_canvasSize1.y;
561
+ this.textLayout.width = canvasWidth1 / textStyle.fontScale;
562
+ this.textLayout.height = canvasHeight1 / textStyle.fontScale;
563
+ this.canvas.width = canvasWidth1;
564
+ this.canvas.height = canvasHeight1;
565
+ context.clearRect(0, 0, canvasWidth1, canvasHeight1);
566
+ // fix bug 1/255
567
+ context.fillStyle = "rgba(255, 255, 255, " + this.ALPHA_FIX_VALUE + ")";
568
+ if (!flipY) {
569
+ context.translate(0, canvasHeight1);
570
+ context.scale(1, -1);
571
+ }
572
+ if (charsInfo.length === 0) {
573
+ context.restore();
574
+ return;
575
+ }
576
+ var charsLineHeight = textLayout.getOffsetY(textStyle, charsInfo.length, fontHeight * this.singleLineHeight, textStyle.fontSize);
577
+ charsInfo.forEach(function(charInfo, index) {
578
+ var richOptions = charInfo.richOptions, offsetX = charInfo.offsetX, width = charInfo.width;
579
+ var charWidth = width;
580
+ var offset = offsetX;
581
+ if (overflow === spec.TextOverflow.display) {
582
+ if (width > canvasWidth1) {
583
+ var canvasScale = canvasWidth1 / width;
584
+ charWidth *= canvasScale;
585
+ offset = offsetX.map(function(x) {
586
+ return x * canvasScale;
587
+ });
588
+ }
589
+ }
590
+ var x = _this.textLayout.getOffsetX(textStyle, charWidth);
591
+ if (index > 0) {
592
+ charsLineHeight += charInfo.lineHeight - charInfo.offsetY;
593
+ }
594
+ richOptions.forEach(function(options, index) {
595
+ var fontScale = textStyle.fontScale, textColor = textStyle.textColor, textFamily = textStyle.fontFamily, textWeight = textStyle.textWeight, richStyle = textStyle.fontStyle;
596
+ var text = options.text, fontSize = options.fontSize, _options_fontColor = options.fontColor, fontColor = _options_fontColor === void 0 ? textColor : _options_fontColor, _options_fontFamily = options.fontFamily, fontFamily = _options_fontFamily === void 0 ? textFamily : _options_fontFamily, _options_fontWeight = options.fontWeight, fontWeight = _options_fontWeight === void 0 ? textWeight : _options_fontWeight, _options_fontStyle = options.fontStyle, fontStyle = _options_fontStyle === void 0 ? richStyle : _options_fontStyle;
597
+ var textSize = fontSize;
598
+ if (overflow === spec.TextOverflow.display) {
599
+ if (width > canvasWidth1) {
600
+ textSize /= width / canvasWidth1;
601
+ }
602
+ }
603
+ var strOffsetX = offset[index] + x;
604
+ context.font = fontStyle + " " + fontWeight + " " + textSize * fontScale + "px " + fontFamily;
605
+ context.fillStyle = "rgba(" + fontColor[0] + ", " + fontColor[1] + ", " + fontColor[2] + ", " + fontColor[3] + ")";
606
+ context.fillText(text, strOffsetX, charsLineHeight);
607
+ });
608
+ });
609
+ // 与 toDataURL() 两种方式都需要像素读取操作
610
+ var imageData = context.getImageData(0, 0, this.canvas.width, this.canvas.height);
611
+ var texture = Texture.createWithData(this.engine, {
612
+ data: new Uint8Array(imageData.data),
613
+ width: imageData.width,
614
+ height: imageData.height
615
+ }, {
616
+ flipY: flipY,
617
+ magFilter: glContext.LINEAR,
618
+ minFilter: glContext.LINEAR,
619
+ wrapS: glContext.CLAMP_TO_EDGE,
620
+ wrapT: glContext.CLAMP_TO_EDGE
621
+ });
622
+ this.disposeTextTexture();
623
+ this.renderer.texture = texture;
624
+ this.material.setTexture("_MainTex", texture);
625
+ this.isDirty = false;
626
+ context.restore();
627
+ };
628
+ _proto.updateTextureModern = function updateTextureModern(flipY) {
629
+ var _this = this;
630
+ var _Math;
631
+ var _firstLine_richOptions;
632
+ // 解析富文本
633
+ this.generateTextProgram(this.text);
634
+ var _this1 = this, textLayout = _this1.textLayout, textStyle = _this1.textStyle;
635
+ var overflow = textLayout.overflow, _textLayout_letterSpace = textLayout.letterSpace, letterSpace = _textLayout_letterSpace === void 0 ? 0 : _textLayout_letterSpace;
636
+ var context = this.context;
637
+ var width = 0;
638
+ var height = 0;
639
+ if (!context) {
640
+ return;
641
+ }
642
+ context.save();
643
+ var charsInfo = [];
644
+ var fontHeight = textStyle.fontSize * this.textStyle.fontScale;
645
+ var charInfo = {
646
+ richOptions: [],
647
+ offsetX: [],
648
+ width: 0,
649
+ // 包括字体和上下行间距的高度
650
+ lineHeight: fontHeight * this.singleLineHeight + (this.textLayout.lineGap || 0) * this.textStyle.fontScale,
651
+ // 字体偏移高度(也就是行间距)
652
+ offsetY: (this.textLayout.lineGap || 0) * this.textStyle.fontScale / 2,
653
+ chars: []
654
+ };
655
+ // 遍历解析后的文本选项
656
+ this.processedTextOptions.forEach(function(options) {
657
+ var text = options.text, isNewLine = options.isNewLine, fontSize = options.fontSize;
658
+ // 如果是新行,则结束上一行并开始新行
659
+ if (isNewLine) {
660
+ // 结束上一行:累加行高并重置charInfo
661
+ height += charInfo.lineHeight;
662
+ charsInfo.push(charInfo);
663
+ width = Math.max(width, charInfo.width);
664
+ // 初始化新行
665
+ charInfo = {
666
+ richOptions: [],
667
+ offsetX: [],
668
+ width: 0,
669
+ lineHeight: fontHeight * _this.singleLineHeight + (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale,
670
+ offsetY: (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale / 2,
671
+ chars: []
672
+ };
673
+ }
674
+ // 恢复默认设置
675
+ context.font = (options.fontWeight || textStyle.textWeight) + " 10px " + (options.fontFamily || textStyle.fontFamily);
676
+ var textHeight = fontSize * _this.singleLineHeight * _this.textStyle.fontScale + (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale;
677
+ // 更新当前行的最大行高
678
+ if (textHeight > charInfo.lineHeight) {
679
+ charInfo.lineHeight = textHeight;
680
+ charInfo.offsetY = (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale / 2;
681
+ }
682
+ charInfo.offsetX.push(charInfo.width);
683
+ // 逐字计算宽度以实现字符间距
513
684
  var segmentInnerX = 0;
514
685
  var charArr = [];
515
686
  for(var i = 0; i < text.length; i++){
@@ -523,23 +694,24 @@ var RichTextComponent = /*#__PURE__*/ function(TextComponent) {
523
694
  });
524
695
  segmentInnerX += charWidth + letterSpace;
525
696
  }
526
- charInfo.chars.push(charArr); // 每个片段一个字符数组
697
+ charInfo.chars.push(charArr);
527
698
  charInfo.width += segmentInnerX;
528
699
  charInfo.richOptions.push(options);
529
700
  });
530
- // 存储最后一行的字符信息,并且更新最终的宽度和高度用于确定canvas尺寸
701
+ // 结束最后一行
702
+ height += charInfo.lineHeight;
531
703
  charsInfo.push(charInfo);
532
704
  width = Math.max(width, charInfo.width);
533
- height += charInfo.lineHeight;
534
705
  if (width === 0 || height === 0) {
535
706
  this.isDirty = false;
707
+ context.restore();
536
708
  return;
537
709
  }
538
710
  if (this.size === undefined || this.size === null) {
539
711
  this.size = this.item.transform.size.clone();
540
712
  }
541
713
  var _this_size = this.size, _this_size_x = _this_size.x, x = _this_size_x === void 0 ? 1 : _this_size_x, _this_size_y = _this_size.y, y = _this_size_y === void 0 ? 1 : _this_size_y;
542
- // 首次渲染时初始化canvas尺寸和组件变换
714
+ // 首次渲染时初始化 canvas 尺寸和组件变换
543
715
  if (!this.initialized) {
544
716
  this.canvasSize = !this.canvasSize ? new math.Vector2(width, height) : this.canvasSize;
545
717
  var _this_canvasSize = this.canvasSize, canvasWidth = _this_canvasSize.x, canvasHeight = _this_canvasSize.y;
@@ -561,14 +733,29 @@ var RichTextComponent = /*#__PURE__*/ function(TextComponent) {
561
733
  context.scale(1, -1);
562
734
  }
563
735
  if (charsInfo.length === 0) {
736
+ context.restore();
564
737
  return;
565
738
  }
566
- var charsLineHeight = textLayout.getOffsetY(textStyle, charsInfo.length, fontHeight * (this.singleLineHeight + (this.textLayout.lineGap || 0)), textStyle.fontSize);
739
+ // 行高数组
740
+ var lineHeights = charsInfo.map(function(l) {
741
+ return l.lineHeight;
742
+ });
743
+ // 计算第一行基线Y坐标
744
+ var firstLine = charsInfo[0];
745
+ var _firstLine_richOptions_map;
746
+ var firstLineMaxFontSize = (_Math = Math).max.apply(_Math, [].concat((_firstLine_richOptions_map = firstLine == null ? void 0 : (_firstLine_richOptions = firstLine.richOptions) == null ? void 0 : _firstLine_richOptions.map(function(opt) {
747
+ return opt.fontSize;
748
+ })) != null ? _firstLine_richOptions_map : [
749
+ this.textStyle.fontSize
750
+ ]));
751
+ var fontSizeForOffset = firstLineMaxFontSize * this.textStyle.fontScale * this.singleLineHeight;
752
+ var baselineY = textLayout.getOffsetYRich(this.textStyle, lineHeights, fontSizeForOffset);
753
+ // 逐行绘制
567
754
  charsInfo.forEach(function(charInfo, index) {
568
755
  var richOptions = charInfo.richOptions, offsetX = charInfo.offsetX, width = charInfo.width, chars = charInfo.chars;
756
+ var charsArr = chars;
569
757
  var charWidth = width;
570
758
  var offset = offsetX;
571
- var charsArr = chars;
572
759
  if (overflow === spec.TextOverflow.display) {
573
760
  if (width > canvasWidth1) {
574
761
  var canvasScale = canvasWidth1 / width;
@@ -585,29 +772,27 @@ var RichTextComponent = /*#__PURE__*/ function(TextComponent) {
585
772
  }
586
773
  }
587
774
  var x = _this.textLayout.getOffsetX(textStyle, charWidth);
588
- if (index > 0) {
589
- charsLineHeight += charsInfo[index - 1].lineHeight;
590
- }
591
- richOptions.forEach(function(options, index) {
775
+ richOptions.forEach(function(options, segIndex) {
592
776
  var fontScale = textStyle.fontScale, textColor = textStyle.textColor, textFamily = textStyle.fontFamily, textWeight = textStyle.textWeight, richStyle = textStyle.fontStyle;
593
777
  var fontSize = options.fontSize, _options_fontColor = options.fontColor, fontColor = _options_fontColor === void 0 ? textColor : _options_fontColor, _options_fontFamily = options.fontFamily, fontFamily = _options_fontFamily === void 0 ? textFamily : _options_fontFamily, _options_fontWeight = options.fontWeight, fontWeight = _options_fontWeight === void 0 ? textWeight : _options_fontWeight, _options_fontStyle = options.fontStyle, fontStyle = _options_fontStyle === void 0 ? richStyle : _options_fontStyle;
594
778
  var textSize = fontSize;
595
- if (overflow === spec.TextOverflow.display) {
596
- if (width > canvasWidth1) {
597
- textSize /= width / canvasWidth1;
598
- }
779
+ if (overflow === spec.TextOverflow.display && width > canvasWidth1) {
780
+ textSize /= width / canvasWidth1;
599
781
  }
600
- var strOffsetX = offset[index] + x;
782
+ var strOffsetX = offset[segIndex] + x;
601
783
  context.font = fontStyle + " " + fontWeight + " " + textSize * fontScale + "px " + fontFamily;
602
784
  context.fillStyle = "rgba(" + fontColor[0] + ", " + fontColor[1] + ", " + fontColor[2] + ", " + fontColor[3] + ")";
603
- // 遍历当前行的 chars 逐字绘制
604
- var charArr = charInfo.chars[index]; // 只取当前片段的字符数组
785
+ // 逐字绘制
786
+ var charArr = charInfo.chars[segIndex];
605
787
  charArr.forEach(function(charDetail) {
606
- context.fillText(charDetail.char, strOffsetX + charDetail.x, charsLineHeight);
788
+ context.fillText(charDetail.char, strOffsetX + charDetail.x, baselineY);
607
789
  });
608
790
  });
791
+ // 推进到下一行
792
+ if (index < charsInfo.length - 1) {
793
+ baselineY += lineHeights[index + 1];
794
+ }
609
795
  });
610
- // 与 toDataURL() 两种方式都需要像素读取操作
611
796
  var imageData = context.getImageData(0, 0, this.canvas.width, this.canvas.height);
612
797
  var texture = Texture.createWithData(this.engine, {
613
798
  data: new Uint8Array(imageData.data),
@@ -684,7 +869,7 @@ RichTextComponent = __decorate([
684
869
 
685
870
  /**
686
871
  * 插件版本号
687
- */ var version = "2.7.0-alpha.2";
872
+ */ var version = "2.7.0";
688
873
  registerPlugin("rich-text", RichTextLoader, VFXItem);
689
874
  logger.info("Plugin rich text version: " + version + ".");
690
875
  if (version !== EFFECTS.version) {