OpenHarmony开发者论坛
标题:
【SUBJECT技术】(MSDP)Rosen图层绘制的应用
[打印本页]
作者:
诚迈_雨哥
时间:
2024-6-3 16:44
标题:
【SUBJECT技术】(MSDP)Rosen图层绘制的应用
[md]# 一、图层绘制的若干细节
本文结合实例说明Rosen图层绘制的若干细节,以点带面,若全面了解需要深入阅读MSDP和Graphic2D子系统相关代码。
## 1.1. 绘制动画的数据来源
由ARKUI调用MSDP的StartDrag()接口将DragData数据信息初始化到DrawingInfo全局变量。
## 1.2. 从设备DPI转换图片偏移位置
获取设备的dpi,通过deviceDpi计算出缩放因子scalingValue
`int32_t deviceDpi = display->GetDpi();`
将pixelMap的Width和Height,通过scalingValue,裁剪尺寸。
`scalingValue=(1.0*deviceDpi*DEVICE_INDEPENDENT_PIXEL / BASELINE_DENSITY) / SVG_ORIGINAL_SIZE;`
竖直方向增加一个adjustSize 偏移量
```
adjustSize = TWELVE_SIZE * GetScaling();
SetBounds(DEFAULT_POSITION_X,adjustSize,pixelMap->GetWidth(),pixelMap->GetHeight());
SetFrame(DEFAULT_POSITION_X,adjustSize,pixelMap->GetWidth(),pixelMap->GetHeight());
```
## 1.3 图层与绘制节点
### 1.3.1. 绘制多图层的基本步骤
1. 创建窗口节点surfaceNode,设置背景颜色、大小、是否可见等信息;
2. 创建根节点rootNode,设置边框长宽大小、背景颜色等信息;
3. 初始化画布;
4. 再分别创建nodes、filterNode、pixelMapNode、dragStyleNode、mouseIconNode节点,设置相对应的节点参数信息。
### 1.3.2. nodes节点存放节点信息
| 各节点 | 对应的下标常量 | 描述 |
| --------------------------------- | ----------------------- | ------------ |
| Rosen::RSCanvasNode filterNode | BACKGROUND_FILTER_INDEX | 裁剪节点 |
| Rosen::RSCanvasNode pixelMapNode | PIXEL_MAP_INDEX | 阴影图节点 |
| Rosen::RSCanvasNode dragStyleNode | DRAG_STYLE_INDEX | 拖拽样式节点 |
| Rosen::RSCanvasNode mouseIconNode | MOUSE_ICON_INDEX | 鼠标光标节点 |
### 1.3.3. rootNode节点存放节点信息
![nodetree.png](
https://forums-obs.openharmony.c ... 8k8bukyqrkwnzee.png
"nodetree.png")
![](./figures/nodetree.png)
其中multiSelectedNode节点是根据multiSelectedPixelMaps数量给每个像素图片创建对应的节点
### 1.3.4. 拖拽多张图片的层叠顺序说明
![draglayer.PNG](
https://forums-obs.openharmony.c ... 43uaw8t61p6btbo.png
"draglayer.PNG")
![](./figures/draglayer.png)
## 1.4. 绘制阴影图的方法
### 1.4.1. SetShadow系列方法
| 方法 | 功能 |
| ----------------- | -------------- |
| SetShadowColor() | 设置阴影颜色 |
| SetShadow0ffset() | 设置阴影偏移 |
| SetShadowAlpha() | 设置阴影透明度 |
| SetShadowRadius() | 设置阴影半径 |
| SetShadowPath() | 设置阴影path |
### 1.4.2. 阴影 path 说明
Path本质上讲就是SVG的图片信息,就是如下字符串,只包含坐标尺寸部分。
```xml
<?xml version="1.0" encoding="UTF-8"?>
<svg width="300px" height="300px" viewBox="0 0 200 200">
<rect x="10" y="10" width="40" height="40" rx="4" ry="4"
style="stroke: gray; fill: lightgray;"/>
</svg>
```
用浏览器打开,显示如下:
![rectangle_svg.png](
https://forums-obs.openharmony.c ... a7wub6163bs1agj.png
"rectangle_svg.png")
![](./figures/rectangle_svg.png)
## 1.5. 图层重叠的实现
### 1.5.1. 将g_drawingInfo.multiSelectedPixelMaps逐个图片添加到节点,然后保存到multiSelectedNodes
保存节点前设置相应参数,例如SetAlpha(alpha) 为设置透明度,SetRotation(degrees) 为设置旋转角度,SetForegroundColor(TRANSPARENT_COLOR_ARGB)为设置前景色
```
void DragDrawing::InitMultiSelectedNodes()
{
size_t multiSelectedPixelMapsSize = g_drawingInfo.multiSelectedPixelMaps.size();
for (size_t i = 0; i < multiSelectedPixelMapsSize; ++i) {
std::shared_ptr<Media:
ixelMap> multiSelectedPixelMap = g_drawingInfo.multiSelectedPixelMaps
;
std::shared_ptr<Rosen::RSCanvasNode> multiSelectedNode = Rosen::RSCanvasNode::Create();
multiSelectedNode->SetBgImageWidth(multiSelectedPixelMap->GetWidth());
multiSelectedNode->SetBgImageHeight(multiSelectedPixelMap->GetHeight());
multiSelectedNode->SetBgImagePositionX(0);
multiSelectedNode->SetBgImagePositionY(0);
multiSelectedNode->SetForegroundColor(TRANSPARENT_COLOR_ARGB);
auto rosenImage = std::make_shared<Rosen::RSImage>();
rosenImage->SetPixelMap(multiSelectedPixelMap);
rosenImage->SetImageRepeat(0);
multiSelectedNode->SetBgImage(rosenImage);
float alpha = DEFAULT_ALPHA;
float degrees = DEFAULT_ANGLE;
if (i == FIRST_PIXELMAP_INDEX) {
alpha = FIRST_PIXELMAP_ALPHA;
degrees = POSITIVE_ANGLE;
} else if (i == SECOND_PIXELMAP_INDEX) {
alpha = SECOND_PIXELMAP_ALPHA;
degrees = NEGATIVE_ANGLE;
}
multiSelectedNode->SetRotation(degrees);
multiSelectedNode->SetAlpha(alpha);
g_drawingInfo.multiSelectedNodes.emplace_back(multiSelectedNode);
}
}
```
### 1.5.2. 绘制前将 multiSelectedNodes 逐个添加到根节点
```cpp
size_t multiSelectedNodesSize = g_drawingInfo.multiSelectedNodes.size();
for (size_t i = 0; i < multiSelectedNodesSize; ++i) {
g_drawingInfo.rootNode->AddChild(g_drawingInfo.multiSelectedNodes
);
}
```
### 1.5.2. 设置好参数,用FlushImplicitTransaction()更新、重绘
`Rosen::RSTransaction::FlushImplicitTransaction();`
## 1.6. 图层错位的实现
后续目标会按照一定角度进行旋转,以形成错位效果。第一个图片为默认的角度,第二个图片根据设定的旋转角度POSITIVE_ANGLE 进行旋转,第三个图片根据NEGATIVE_ANGLE 角度进行旋转,达到层叠错位的效果。设置好属性后将节点添加到g_drawingInfo.mutilSelectedNodes中。
遍历mutilSelectedPixelMapsSize,根据索引找到FIRST_PIXELMAP_INDEX和SECOND_PIXELMAP_INDEX,设置不同的旋转角度和透明度。
```cpp
constexpr float DEFAULT_ANGLE { 0.0f }; // 默认角度
constexpr float POSITIVE_ANGLE { 8.0f }; // 正向旋转角度
constexpr float NEGATIVE_ANGLE { -8.0f }; // 逆向旋转角度
```
## 1.7. 粘滞动画的实现
### 1.7.1. 使用延迟刷新技术,使得过程非一蹴而就
控制刷新的频率,避免过快的刷新导致拖尾效果不明显。不同层叠阴影缩略图的动画持续时间设置为不相同。在拖拽移动过程中,在前面的图片动画持续时间快于后面的图片,已达到拖尾的效果。定义动画的持续时长:
```
constexpr int32_t SHORT_DURATION { 55 };
constexpr int32_t LONG_DURATION { 90 };
```
遍历节点,设置第一个节点的动画持续效果为SHORT_DURATION,其余的动画持续效果为LONG_DURATION。
### 1.7.2. 使用动画缓入缓出技术,使得起止更加流畅,减少“失重”感
使用Rosen::RSNode::Animate对节点进行动画处理,参数RSAnimationTimingCurve::EASE_IN_OUT是一种动画时间曲线,用于描述动画的起始和结束阶段的速度变化。它是一种缓入缓出的曲线,意味着动画在开始和结束时速度较慢,而在中间阶段速度较快。这种时间曲线可以提供一种自然的、连续的视觉反馈,使动画看起来更加自然和流畅。在某些情况下,它还可以使动画的呈现更加平滑,从而增强用户的视觉体验。
# 二、参考文献
* (MSDP) 探索OpenHarmony 拖拽动画的技术实现:
https://forums.openharmony.cn/fo ... thread&tid=2047
* 2D 图形子系统介绍:
https://gitee.com/openharmony/do ... /graphic_graphic_2d
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5