Skip to content

Commit d815bd3

Browse files
authored
feat:adapt Harmony (#4)
1 parent 8874ee4 commit d815bd3

7 files changed

+366
-77
lines changed

harmony/shared_element/src/main/cpp/RNSharedStyle.h

+20-7
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,29 @@
99
namespace rnoh {
1010
class RNSharedStyle {
1111
public:
12-
RNSharedStyle(){}
13-
~RNSharedStyle(){}
14-
12+
RNSharedStyle() {}
13+
~RNSharedStyle() {}
14+
1515
facebook::react::Rect boundingBox;
1616
ArkUI_AttributeItem sourceItem;
1717
ArkUI_IntOffset offset;
18-
19-
void setSource(const char* source){
20-
sourceItem = {.string = source};
18+
// ancestor view borderRadius
19+
ArkUI_AttributeItem borderRadius = {.value = {}, .size = 0};
20+
21+
facebook::react::Rect parentBoundingBox;
22+
23+
void setSource(const char *source) { sourceItem = {.string = source}; }
24+
25+
void setBorderRadius(const ArkUI_AttributeItem *item) {
26+
if (item->size == 1) {
27+
auto radius = item->value[0].f32;
28+
ArkUI_NumberValue values[] = {{radius}, {radius}, {radius}, {radius}};
29+
borderRadius = {.value = values, .size = 4};
30+
} else if (item->size == 4) {
31+
borderRadius = {.value = item->value, .size = item->size};
32+
} else {
33+
borderRadius = {.size = 0};
34+
}
2135
}
22-
2336
};
2437
} // namespace rnoh

harmony/shared_element/src/main/cpp/RNTransitionNode.h

+198-45
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "RNSharedStyle.h"
1313

1414
#include "RNSharedNode.h"
15+
#include "helper/Rect.h"
1516

1617

1718
namespace rnoh {
@@ -35,6 +36,7 @@ class RNTransitionNode : public ArkUINode {
3536
void setAlign(int align) {
3637
if (align_ != align) {
3738
align_ = align;
39+
setAlignmentWithAlign();
3840
}
3941
}
4042

@@ -44,34 +46,103 @@ class RNTransitionNode : public ArkUINode {
4446
mInitialNodePositionSet = true;
4547
}
4648
}
49+
50+
using Alignment = ArkUI_Alignment;
51+
void setAlignmentWithAlign() {
52+
switch (align_) {
53+
case 0:
54+
setAlignment(Alignment::ARKUI_ALIGNMENT_CENTER);
55+
break;
56+
case 1:
57+
// left-top
58+
setAlignment(Alignment::ARKUI_ALIGNMENT_TOP_START);
59+
break;
60+
case 2:
61+
// left-center
62+
setAlignment(Alignment::ARKUI_ALIGNMENT_START);
63+
setAlignment(Alignment::ARKUI_ALIGNMENT_CENTER);
64+
break;
65+
case 3:
66+
// left-bottom
67+
setAlignment(Alignment::ARKUI_ALIGNMENT_BOTTOM_START);
68+
break;
69+
case 4:
70+
// right-top
71+
setAlignment(Alignment::ARKUI_ALIGNMENT_TOP_START);
72+
break;
73+
case 5:
74+
// right-center
75+
setAlignment(Alignment::ARKUI_ALIGNMENT_END);
76+
setAlignment(Alignment::ARKUI_ALIGNMENT_CENTER);
77+
break;
78+
case 6:
79+
// right-bottom
80+
setAlignment(Alignment::ARKUI_ALIGNMENT_BOTTOM_END);
81+
break;
82+
case 7:
83+
// center-top
84+
setAlignment(Alignment::ARKUI_ALIGNMENT_TOP);
85+
setAlignment(Alignment::ARKUI_ALIGNMENT_CENTER);
86+
break;
87+
case 8:
88+
// center-center
89+
setAlignment(Alignment::ARKUI_ALIGNMENT_CENTER);
90+
break;
91+
case 9:
92+
// center-bottom
93+
setAlignment(Alignment::ARKUI_ALIGNMENT_BOTTOM);
94+
setAlignment(Alignment::ARKUI_ALIGNMENT_CENTER);
95+
break;
96+
}
97+
}
4798

4899
void beforeTransition(int item, std::shared_ptr<ComponentInstance> node,
49100
std::shared_ptr<ComponentInstance> ancestor) {
50101
if (node == nullptr) {
51102
return;
52103
}
53-
node->getLocalRootArkUINode().setOpacity(0);
54-
transitionNodes.push_back(node);
55104

105+
node->getLocalRootArkUINode().setOpacity(0);
56106

107+
transitionNodes.push_back(node);
108+
57109
if (item == 0) {
58110
startNode = node;
111+
112+
if (animation_ == 2) {
113+
startNode->getLocalRootArkUINode().setOpacity(1);
114+
}
115+
59116
startImageStyle = std::make_shared<RNSharedStyle>();
60117
std::shared_ptr<ComponentInstance> sourceNode = resolveNode(node, startImageStyle);
61118
startSharedElementNode.setSize(
62119
{startImageStyle->boundingBox.size.width, startImageStyle->boundingBox.size.height});
63120
startSharedElementNode.setSources(startImageStyle->sourceItem.string);
121+
122+
auto borderRadius = NativeNodeApi::getInstance()->getAttribute(
123+
ancestor->getLocalRootArkUINode().getArkUINodeHandle(), NODE_BORDER_RADIUS);
124+
startImageStyle->setBorderRadius(borderRadius);
125+
126+
startImageStyle->parentBoundingBox = ancestor->getBoundingBox();
127+
64128
} else {
65129
endNode = node;
66130

131+
if (animation_ == 3) {
132+
endNode->getLocalRootArkUINode().setOpacity(1);
133+
}
134+
67135
endImageStyle = std::make_shared<RNSharedStyle>();
68136
std::shared_ptr<ComponentInstance> sourceNode = resolveNode(node, endImageStyle);
69137
endSharedElementNode.setSize(
70138
{endImageStyle->boundingBox.size.width, endImageStyle->boundingBox.size.height});
71139
endSharedElementNode.setSources(endImageStyle->sourceItem.string);
72140

141+
auto borderRadius = NativeNodeApi::getInstance()->getAttribute(
142+
ancestor->getLocalRootArkUINode().getArkUINodeHandle(), NODE_BORDER_RADIUS);
143+
endImageStyle->setBorderRadius(borderRadius);
73144

74-
// endSharedElementNode.setUp(item);
145+
endImageStyle->parentBoundingBox = ancestor->getBoundingBox();
75146
}
76147
}
77148

@@ -92,6 +163,7 @@ class RNTransitionNode : public ArkUINode {
92163
OH_ArkUI_NodeUtils_GetLayoutPositionInScreen(node->getLocalRootArkUINode().getArkUINodeHandle(),
93164
intOff);
94165
style->offset = {intOff->x, intOff->y};
166+
95167
return child;
96168
}
97169
}
@@ -110,6 +182,7 @@ class RNTransitionNode : public ArkUINode {
110182
// 取 start
111183
recoverAlpha = mInitialNodePositionSet && nodePosition_ == 1;
112184
}
185+
113186
if (recoverAlpha) {
114187
for (std::shared_ptr<ComponentInstance> node : transitionNodes) {
115188
node->getLocalRootArkUINode().setOpacity(1);
@@ -118,52 +191,126 @@ class RNTransitionNode : public ArkUINode {
118191
} else {
119192
if (direct == 1) {
120193
setLayoutPosition(direct);
121-
122-
Float scaleW = (endImageStyle->boundingBox.size.width - startImageStyle->boundingBox.size.width) * (1 - nodePosition_);
123-
Float endW = endImageStyle->boundingBox.size.width - scaleW;
124-
125-
Float scaleH = (endImageStyle->boundingBox.size.height - startImageStyle->boundingBox.size.height) * (1 - nodePosition_);
126-
Float endH = endImageStyle->boundingBox.size.height - scaleH;
127-
128-
float scalePositionX = static_cast<float>(endImageStyle->offset.x) / pixelDensity + scaleW / 2;
129-
float scalePositionY = static_cast<float>(endImageStyle->offset.y) / pixelDensity + scaleH / 2;
130-
131-
if (endW < startImageStyle->boundingBox.size.width) {
132-
endW = startImageStyle->boundingBox.size.width;
133-
};
134-
if (endH < startImageStyle->boundingBox.size.height) {
135-
endH = startImageStyle->boundingBox.size.height;
136-
};
137-
setPosition({scalePositionX, scalePositionY});
138-
setSize({endW, endH});
139-
endSharedElementNode.setSize({endW, endH});
194+
195+
if (endImageStyle->boundingBox.size.width > startImageStyle->boundingBox.size.width &&
196+
endImageStyle->boundingBox.size.height > startImageStyle->boundingBox.size.height) {
197+
// endImageStyle 矩形在宽度和高度上都更大
198+
Float scaleW = (endImageStyle->boundingBox.size.width - startImageStyle->boundingBox.size.width) *
199+
(1 - nodePosition_);
200+
Float endW = endImageStyle->boundingBox.size.width - scaleW;
201+
202+
Float scaleH = (endImageStyle->boundingBox.size.height - startImageStyle->boundingBox.size.height) *
203+
(1 - nodePosition_);
204+
Float endH = endImageStyle->boundingBox.size.height - scaleH;
205+
206+
float scalePositionX = static_cast<float>(endImageStyle->offset.x) / pixelDensity + scaleW / 2;
207+
float scalePositionY = static_cast<float>(endImageStyle->offset.y) / pixelDensity + scaleH / 2;
208+
209+
if (endW < startImageStyle->boundingBox.size.width) {
210+
endW = startImageStyle->boundingBox.size.width;
211+
};
212+
if (endH < startImageStyle->boundingBox.size.height) {
213+
endH = startImageStyle->boundingBox.size.height;
214+
};
215+
setPosition({scalePositionX, scalePositionY});
216+
setSize({endW, endH});
217+
endSharedElementNode.setSize({endW, endH});
218+
} else if (endImageStyle->boundingBox.size.width < startImageStyle->boundingBox.size.width &&
219+
endImageStyle->boundingBox.size.height < startImageStyle->boundingBox.size.height) {
220+
// startImageStyle 矩形在宽度和高度上都更大
221+
// 计算宽度和高度的缩放量
222+
Float scaleW = (startImageStyle->boundingBox.size.width - endImageStyle->boundingBox.size.width) *
223+
nodePosition_;
224+
Float endW = startImageStyle->boundingBox.size.width - scaleW;
225+
226+
Float scaleH = (startImageStyle->boundingBox.size.height - endImageStyle->boundingBox.size.height) *
227+
nodePosition_;
228+
Float endH = startImageStyle->boundingBox.size.height - scaleH;
229+
230+
// 计算缩放后的位置
231+
float scalePositionX = static_cast<float>(startImageStyle->offset.x) / pixelDensity + scaleW / 2;
232+
float scalePositionY = static_cast<float>(startImageStyle->offset.y) / pixelDensity + scaleH / 2;
233+
234+
// 确保宽度和高度不小于 endImageStyle 的最小值
235+
if (endW > startImageStyle->boundingBox.size.width) {
236+
endW = startImageStyle->boundingBox.size.width;
237+
}
238+
if (endH > startImageStyle->boundingBox.size.height) {
239+
endH = startImageStyle->boundingBox.size.height;
240+
}
241+
242+
// 设置位置和大小
243+
setPosition({scalePositionX, scalePositionY});
244+
setSize({endW, endH});
245+
endSharedElementNode.setSize({endW, endH});
246+
}
247+
248+
applyOpacity(animation_);
249+
140250
maybeThrow(NativeNodeApi::getInstance()->insertChildAt(
141251
m_nodeHandle, endSharedElementNode.getArkUINodeHandle(), static_cast<int32_t>(-1)));
142252
} else {
143-
Float scaleW = (endImageStyle->boundingBox.size.width - startImageStyle->boundingBox.size.width) * nodePosition_;
144-
Float startW = startImageStyle->boundingBox.size.width + scaleW;
145-
146-
Float scaleH = (endImageStyle->boundingBox.size.height - startImageStyle->boundingBox.size.height) * nodePosition_;
147-
Float startH = startImageStyle->boundingBox.size.width + scaleH;
148-
149-
float scalePositionX = static_cast<float>(startImageStyle->offset.x) / pixelDensity - scaleW / 2;
150-
float scalePositionY = static_cast<float>(startImageStyle->offset.y) / pixelDensity - scaleH / 2;
151-
152-
if (startW > endImageStyle->boundingBox.size.width) {
153-
startW = endImageStyle->boundingBox.size.width;
154-
};
155-
if (startH > endImageStyle->boundingBox.size.height) {
156-
startH = endImageStyle->boundingBox.size.height;
157-
};
158-
setPosition({scalePositionX, scalePositionY});
159-
setSize({startW, startH});
160-
startSharedElementNode.setSize({startW, startH});
253+
if (endImageStyle->boundingBox.size.width > startImageStyle->boundingBox.size.width &&
254+
endImageStyle->boundingBox.size.height > startImageStyle->boundingBox.size.height) {
255+
// endImageStyle 矩形在宽度和高度上都更大
256+
Float scaleW = (endImageStyle->boundingBox.size.width - startImageStyle->boundingBox.size.width) *
257+
nodePosition_;
258+
Float startW = startImageStyle->boundingBox.size.width + scaleW;
259+
260+
Float scaleH = (endImageStyle->boundingBox.size.height - startImageStyle->boundingBox.size.height) *
261+
nodePosition_;
262+
Float startH = startImageStyle->boundingBox.size.width + scaleH;
263+
264+
float scalePositionX = static_cast<float>(startImageStyle->offset.x) / pixelDensity - scaleW / 2;
265+
float scalePositionY = static_cast<float>(startImageStyle->offset.y) / pixelDensity - scaleH / 2;
266+
267+
if (startW > endImageStyle->boundingBox.size.width) {
268+
startW = endImageStyle->boundingBox.size.width;
269+
};
270+
if (startH > endImageStyle->boundingBox.size.height) {
271+
startH = endImageStyle->boundingBox.size.height;
272+
};
273+
274+
setPosition({scalePositionX, scalePositionY});
275+
setSize({startW, startH});
276+
startSharedElementNode.setSize({startW, startH});
277+
} else if (endImageStyle->boundingBox.size.width < startImageStyle->boundingBox.size.width &&
278+
endImageStyle->boundingBox.size.height < startImageStyle->boundingBox.size.height) {
279+
// 计算缩放量
280+
Float scaleW = (startImageStyle->boundingBox.size.width - endImageStyle->boundingBox.size.width) *
281+
(1 - nodePosition_);
282+
Float startW = endImageStyle->boundingBox.size.width + scaleW;
283+
284+
Float scaleH = (startImageStyle->boundingBox.size.height - endImageStyle->boundingBox.size.height) *
285+
(1 - nodePosition_);
286+
Float startH = endImageStyle->boundingBox.size.height + scaleH;
287+
288+
// 计算新的位置,保证中心对齐
289+
float scalePositionX = static_cast<float>(endImageStyle->offset.x) / pixelDensity - scaleW / 2;
290+
float scalePositionY = static_cast<float>(endImageStyle->offset.y) / pixelDensity - scaleH / 2;
291+
292+
// 设定最大值限制
293+
if (startW > startImageStyle->boundingBox.size.width) {
294+
startW = startImageStyle->boundingBox.size.width;
295+
}
296+
if (startH > startImageStyle->boundingBox.size.height) {
297+
startH = startImageStyle->boundingBox.size.height;
298+
}
299+
300+
// 设置新的位置和大小
301+
setPosition({scalePositionX, scalePositionY});
302+
setSize({startW, startH});
303+
startSharedElementNode.setSize({startW, startH});
304+
}
305+
306+
applyOpacity(animation_);
307+
161308
maybeThrow(NativeNodeApi::getInstance()->insertChildAt(
162309
m_nodeHandle, startSharedElementNode.getArkUINodeHandle(), static_cast<int32_t>(-1)));
163310
}
164311
}
165312
};
166-
313+
167314
int isSet = 0;
168315

169316
void setLayoutPosition(int direct) {
@@ -175,8 +322,18 @@ class RNTransitionNode : public ArkUINode {
175322
}
176323
}
177324

325+
void applyOpacity(int animationType) {
326+
if (animationType == 1 || animationType == 3) {
327+
setOpacity(0.5);
328+
} else if (animationType == 2) {
329+
setOpacity(0.8);
330+
}
331+
}
332+
178333
using Weak = std::weak_ptr<ComponentInstance>;
179334
ComponentInstance::Weak parent;
335+
std::shared_ptr<RNSharedStyle> startImageStyle = std::make_shared<RNSharedStyle>();
336+
std::shared_ptr<RNSharedStyle> endImageStyle = std::make_shared<RNSharedStyle>();
180337

181338
private:
182339
float pixelDensity = 3.25;
@@ -186,7 +343,6 @@ class RNTransitionNode : public ArkUINode {
186343
float nodePosition_;
187344
bool mInitialNodePositionSet = false;
188345

189-
190346
std::vector<facebook::react::SharedElementWarpNodeStruct> transitionItems;
191347

192348
bool mInitialNodeLayoutPositionSet = false;
@@ -196,9 +352,6 @@ class RNTransitionNode : public ArkUINode {
196352
std::shared_ptr<ComponentInstance> endNode = nullptr;
197353

198354
ImageNode startSharedElementNode{};
199-
std::shared_ptr<RNSharedStyle> startImageStyle = std::make_shared<RNSharedStyle>();
200-
201355
ImageNode endSharedElementNode{};
202-
std::shared_ptr<RNSharedStyle> endImageStyle = std::make_shared<RNSharedStyle>();
203356
};
204357
} // namespace rnoh

0 commit comments

Comments
 (0)