@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.js 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
  'use strict';
@@ -433,7 +433,7 @@ exports.RichTextComponent = /*#__PURE__*/ function(TextComponent) {
433
433
  _this = TextComponent.call(this, engine) || this;
434
434
  _this.processedTextOptions = [];
435
435
  // 字体高度的倍数(字体高度上下多出来的部分就是行间距)
436
- _this.singleLineHeight = 1.0;
436
+ _this.singleLineHeight = 1.571;
437
437
  _this.size = null;
438
438
  /**
439
439
  * 获取第一次渲染的 size
@@ -481,17 +481,31 @@ exports.RichTextComponent = /*#__PURE__*/ function(TextComponent) {
481
481
  program(text);
482
482
  };
483
483
  _proto.updateTexture = function updateTexture(flipY) {
484
- var _this = this;
485
484
  if (flipY === void 0) flipY = true;
486
485
  if (!this.isDirty || !this.context || !this.canvas) {
487
486
  return;
488
487
  }
488
+ // 根据 useLegacyRichText 字段来判断使用哪种渲染模式
489
+ var useLegacy = this.textLayout.useLegacyRichText === true;
490
+ this.singleLineHeight = useLegacy ? 1.571 : 1.0;
491
+ if (useLegacy) {
492
+ this.updateTextureLegacy(flipY);
493
+ } else {
494
+ this.updateTextureModern(flipY);
495
+ }
496
+ };
497
+ _proto.updateTextureLegacy = function updateTextureLegacy(flipY) {
498
+ var _this = this;
499
+ if (!this.isDirty || !this.context || !this.canvas) {
500
+ return;
501
+ }
489
502
  // 解析富文本
490
503
  this.generateTextProgram(this.text);
491
- var width = 0, height = 0;
492
504
  var _this1 = this, textLayout = _this1.textLayout, textStyle = _this1.textStyle;
493
505
  var overflow = textLayout.overflow, _textLayout_letterSpace = textLayout.letterSpace, letterSpace = _textLayout_letterSpace === void 0 ? 0 : _textLayout_letterSpace;
494
506
  var context = this.context;
507
+ var width = 0;
508
+ var height = 0;
495
509
  context.save();
496
510
  var charsInfo = [];
497
511
  var fontHeight = textStyle.fontSize * this.textStyle.fontScale;
@@ -500,15 +514,14 @@ exports.RichTextComponent = /*#__PURE__*/ function(TextComponent) {
500
514
  offsetX: [],
501
515
  width: 0,
502
516
  // 包括字体和上下行间距的高度
503
- lineHeight: fontHeight * (this.singleLineHeight + (this.textLayout.lineGap || 0)),
517
+ lineHeight: fontHeight * this.singleLineHeight,
504
518
  // 字体偏移高度(也就是行间距)
505
- offsetY: fontHeight * (this.singleLineHeight + (this.textLayout.lineGap || 0) - 1) / 2,
506
- chars: []
519
+ offsetY: fontHeight * (this.singleLineHeight - 1) / 2
507
520
  };
508
521
  // 遍历解析后的文本选项
509
522
  this.processedTextOptions.forEach(function(options) {
510
523
  var text = options.text, isNewLine = options.isNewLine, fontSize = options.fontSize;
511
- // 如果是新行,则将之前行的信息存入charsInfo并且初始化新行的charInfo
524
+ // 如果是新行,则将之前行的信息存入 charsInfo 并且初始化新行的 charInfo
512
525
  if (isNewLine) {
513
526
  charsInfo.push(charInfo);
514
527
  width = Math.max(width, charInfo.width);
@@ -516,23 +529,181 @@ exports.RichTextComponent = /*#__PURE__*/ function(TextComponent) {
516
529
  richOptions: [],
517
530
  offsetX: [],
518
531
  width: 0,
519
- lineHeight: fontHeight * (_this.singleLineHeight + (_this.textLayout.lineGap || 0)),
520
- offsetY: fontHeight * (_this.singleLineHeight + (_this.textLayout.lineGap || 0) - 1) / 2,
521
- chars: []
532
+ lineHeight: fontHeight * _this.singleLineHeight,
533
+ offsetY: fontHeight * (_this.singleLineHeight - 1) / 2
522
534
  };
523
- // 管理行的总高度调整canvas尺寸
535
+ // 管理行的总高度调整 canvas 尺寸
524
536
  height += charInfo.lineHeight;
525
537
  }
526
538
  // 恢复默认设置
527
539
  context.font = (options.fontWeight || textStyle.textWeight) + " 10px " + (options.fontFamily || textStyle.fontFamily);
528
- var textHeight = fontSize * (_this.singleLineHeight + (_this.textLayout.lineGap || 0)) * _this.textStyle.fontScale;
540
+ // 计算得到每个字段的宽度 textWidth
541
+ var textMetrics = context.measureText(text);
542
+ var textWidth = textMetrics.width;
543
+ if (textMetrics.actualBoundingBoxLeft !== undefined && textMetrics.actualBoundingBoxRight !== undefined) {
544
+ var actualWidth = textMetrics.actualBoundingBoxLeft + textMetrics.actualBoundingBoxRight;
545
+ if (actualWidth > 0) {
546
+ textWidth = Math.max(textWidth, actualWidth);
547
+ }
548
+ }
549
+ var textHeight = fontSize * _this.singleLineHeight * _this.textStyle.fontScale;
529
550
  if (textHeight > charInfo.lineHeight) {
530
551
  height += textHeight - charInfo.lineHeight;
531
552
  charInfo.lineHeight = textHeight;
532
- charInfo.offsetY = fontSize * _this.textStyle.fontScale * (_this.singleLineHeight + (_this.textLayout.lineGap || 0) - 1) / 2;
553
+ charInfo.offsetY = fontSize * _this.textStyle.fontScale * (_this.singleLineHeight - 1) / 2;
533
554
  }
534
555
  charInfo.offsetX.push(charInfo.width);
535
- //逐字计算宽度以实现字符间距
556
+ // 计算字段宽度*富文本字体大小*缩放因子*整体文本大小+每个字符的间距(每个字符间距存疑,因为实际测量的宽度已经包含了间距)
557
+ charInfo.width += (textWidth <= 0 ? 0 : textWidth) * fontSize * _this.SCALE_FACTOR * _this.textStyle.fontScale + text.length * letterSpace;
558
+ // 将富文本数据存入 charInfo
559
+ charInfo.richOptions.push(options);
560
+ });
561
+ // 存储最后一行的字符信息,并且更新最终的宽度和高度用于确定 canvas 尺寸
562
+ charsInfo.push(charInfo);
563
+ width = Math.max(width, charInfo.width);
564
+ height += charInfo.lineHeight;
565
+ if (width === 0 || height === 0) {
566
+ this.isDirty = false;
567
+ context.restore();
568
+ return;
569
+ }
570
+ if (this.size === undefined || this.size === null) {
571
+ this.size = this.item.transform.size.clone();
572
+ }
573
+ 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;
574
+ // 首次渲染时初始化 canvas 尺寸和组件变换
575
+ if (!this.initialized) {
576
+ this.canvasSize = !this.canvasSize ? new EFFECTS.math.Vector2(width, height) : this.canvasSize;
577
+ var _this_canvasSize = this.canvasSize, canvasWidth = _this_canvasSize.x, canvasHeight = _this_canvasSize.y;
578
+ this.item.transform.size.set(x * canvasWidth * this.SCALE_FACTOR * this.SCALE_FACTOR, y * canvasHeight * this.SCALE_FACTOR * this.SCALE_FACTOR);
579
+ this.size = this.item.transform.size.clone();
580
+ this.initialized = true;
581
+ }
582
+ EFFECTS.assertExist(this.canvasSize);
583
+ var _this_canvasSize1 = this.canvasSize, canvasWidth1 = _this_canvasSize1.x, canvasHeight1 = _this_canvasSize1.y;
584
+ this.textLayout.width = canvasWidth1 / textStyle.fontScale;
585
+ this.textLayout.height = canvasHeight1 / textStyle.fontScale;
586
+ this.canvas.width = canvasWidth1;
587
+ this.canvas.height = canvasHeight1;
588
+ context.clearRect(0, 0, canvasWidth1, canvasHeight1);
589
+ // fix bug 1/255
590
+ context.fillStyle = "rgba(255, 255, 255, " + this.ALPHA_FIX_VALUE + ")";
591
+ if (!flipY) {
592
+ context.translate(0, canvasHeight1);
593
+ context.scale(1, -1);
594
+ }
595
+ if (charsInfo.length === 0) {
596
+ context.restore();
597
+ return;
598
+ }
599
+ var charsLineHeight = textLayout.getOffsetY(textStyle, charsInfo.length, fontHeight * this.singleLineHeight, textStyle.fontSize);
600
+ charsInfo.forEach(function(charInfo, index) {
601
+ var richOptions = charInfo.richOptions, offsetX = charInfo.offsetX, width = charInfo.width;
602
+ var charWidth = width;
603
+ var offset = offsetX;
604
+ if (overflow === EFFECTS.spec.TextOverflow.display) {
605
+ if (width > canvasWidth1) {
606
+ var canvasScale = canvasWidth1 / width;
607
+ charWidth *= canvasScale;
608
+ offset = offsetX.map(function(x) {
609
+ return x * canvasScale;
610
+ });
611
+ }
612
+ }
613
+ var x = _this.textLayout.getOffsetX(textStyle, charWidth);
614
+ if (index > 0) {
615
+ charsLineHeight += charInfo.lineHeight - charInfo.offsetY;
616
+ }
617
+ richOptions.forEach(function(options, index) {
618
+ var fontScale = textStyle.fontScale, textColor = textStyle.textColor, textFamily = textStyle.fontFamily, textWeight = textStyle.textWeight, richStyle = textStyle.fontStyle;
619
+ 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;
620
+ var textSize = fontSize;
621
+ if (overflow === EFFECTS.spec.TextOverflow.display) {
622
+ if (width > canvasWidth1) {
623
+ textSize /= width / canvasWidth1;
624
+ }
625
+ }
626
+ var strOffsetX = offset[index] + x;
627
+ context.font = fontStyle + " " + fontWeight + " " + textSize * fontScale + "px " + fontFamily;
628
+ context.fillStyle = "rgba(" + fontColor[0] + ", " + fontColor[1] + ", " + fontColor[2] + ", " + fontColor[3] + ")";
629
+ context.fillText(text, strOffsetX, charsLineHeight);
630
+ });
631
+ });
632
+ // 与 toDataURL() 两种方式都需要像素读取操作
633
+ var imageData = context.getImageData(0, 0, this.canvas.width, this.canvas.height);
634
+ var texture = EFFECTS.Texture.createWithData(this.engine, {
635
+ data: new Uint8Array(imageData.data),
636
+ width: imageData.width,
637
+ height: imageData.height
638
+ }, {
639
+ flipY: flipY,
640
+ magFilter: EFFECTS.glContext.LINEAR,
641
+ minFilter: EFFECTS.glContext.LINEAR,
642
+ wrapS: EFFECTS.glContext.CLAMP_TO_EDGE,
643
+ wrapT: EFFECTS.glContext.CLAMP_TO_EDGE
644
+ });
645
+ this.disposeTextTexture();
646
+ this.renderer.texture = texture;
647
+ this.material.setTexture("_MainTex", texture);
648
+ this.isDirty = false;
649
+ context.restore();
650
+ };
651
+ _proto.updateTextureModern = function updateTextureModern(flipY) {
652
+ var _this = this;
653
+ var _Math;
654
+ var _firstLine_richOptions;
655
+ // 解析富文本
656
+ this.generateTextProgram(this.text);
657
+ var _this1 = this, textLayout = _this1.textLayout, textStyle = _this1.textStyle;
658
+ var overflow = textLayout.overflow, _textLayout_letterSpace = textLayout.letterSpace, letterSpace = _textLayout_letterSpace === void 0 ? 0 : _textLayout_letterSpace;
659
+ var context = this.context;
660
+ var width = 0;
661
+ var height = 0;
662
+ if (!context) {
663
+ return;
664
+ }
665
+ context.save();
666
+ var charsInfo = [];
667
+ var fontHeight = textStyle.fontSize * this.textStyle.fontScale;
668
+ var charInfo = {
669
+ richOptions: [],
670
+ offsetX: [],
671
+ width: 0,
672
+ // 包括字体和上下行间距的高度
673
+ lineHeight: fontHeight * this.singleLineHeight + (this.textLayout.lineGap || 0) * this.textStyle.fontScale,
674
+ // 字体偏移高度(也就是行间距)
675
+ offsetY: (this.textLayout.lineGap || 0) * this.textStyle.fontScale / 2,
676
+ chars: []
677
+ };
678
+ // 遍历解析后的文本选项
679
+ this.processedTextOptions.forEach(function(options) {
680
+ var text = options.text, isNewLine = options.isNewLine, fontSize = options.fontSize;
681
+ // 如果是新行,则结束上一行并开始新行
682
+ if (isNewLine) {
683
+ // 结束上一行:累加行高并重置charInfo
684
+ height += charInfo.lineHeight;
685
+ charsInfo.push(charInfo);
686
+ width = Math.max(width, charInfo.width);
687
+ // 初始化新行
688
+ charInfo = {
689
+ richOptions: [],
690
+ offsetX: [],
691
+ width: 0,
692
+ lineHeight: fontHeight * _this.singleLineHeight + (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale,
693
+ offsetY: (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale / 2,
694
+ chars: []
695
+ };
696
+ }
697
+ // 恢复默认设置
698
+ context.font = (options.fontWeight || textStyle.textWeight) + " 10px " + (options.fontFamily || textStyle.fontFamily);
699
+ var textHeight = fontSize * _this.singleLineHeight * _this.textStyle.fontScale + (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale;
700
+ // 更新当前行的最大行高
701
+ if (textHeight > charInfo.lineHeight) {
702
+ charInfo.lineHeight = textHeight;
703
+ charInfo.offsetY = (_this.textLayout.lineGap || 0) * _this.textStyle.fontScale / 2;
704
+ }
705
+ charInfo.offsetX.push(charInfo.width);
706
+ // 逐字计算宽度以实现字符间距
536
707
  var segmentInnerX = 0;
537
708
  var charArr = [];
538
709
  for(var i = 0; i < text.length; i++){
@@ -546,23 +717,24 @@ exports.RichTextComponent = /*#__PURE__*/ function(TextComponent) {
546
717
  });
547
718
  segmentInnerX += charWidth + letterSpace;
548
719
  }
549
- charInfo.chars.push(charArr); // 每个片段一个字符数组
720
+ charInfo.chars.push(charArr);
550
721
  charInfo.width += segmentInnerX;
551
722
  charInfo.richOptions.push(options);
552
723
  });
553
- // 存储最后一行的字符信息,并且更新最终的宽度和高度用于确定canvas尺寸
724
+ // 结束最后一行
725
+ height += charInfo.lineHeight;
554
726
  charsInfo.push(charInfo);
555
727
  width = Math.max(width, charInfo.width);
556
- height += charInfo.lineHeight;
557
728
  if (width === 0 || height === 0) {
558
729
  this.isDirty = false;
730
+ context.restore();
559
731
  return;
560
732
  }
561
733
  if (this.size === undefined || this.size === null) {
562
734
  this.size = this.item.transform.size.clone();
563
735
  }
564
736
  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;
565
- // 首次渲染时初始化canvas尺寸和组件变换
737
+ // 首次渲染时初始化 canvas 尺寸和组件变换
566
738
  if (!this.initialized) {
567
739
  this.canvasSize = !this.canvasSize ? new EFFECTS.math.Vector2(width, height) : this.canvasSize;
568
740
  var _this_canvasSize = this.canvasSize, canvasWidth = _this_canvasSize.x, canvasHeight = _this_canvasSize.y;
@@ -584,14 +756,29 @@ exports.RichTextComponent = /*#__PURE__*/ function(TextComponent) {
584
756
  context.scale(1, -1);
585
757
  }
586
758
  if (charsInfo.length === 0) {
759
+ context.restore();
587
760
  return;
588
761
  }
589
- var charsLineHeight = textLayout.getOffsetY(textStyle, charsInfo.length, fontHeight * (this.singleLineHeight + (this.textLayout.lineGap || 0)), textStyle.fontSize);
762
+ // 行高数组
763
+ var lineHeights = charsInfo.map(function(l) {
764
+ return l.lineHeight;
765
+ });
766
+ // 计算第一行基线Y坐标
767
+ var firstLine = charsInfo[0];
768
+ var _firstLine_richOptions_map;
769
+ 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) {
770
+ return opt.fontSize;
771
+ })) != null ? _firstLine_richOptions_map : [
772
+ this.textStyle.fontSize
773
+ ]));
774
+ var fontSizeForOffset = firstLineMaxFontSize * this.textStyle.fontScale * this.singleLineHeight;
775
+ var baselineY = textLayout.getOffsetYRich(this.textStyle, lineHeights, fontSizeForOffset);
776
+ // 逐行绘制
590
777
  charsInfo.forEach(function(charInfo, index) {
591
778
  var richOptions = charInfo.richOptions, offsetX = charInfo.offsetX, width = charInfo.width, chars = charInfo.chars;
779
+ var charsArr = chars;
592
780
  var charWidth = width;
593
781
  var offset = offsetX;
594
- var charsArr = chars;
595
782
  if (overflow === EFFECTS.spec.TextOverflow.display) {
596
783
  if (width > canvasWidth1) {
597
784
  var canvasScale = canvasWidth1 / width;
@@ -608,29 +795,27 @@ exports.RichTextComponent = /*#__PURE__*/ function(TextComponent) {
608
795
  }
609
796
  }
610
797
  var x = _this.textLayout.getOffsetX(textStyle, charWidth);
611
- if (index > 0) {
612
- charsLineHeight += charsInfo[index - 1].lineHeight;
613
- }
614
- richOptions.forEach(function(options, index) {
798
+ richOptions.forEach(function(options, segIndex) {
615
799
  var fontScale = textStyle.fontScale, textColor = textStyle.textColor, textFamily = textStyle.fontFamily, textWeight = textStyle.textWeight, richStyle = textStyle.fontStyle;
616
800
  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;
617
801
  var textSize = fontSize;
618
- if (overflow === EFFECTS.spec.TextOverflow.display) {
619
- if (width > canvasWidth1) {
620
- textSize /= width / canvasWidth1;
621
- }
802
+ if (overflow === EFFECTS.spec.TextOverflow.display && width > canvasWidth1) {
803
+ textSize /= width / canvasWidth1;
622
804
  }
623
- var strOffsetX = offset[index] + x;
805
+ var strOffsetX = offset[segIndex] + x;
624
806
  context.font = fontStyle + " " + fontWeight + " " + textSize * fontScale + "px " + fontFamily;
625
807
  context.fillStyle = "rgba(" + fontColor[0] + ", " + fontColor[1] + ", " + fontColor[2] + ", " + fontColor[3] + ")";
626
- // 遍历当前行的 chars 逐字绘制
627
- var charArr = charInfo.chars[index]; // 只取当前片段的字符数组
808
+ // 逐字绘制
809
+ var charArr = charInfo.chars[segIndex];
628
810
  charArr.forEach(function(charDetail) {
629
- context.fillText(charDetail.char, strOffsetX + charDetail.x, charsLineHeight);
811
+ context.fillText(charDetail.char, strOffsetX + charDetail.x, baselineY);
630
812
  });
631
813
  });
814
+ // 推进到下一行
815
+ if (index < charsInfo.length - 1) {
816
+ baselineY += lineHeights[index + 1];
817
+ }
632
818
  });
633
- // 与 toDataURL() 两种方式都需要像素读取操作
634
819
  var imageData = context.getImageData(0, 0, this.canvas.width, this.canvas.height);
635
820
  var texture = EFFECTS.Texture.createWithData(this.engine, {
636
821
  data: new Uint8Array(imageData.data),
@@ -707,7 +892,7 @@ exports.RichTextComponent = __decorate([
707
892
 
708
893
  /**
709
894
  * 插件版本号
710
- */ var version = "2.7.0-alpha.2";
895
+ */ var version = "2.7.0";
711
896
  EFFECTS.registerPlugin("rich-text", RichTextLoader, EFFECTS.VFXItem);
712
897
  EFFECTS.logger.info("Plugin rich text version: " + version + ".");
713
898
  if (version !== EFFECTS__namespace.version) {