@tarojs/plugin-platform-harmony-ets 4.0.0-beta.31 → 4.0.0-beta.33

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.
@@ -5,6 +5,15 @@ import { CSSProperties } from 'react'
5
5
  import { TaroElement } from '../element/element'
6
6
  import { BORDER_STYLE_MAP, capitalizeFirstLetter, FlexManager, getNodeMarginOrPaddingData, getUnit } from './util'
7
7
 
8
+ // 背景解析正则
9
+ const BACKGROUND_REGEX = {
10
+ IMAGE: /url\((['"])?(.*?)\1\)|(linear|radial)-gradient\([^)]*\)/,
11
+ COLOR: /(#[0-9a-fA-F]{3,6}|rgb\(\d+,\s*\d+,\s*\d+\)|rgba?\(\d+,\s*\d+,\s*\d+,\s*(?:0?\.\d+|\d+%)\)|transparent)/,
12
+ REPEAT: /(repeat-x|repeat-y|repeat|space|round|no-repeat)/,
13
+ POSITION: /(top|left|center|right|bottom|\d+(\.\d+)?(px|%|vw|vh)?)+/g,
14
+ SIZE: /(cover|contain|\d+(\.\d+)?(px|%|vw|vh)?)+/g
15
+ }
16
+
8
17
  // Note: 将 web 端的 style 转换为 hm 端的 style
9
18
  export default function convertWebStyle2HmStyle(webStyle: CSSProperties, node?: TaroElement) {
10
19
  const hmStyle: Record<string, any> = node?._st?.hmStyle || {}
@@ -155,7 +164,12 @@ export default function convertWebStyle2HmStyle(webStyle: CSSProperties, node?:
155
164
  break
156
165
  }
157
166
  case 'background': {
158
- // TODO: 暂未实现
167
+ const bg = setBackground(value)
168
+ if (bg['background-color']) { hmStyle.backgroundColor = bg['background-color'] }
169
+ bg['background-image'] && setBackgroundImage(hmStyle, bg['background-image'])
170
+ bg['background-repeat'] && setBackgroundRepeat(hmStyle, bg['background-repeat'])
171
+ bg['background-position'] && setBackgroundPosistion(hmStyle, bg['background-position'])
172
+ bg['background-size'] && setBackgroundSize(hmStyle, bg['background-size'])
159
173
  break
160
174
  }
161
175
  case 'backgroundColor': {
@@ -409,8 +423,11 @@ export default function convertWebStyle2HmStyle(webStyle: CSSProperties, node?:
409
423
  break
410
424
  }
411
425
  case 'transform': {
412
- // todo: 需要更新
413
- // hmStyle.transform = parseTransform(value)
426
+ hmStyle.transform = parseTransform(value)
427
+ break
428
+ }
429
+ case 'transformOrigin': {
430
+ hmStyle.transformOrigin = parseTransformOrigin(value)
414
431
  break
415
432
  }
416
433
  case 'position': {
@@ -456,6 +473,61 @@ function setBackgroundImage(hmStyle, value) {
456
473
  // todo 渐变需要处理
457
474
  }
458
475
 
476
+ // 解析background属性
477
+ function setBackground (backgroundValue: string) {
478
+ const result = {
479
+ 'background-color': '',
480
+ 'background-image': '',
481
+ 'background-repeat': '',
482
+ 'background-position': '',
483
+ 'background-size': ''
484
+ }
485
+
486
+ if (!backgroundValue) return result
487
+
488
+ // 匹配background-image
489
+ const imageMatch = backgroundValue.match(BACKGROUND_REGEX.IMAGE)
490
+ if (imageMatch) {
491
+ result['background-image'] = imageMatch[0]
492
+ backgroundValue = backgroundValue.replace(imageMatch[0], '').trim()
493
+ }
494
+
495
+ // 匹配background-color
496
+ const colorMatch = backgroundValue.match(BACKGROUND_REGEX.COLOR)
497
+ if (colorMatch) {
498
+ result['background-color'] = colorMatch[0]
499
+ backgroundValue = backgroundValue.replace(colorMatch[0], '').trim()
500
+ }
501
+
502
+ // 匹配background-repeat
503
+ const repeatMatch = backgroundValue.match(BACKGROUND_REGEX.REPEAT)
504
+ if (repeatMatch) {
505
+ result['background-repeat'] = repeatMatch[0]
506
+ backgroundValue = backgroundValue.replace(repeatMatch[0], '').trim()
507
+ }
508
+
509
+ // 匹配background-position,background-size
510
+ // 先分割 / 分割出background-position\background-size
511
+ const positionSize = backgroundValue.split('/')
512
+ const [position, size] = positionSize
513
+ // 匹配background-position
514
+ if (position) {
515
+ const positionMatch = position.match(BACKGROUND_REGEX.POSITION)
516
+ if (positionMatch) {
517
+ result['background-position'] = positionMatch.join(' ')
518
+ }
519
+ }
520
+ if (size) {
521
+ // 匹配background-size
522
+ const sizeMatch = size.match(BACKGROUND_REGEX.SIZE)
523
+ if (sizeMatch) {
524
+ result['background-size'] = sizeMatch.join(' ')
525
+ }
526
+ }
527
+
528
+ return result
529
+ }
530
+
459
531
  function setBackgroundRepeat(hmStyle, value) {
460
532
  if (typeof value === 'string') {
461
533
  switch (value) {
@@ -469,6 +541,13 @@ function setBackgroundRepeat(hmStyle, value) {
469
541
 
470
542
  function setBackgroundSize(hmStyle, value) {
471
543
  if (typeof value === 'string') {
544
+ if (value === 'cover') {
545
+ hmStyle.backgroundSize = ImageSize.Cover
546
+ return
547
+ } else if (value === 'contain') {
548
+ hmStyle.backgroundSize = ImageSize.Contain
549
+ return
550
+ }
472
551
  const sizes = value.split(' ')
473
552
  if (sizes.length === 1) {
474
553
  hmStyle.backgroundSize = { width: getUnit(sizes[0]) }
@@ -482,7 +561,7 @@ function setBackgroundPosistion (hmStyle, value) {
482
561
  if (typeof value === 'string') {
483
562
  const positions = value.split(' ')
484
563
  const horizontal = positions[0].toLowerCase()
485
- const vertical = positions[1].toLowerCase() || 'top'
564
+ const vertical = positions[1]?.toLowerCase() || 'top'
486
565
 
487
566
  if (horizontal === 'left' && vertical === 'top') {
488
567
  hmStyle.backgroundPosition = Alignment.TopStart
@@ -526,12 +605,12 @@ function setFontWeight (hmStyle, value) {
526
605
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
527
606
  function parseTransform(transformString) {
528
607
  const transformRegex = /(\w+)\(([^)]+)\)/g
529
- const transforms = []
608
+ const transform = {}
530
609
 
531
610
  let matchs
532
611
  while ((matchs = transformRegex.exec(transformString)) !== null) {
533
612
  const [, type, valueString] = matchs
534
- const values = valueString.split(/\s*,\s*/).map(parseFloat)
613
+ const values = valueString.split(/\s*,\s*/)
535
614
 
536
615
  const transformObj = {
537
616
  type: capitalizeFirstLetter(type),
@@ -541,62 +620,101 @@ function parseTransform(transformString) {
541
620
  switch (type) {
542
621
  case 'translate':
543
622
  case 'translate3d':
544
- transformObj.value.x = parseFloat(getUnit(values[0])) || 0
545
- transformObj.value.y = parseFloat(getUnit(values[1])) || 0
546
- transformObj.value.z = parseFloat(getUnit(values[2])) || 0
623
+ transformObj.value.x = (getUnit(values[0])) || 0
624
+ transformObj.value.y = (getUnit(values[1])) || 0
625
+ transformObj.value.z = (getUnit(values[2])) || 0
547
626
  break
548
627
  case 'translateX':
549
- transformObj.value.x = parseFloat(getUnit(values[0])) || 0
628
+ transformObj.value.x = (getUnit(values[0])) || 0
550
629
  break
551
630
  case 'translateY':
552
- transformObj.value.y = parseFloat(getUnit(values[0])) || 0
631
+ transformObj.value.y = (getUnit(values[0])) || 0
553
632
  break
554
633
  case 'translateZ':
555
- transformObj.value.z = parseFloat(getUnit(values[0])) || 0
634
+ transformObj.value.z = (getUnit(values[0])) || 0
556
635
  break
557
636
  case 'rotate':
558
- transformObj.value.angle = parseFloat(getUnit(values[0])) || 0
637
+ case 'rotateZ':
638
+ transformObj.value.angle = (getUnit(values[0])) || 0
559
639
  transformObj.value.x = 0
560
640
  transformObj.value.y = 0
561
641
  transformObj.value.z = 1
562
642
  break
563
643
  case 'rotate3d':
564
- transformObj.value.angle = parseFloat(getUnit(values[0])) || 0
644
+ transformObj.value.angle = getUnit(values[0]) || 0
565
645
  transformObj.value.x = values[1] || 0
566
646
  transformObj.value.y = values[2] || 0
567
647
  transformObj.value.z = values[3] || 0
568
648
  break
569
649
  case 'rotateX':
570
- transformObj.value.angle = parseFloat(getUnit(values[0])) || 0
650
+ transformObj.value.angle = getUnit(values[0]) || 0
571
651
  transformObj.value.x = 1
572
652
  transformObj.value.y = 0
573
653
  transformObj.value.z = 0
574
654
  break
575
655
  case 'rotateY':
576
- transformObj.value.angle = parseFloat(getUnit(values[0])) || 0
656
+ transformObj.value.angle = getUnit(values[0]) || 0
577
657
  transformObj.value.x = 0
578
658
  transformObj.value.y = 1
579
659
  transformObj.value.z = 0
580
660
  break
581
661
  case 'scale':
582
662
  case 'scale3d':
583
- transformObj.value.x = values[0] || 1
584
- transformObj.value.y = values[1] || values[0] || 1
585
- transformObj.value.z = values[2] || 1
663
+ transformObj.value.x = parseFloat(values[0]) || 1
664
+ transformObj.value.y = parseFloat(values[1] || values[0]) || 1
665
+ transformObj.value.z = parseFloat(values[2]) || 1
586
666
  break
587
667
  case 'scaleX':
588
- transformObj.value.x = values[0] || 1
668
+ transformObj.value.x = parseFloat(values[0]) || 1
589
669
  break
590
670
  case 'scaleY':
591
- transformObj.value.y = values[0] || 1
671
+ transformObj.value.y = parseFloat(values[0]) || 1
592
672
  break
593
673
  default:
594
674
  // Handle unrecognized transform types or ignore them
595
675
  break
596
676
  }
597
677
 
598
- transforms.push(transformObj)
678
+ transform[transformObj.type] = transformObj.value
679
+ }
680
+
681
+ return transform
682
+ }
683
+
684
+ // 方向转百分比
685
+ function directionToPercent(direction: string) {
686
+ switch (direction) {
687
+ case 'top':
688
+ case 'left':
689
+ return '0%'
690
+ case 'center':
691
+ return '50%'
692
+ case 'bottom':
693
+ case 'right':
694
+ return '100%'
695
+ default:
696
+ return direction
599
697
  }
698
+ }
600
699
 
601
- return transforms
700
+ // 解析transform-orgin
701
+ function parseTransformOrigin (value: string) {
702
+ if (typeof value === 'string') {
703
+ const values = value.split(' ')
704
+ if (values.length === 1) {
705
+ return {
706
+ x: getUnit(directionToPercent(values[0])),
707
+ y: getUnit(directionToPercent(values[0]))
708
+ }
709
+ } else if (values.length === 2) {
710
+ return {
711
+ x: getUnit(directionToPercent(values[0])),
712
+ y: getUnit(directionToPercent(values[1]))
713
+ }
714
+ }
715
+ }
716
+ return {
717
+ x: 0,
718
+ y: 0
719
+ }
602
720
  }
@@ -60,6 +60,7 @@ export interface TaroStyleType {
60
60
 
61
61
  // 渐变
62
62
  linearGradient?: HarmonyType.LinearGradient
63
+ radialGradient?: HarmonyType.RadialGradient
63
64
 
64
65
  // transform
65
66
  rotate?: HarmonyType.Transform.Rotate
@@ -98,9 +99,6 @@ export interface TaroStyleType {
98
99
  fontFamily?: string | Resource
99
100
  textDecoration?: TextDecorationType
100
101
 
101
- // gradient
102
- linearGradient?: HarmonyType.LinearGradient
103
-
104
102
  // other
105
103
  opacity?: number | Resource
106
104
  zIndex?: number
@@ -130,6 +128,12 @@ export namespace HarmonyType {
130
128
  colors: Array<[ResourceColor, number]>
131
129
  repeating?: boolean
132
130
  }
131
+ export interface RadialGradient {
132
+ center: Point
133
+ radius: number | string
134
+ colors: Array<[ResourceColor, number]>
135
+ repeating?: boolean
136
+ }
133
137
  export interface Overflow {
134
138
  overflow: TextOverflow
135
139
  }
@@ -220,14 +220,14 @@ export function getUnit (val) {
220
220
  // 空的字符串代表 Reconciler remove 了这个 prop,不进行后面的逻辑了
221
221
  if (val === '') return val
222
222
 
223
- if (/\d+(vp)$/.test(val)) {
223
+ if (/\d+(vp|px)$/.test(val)) {
224
224
  return val
225
225
  } else if (isNumber(val)) {
226
- return convertNumber2VP(parseFloat(val))
226
+ return parseFloat(val) + 'px'
227
227
  }
228
228
  if (val) {
229
229
  // 匹配vw\vh
230
- const exec = val.match(/(-?\d*(\.\d+)?)(vw|vh|px)$/)
230
+ const exec = val.match(/(-?\d*(\.\d+)?)(vw|vh)$/)
231
231
  if (exec) {
232
232
  const [, num, , unit] = exec
233
233
  return convertNumber2VP(parseFloat(num), unit)
@@ -32,7 +32,7 @@ import dataPreferences from '@ohos.data.preferences';
32
32
  import hilog from '@ohos.hilog';
33
33
  import matrix4 from '@ohos.matrix4';
34
34
  import prompt from '@ohos.prompt';
35
- import { pxTransformHelper } from '@tarojs/taro';
35
+ import { pxTransformHelper as pxTransformHelper$1 } from '@tarojs/taro';
36
36
 
37
37
  class MethodHandler {
38
38
  constructor({ name, success, fail, complete }) {
@@ -3880,7 +3880,7 @@ const pageScrollTo = (options) => {
3880
3880
  scroller = getPageScrollerOrNode(scroller, page);
3881
3881
  const { yOffset } = scroller.currentOffset();
3882
3882
  if (areaInfo) {
3883
- scrollValue = areaInfo.globalPosition.y + yOffset + pxTransformHelper(offsetTop, 'px', true);
3883
+ scrollValue = areaInfo.globalPosition.y + yOffset + pxTransformHelper$1(offsetTop, 'px', true);
3884
3884
  }
3885
3885
  }
3886
3886
  const { xOffset } = scroller.currentOffset();
@@ -4870,19 +4870,60 @@ function initPxTransform({ designWidth = defaultDesignWidth, deviceRatio = defau
4870
4870
  }
4871
4871
  }
4872
4872
  const display = _display.getDefaultDisplaySync();
4873
- display.width;
4873
+ let displayWidth = display.width;
4874
+ let ratioCache = false;
4875
+ let designWidthFunc;
4876
+ let designWidth = defaultDesignWidth;
4877
+ let deviceRatio = defaultDesignRatio;
4878
+ function getRatio(value) {
4879
+ var _a;
4880
+ // Note: 提前调用 display 可能无法获取正确值
4881
+ if (ratioCache === false || displayWidth !== display.width) {
4882
+ const config = ((_a = Current.taro) === null || _a === void 0 ? void 0 : _a.config) || {};
4883
+ if (!isFunction(designWidthFunc)) {
4884
+ designWidthFunc = isFunction(config.designWidth)
4885
+ ? config.designWidth
4886
+ : () => config.designWidth;
4887
+ designWidth = designWidthFunc(value) || defaultDesignWidth;
4888
+ deviceRatio = config.deviceRatio || defaultDesignRatio;
4889
+ if (!(designWidth in deviceRatio)) {
4890
+ throw new Error(`deviceRatio 配置中不存在 ${designWidth} 的设置!`);
4891
+ }
4892
+ }
4893
+ displayWidth = display.width;
4894
+ ratioCache = Math.min(display.width, display.height) / designWidth / deviceRatio[designWidth];
4895
+ }
4896
+ return ratioCache;
4897
+ }
4898
+ // Note: 设置为 style 单位时会自动完成设计稿转换,设计开发者调用 API 时也许抹平差异,例如 pageScrollTo[option.offsetTop]
4899
+ function pxTransformHelper(size, unit, isNumber = false) {
4900
+ var _a;
4901
+ const config = ((_a = Current.taro) === null || _a === void 0 ? void 0 : _a.config) || {};
4902
+ const targetUnit = unit || config.targetUnit || defaultTargetUnit;
4903
+ if (targetUnit === 'PX') {
4904
+ return px2vp(size * display.scaledDensity) + 'vp';
4905
+ }
4906
+ const ratio = getRatio(size);
4907
+ let val = size * ratio;
4908
+ switch (targetUnit) {
4909
+ case 'vp':
4910
+ // Note: 在应用创建前调用无效
4911
+ val = px2vp(val);
4912
+ break;
4913
+ }
4914
+ return isNumber ? val : val + targetUnit;
4915
+ }
4874
4916
  function pxTransform(size) {
4875
4917
  var _a;
4876
4918
  const config = ((_a = Current.taro) === null || _a === void 0 ? void 0 : _a.config) || {};
4877
4919
  const targetUnit = config.targetUnit || defaultTargetUnit;
4878
- let val = size;
4920
+ const val = size;
4879
4921
  switch (targetUnit) {
4880
4922
  case 'vp':
4881
- val = px2vp(size);
4882
- break;
4923
+ return pxTransformHelper(size, 'px');
4883
4924
  // NOTE: 鸿蒙环境下 style 会自动完成设计稿转换,无需在方法内二次调整
4884
4925
  }
4885
- return val + config.targetUnit;
4926
+ return val + targetUnit;
4886
4927
  }
4887
4928
  function canIUseWebp() {
4888
4929
  return true;