前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >继续修复css3动画一处小bug

继续修复css3动画一处小bug

作者头像
龙泉寺扫地僧
发布2019-02-20 14:38:39
5320
发布2019-02-20 14:38:39
举报
文章被收录于专栏:盟主来了盟主来了

起因还是上次那个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。

代码语言:javascript
复制
>	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++

重点是这个函数:

代码语言:javascript
复制
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,这里面包含了所有正在做动画的列表。如果有的话,就

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

代码语言:javascript
复制
 m_timing->serviceOnNextFrame();

),要么定时唤醒(

代码语言:javascript
复制
m_timing->wakeAfter

然而通过log,我发现调用

代码语言:javascript
复制
 m_timing->serviceOnNextFrame();

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

代码语言:javascript
复制
if (m_needsLayout) {
     WebBeginFrameArgs frameArgs(lastFrameTimeMonotonic, 0, lastFrameTimeMonotonic - m_lastFrameTimeMonotonic);
     m_webViewImpl->beginFrame(frameArgs);
     m_webViewImpl->layout();
代码语言:javascript
复制
	  m_needsLayout = false;
代码语言:javascript
复制
}

这个

代码语言:javascript
复制
m_needsLayout 

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

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

未完待续····

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年12月20日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档