HarmonyOS鸿蒙Next中结合Navigation的共享元素转场的demo的计算问题

HarmonyOS鸿蒙Next中结合Navigation的共享元素转场的demo的计算问题 首先,文档链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-shared-element-transition#%E7%BB%93%E5%90%88navigation%E4%BD%BF%E7%94%A8

疑问代码:

// 首先计算卡片的宽高与窗口宽高的比例
let widthScaleRatio = cardItemInfo_px.width / WindowUtils.windowWidth_px;
let heightScaleRatio = cardItemInfo_px.height / WindowUtils.windowHeight_px;
let isUseWidthScale = widthScaleRatio > heightScaleRatio;
let initScale: number = isUseWidthScale ? widthScaleRatio : heightScaleRatio;

let initTranslateX: number = 0;
let initTranslateY: number = 0;
let initClipWidth: Dimension = 0;
let initClipHeight: Dimension = 0;
// 使得PageTwo卡片向上扩到状态栏
let initPositionValue: number = -(WindowUtils.topAvoidAreaHeight_px + extraTranslateValue);

if (isUseWidthScale) {
  initTranslateX = px2vp(cardItemInfo_px.left - (WindowUtils.windowWidth_px - cardItemInfo_px.width) / 2);
  initClipWidth = '100%';
  initClipHeight = px2vp((cardItemInfo_px.height) / initScale);
  initTranslateY = px2vp(cardItemInfo_px.top - ((vp2px(initClipHeight) - vp2px(initClipHeight) * initScale) / 2));
} else {
  initTranslateY = px2vp(cardItemInfo_px.top - (WindowUtils.windowHeight_px - cardItemInfo_px.height) / 2);
  initClipHeight = '100%';
  initClipWidth = px2vp((cardItemInfo_px.width) / initScale);
  initTranslateX = px2vp(cardItemInfo_px.left - (WindowUtils.windowWidth_px / 2 - cardItemInfo_px.width / 2));
}

主要疑问在:initTranslateY = px2vp(cardItemInfo_px.top - ((vp2px(initClipHeight) - vp2px(initClipHeight) * initScale) / 2));

首先 cardItemInfo_px.topPageOne 元素的 top 值,initClipHeightPageTwo 动画后的元素高度,由于等比缩放,所以 vp2px(initClipHeight) * initScale 这部分的值应该是 PageOne 中元素的高度(后续日志已经证明)

所以 ((vp2px(initClipHeight) - vp2px(initClipHeight) * initScale) 这部分是 PageTwo 元素与 PageOne 元素的高度差

PageTwo 渲染时要做动画,所以 PageTwo 元素初始的位置应该与 PageOne 元素的位置相同,所以 PageTwo 元素的 initTranslateY 不应该直接是 PageOne 中元素距离顶部的距离吗(因为 PageTwo 元素的 Y0)?为什么要做高度差除以 2


更多关于HarmonyOS鸿蒙Next中结合Navigation的共享元素转场的demo的计算问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

你好,问题内部处理中,请耐心等待。

更多关于HarmonyOS鸿蒙Next中结合Navigation的共享元素转场的demo的计算问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


嗷,我懂了,initTranslateY = cardItemInfo_px.topPageTwoPageOne 的元素的 Y 轴是一样的,当这个值再向上也就是减去高度差的一半,就让两个元素的中心点在同一个位置,然后 PageTwo 中的元素设置 scale 值使新元素与老元素在相同的位置上开始做动画,形成一镜到底的效果

你可以尝试下,将initTranslateY的公式改成下方你说的,直接设置成cardItemInfo的高度。

initTranslateY = px2vp(cardItemInfo_px.top);

你测试下会发现,图片转场动画变得就不会那么流程,因为直接设置高度,没有考虑到图片变大后,实际高度就会变小的情况。

我知道我说的这个不对,但是我不知道这个为什么不对,为什么 Y轴的偏移位置等于 原本上边距 - 高度差的一半,我不知道这个公式怎么推理出来的,所以我不理解,

在HarmonyOS鸿蒙Next中,结合Navigation实现共享元素转场时,计算问题主要涉及动画的起始和结束位置。通过SharedElementTransition组件,可以定义共享元素的动画效果。关键步骤包括:

  1. 获取元素位置:使用getBoundingClientRect获取共享元素在源页面和目标页面的位置信息。
  2. 计算偏移量:根据获取的位置信息,计算元素在转场过程中的偏移量。
  3. 应用动画:将计算出的偏移量应用到SharedElementTransition的动画属性中,实现平滑转场。

示例代码:

const startRect = startElement.getBoundingClientRect();
const endRect = endElement.getBoundingClientRect();
const offsetX = endRect.left - startRect.left;
const offsetY = endRect.top - startRect.top;

SharedElementTransition({
  startElement,
  endElement,
  duration: 300,
  curve: Curve.EaseInOut,
  translate: { x: offsetX, y: offsetY }
});

通过精确计算,确保共享元素在转场过程中的位置和大小变化自然流畅。

回到顶部