【SUBJECT技术】(MSDP)Rosen图层绘制的应用

一、图层绘制的若干细节

本文结合实例说明 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 filterNodeBACKGROUND_FILTER_INDEX裁剪节点
Rosen::RSCanvasNode pixelMapNodePIXEL_MAP_INDEX阴影图节点
Rosen::RSCanvasNode dragStyleNodeDRAG_STYLE_INDEX拖拽样式节点
Rosen::RSCanvasNode mouseIconNodeMOUSE_ICON_INDEX鼠标光标节点

1.3.3. rootNode 节点存放节点信息

其中 multiSelectedNode 节点是根据 multiSelectedPixelMaps 数量给每个像素图片创建对应的节点

1.3.4. 拖拽多张图片的层叠顺序说明

1.4. 绘制阴影图的方法

1.4.1. SetShadow 系列方法

方法功能
SetShadowColor()设置阴影颜色
SetShadow0ffset()设置阴影偏移
SetShadowAlpha()设置阴影透明度
SetShadowRadius()设置阴影半径
SetShadowPath()设置阴影 path

1.4.2. 阴影 path 说明

Path 本质上讲就是 SVG 的图片信息,就是如下字符串,只包含坐标尺寸部分。

<?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>

用浏览器打开,显示如下:

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::PixelMap> multiSelectedPixelMap = g_drawingInfo.multiSelectedPixelMaps[i];
        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 逐个添加到根节点

size_t multiSelectedNodesSize = g_drawingInfo.multiSelectedNodes.size();
for (size_t i = 0; i < multiSelectedNodesSize; ++i) {
    g_drawingInfo.rootNode->AddChild(g_drawingInfo.multiSelectedNodes[i]);
}

1.5.2. 设置好参数,用 FlushImplicitTransaction()更新、重绘

Rosen::RSTransaction::FlushImplicitTransaction();

1.6. 图层错位的实现

后续目标会按照一定角度进行旋转,以形成错位效果。第一个图片为默认的角度,第二个图片根据设定的旋转角度 POSITIVE_ANGLE 进行旋转,第三个图片根据 NEGATIVE_ANGLE 角度进行旋转,达到层叠错位的效果。设置好属性后将节点添加到 g_drawingInfo.mutilSelectedNodes 中。

遍历 mutilSelectedPixelMapsSize,根据索引找到 FIRST_PIXELMAP_INDEX 和 SECOND_PIXELMAP_INDEX,设置不同的旋转角度和透明度。

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 是一种动画时间曲线,用于描述动画的起始和结束阶段的速度变化。它是一种缓入缓出的曲线,意味着动画在开始和结束时速度较慢,而在中间阶段速度较快。这种时间曲线可以提供一种自然的、连续的视觉反馈,使动画看起来更加自然和流畅。在某些情况下,它还可以使动画的呈现更加平滑,从而增强用户的视觉体验。

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值