继续修复css3动画一处小bug

起因还是上次那个wke\3d-cube-loading动画。在启动后如果鼠标不hover上去,动画居然不会动。

借此机会学习了下css3在blink里的部分逻辑。

首先需要确定下css3是怎么设置层的transform的。下个GraphicsLayer::setTransform的断点,可以看到:


content::WebPageImpl::setNeedsCommitAndNotLayout
cc_blink::WebLayerImpl::setNeedsCommit
cc_blink::WebLayerImpl::setTransform
blink::GraphicsLayer::setTransform
blink::CompositedDeprecatedPaintLayerMapping::updateTransform
blink::CompositedDeprecatedPaintLayerMapping::updateGraphicsLayerGeometry
blink::GraphicsLayerUpdater::updateRecursive(blink::DeprecatedPaintLayer 
blink::GraphicsLayerUpdater::updateRecursive(blink::DeprecatedPaintLayer 
blink::GraphicsLayerUpdater::updateRecursive(blink::DeprecatedPaintLayer 
blink::GraphicsLayerUpdater::updateRecursive(blink::DeprecatedPaintLayer 
blink::GraphicsLayerUpdater::update
blink::DeprecatedPaintLayerCompositor::updateIfNeeded
blink::DeprecatedPaintLayerCompositor::updateIfNeededRecursive
blink::FrameView::updateAllLifecyclePhasesInternal
blink::PageAnimator::updateLayoutAndStyleForPainting
blink::PageWidgetDelegate::layout

看这组堆栈,原来是每镇layout的时候,更新所有层的transform。

具体就是在CompositedDeprecatedPaintLayerMapping::updateTransform里调用style.applyTransform来设置的。

这个style又是在哪被设置的呢,原来是在这里:

ComputedStyle::setTransform
AnimatedStyleBuilder::applyProperty
LegacyStyleInterpolation::apply
DeferredLegacyStyleInterpolation::apply
StyleResolver::applyAnimatedProperties<1>
StyleResolver::applyAnimatedProperties
StyleResolver::styleForElement
Element::originalStyleForLayoutObject
Element::styleForLayoutObject
Element::recalcOwnStyle(blink::StyleRecalc
Element::recalcStyle
ContainerNode::recalcChildStyle(blink::Sty
Element::recalcStyle(blink::StyleRecalcCha
ContainerNode::recalcChildStyle(blink::Sty
Element::recalcStyle(blink::StyleRecalcCha
ContainerNode::recalcChildStyle(blink::Sty
Element::recalcStyle(blink::StyleRecalcCha
Document::updateStyle(blink::StyleRecalcCh
Document::updateLayoutTree(blink::StyleRec
Document::updateLayoutTreeIfNeeded() 行 43
FrameView::updateStyleAndLayoutIfNeededRec
FrameView::updateAllLifecyclePhasesInterna
FrameView::updateAllLifecyclePhases() 行 2
PageAnimator::updateLayoutAndStyleForPaint
PageWidgetDelegate::layout(blink::Page & p
WebViewImpl::layout() 行 1913 C++

原来是通过StyleResolver::styleForElement这个地方来搞的。StyleResolver::styleForElement这个函数很重要,是所有样式对元素进行更新时候都会调用的。

仔细看这个DeferredLegacyStyleInterpolation::apply,这玩意不但会导致设置transform,还会:

  libcef.dll!blink::AnimatableTransform::AnimatableTransform
  libcef.dll!blink::AnimatableTransform::create
  libcef.dll!blink::AnimatableTransform::interpolateTo
  libcef.dll!blink::AnimatableValue::interpolate
  libcef.dll!blink::InterpolableAnimatableValue::interpolate
  libcef.dll!blink::Interpolation::interpolate
  libcef.dll!blink::DeferredLegacyStyleInterpolation::apply

创建插值的动画transform。

>	libcef.dll!blink::AnimationEffect::updateInheritedTime(double inheritedTime, blink::TimingUpdateReason reason) 行 149	C++
 	libcef.dll!blink::InertEffect::sample(WTF::RawPtr<blink::HeapVector<blink::Member<blink::Interpolation>,0> > & result) 行 54	C++
 	libcef.dll!blink::AnimationStack::activeInterpolations
 	libcef.dll!blink::CSSAnimations::calculateAnimationActiveInterpolations
 	libcef.dll!blink::CSSAnimations::calculateUpdate
 	libcef.dll!blink::StyleResolver::applyAnimatedProperties
 	libcef.dll!blink::StyleResolver::styleForElement
 	libcef.dll!blink::Element::originalStyleForLayoutObject() 行 1625	C++
 	libcef.dll!blink::Element::styleForLayoutObject() 行 1601	C++

中间N字的过程就省略了,最后我发现

  minichrome.exe!blink::WebViewImpl::scheduleAnimation() 行 4158 C++
  minichrome.exe!blink::ChromeClientImpl::scheduleAnimation() 行 488 C++
  minichrome.exe!blink::ScrollableArea::scheduleAnimation() 行 499 C++
  minichrome.exe!blink::AnimationTimeline::AnimationTimelineTiming::serviceOnNextFrame() 行 198 C++
  minichrome.exe!blink::AnimationTimeline::scheduleNextService() 行 172 C++
  minichrome.exe!blink::DocumentAnimations::updateCompositorAnimations(blink::Document & document) 行 99 C++
  minichrome.exe!blink::DeprecatedPaintLayerCompositor::updateIfNeededRecursive() 行 235 C++
  minichrome.exe!blink::FrameView::updateAllLifecyclePhasesInternal() 行 2481 C++
  minichrome.exe!blink::FrameView::updateAllLifecyclePhases() 行 2452 C++
  minichrome.exe!blink::PageAnimator::updateLayoutAndStyleForPainting(blink::LocalFrame * rootFrame) 行 98 C++
  minichrome.exe!blink::PageWidgetDelegate::layout(blink::Page & page, blink::LocalFrame & root) 行 67 C++
  minichrome.exe!blink::WebViewImpl::layout() 行 1913 C++


重点是这个函数:

void AnimationTimeline::scheduleNextService()
{
    ASSERT(m_outdatedAnimationCount == 0);

    double timeToNextEffect = std::numeric_limits<double>::infinity();
    for (const auto& animation : m_animationsNeedingUpdate) {
        timeToNextEffect = std::min(timeToNextEffect, animation->timeToEffectChange());
    }

    if (timeToNextEffect < s_minimumDelay) {
        m_timing->serviceOnNextFrame();
    } else if (timeToNextEffect != std::numeric_limits<double>::infinity()) {
        m_timing->wakeAfter(timeToNextEffect - s_minimumDelay);
    }
}


在layout的过程中,会检查AnimationTimeline,这里面包含了所有正在做动画的列表。如果有的话,就


去通知外部要么马上调度(

 m_timing->serviceOnNextFrame();
),要么定时唤醒(
m_timing->wakeAfter

然而通过log,我发现调用

 m_timing->serviceOnNextFrame();

后并没有马上调度。仔细一看,我外层代码写的有问题:


if (m_needsLayout) {
     WebBeginFrameArgs frameArgs(lastFrameTimeMonotonic, 0, lastFrameTimeMonotonic - m_lastFrameTimeMonotonic);
     m_webViewImpl->beginFrame(frameArgs);
     m_webViewImpl->layout();
	  m_needsLayout = false;
}

这个

m_needsLayout 

位置不对,不应该在layout后面。因为layout过程中由于上述讨论,会再次设置m_needsLayout = true;而执行完layout后,m_needsLayout = false;会冲掉。导致失去一次调度的机会。

问题的解决其实很简单,但要调这坨css3动画在blink里的流程比较费劲。有时间我再补充这篇文章里动画流程相关。


未完待续····


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值