高性能 CSS3 动画

2023-05-28 0 1,076

户机房数据流采用的情形,电子设备耗电的情形。

高性能 CSS3 动画

有关简洁度,主要就充分体现在后端动画电影中,在原有的后端动画电影管理体系中,一般来说有三种商业模式:JS动画电影与CSS3动画电影。 JS动画电影是透过JS静态重写式样同时实现动画电影潜能的一类计划,在PC端相容中低端应用程序中可说是一类所推荐计划。 而在终端端,他们优先选择操控性更佳应用程序原生植物同时实现计划:CSS3动画电影。

不过,CSS3 动画电影在终端多终端机情景下,较之PC会直面更多的操控性难题,主要就充分体现在动画电影的雅雷与闪光。

现阶段对提高终端端CSS3动画电影新体验的主要就方式有以下几点:

尽量多的借助硬体潜能,如采用3D形变来迈入GPU快速

-webkit-transform: translate3d(0, 0, 0);-moz-transform: translate3d(0, 0, 0);-ms-transform: translate3d(0, 0, 0);transform: translate3d(0, 0, 0);

如动画电影操作过程有闪光(一般来说出现在动画电影已经开始的这时候),能试著上面的Hack:

-webkit-backface-visibility: hidden;-moz-backface-visibility: hidden;-ms-backface-visibility: hidden;backface-visibility: hidden;-webkit-perspective: 1000;-moz-perspective: 1000;-ms-perspective: 1000;perspective: 1000;

如上面一个元素透过 translate3d 右移 500px 的动画电影简洁度会明显优于采用 left 属性:

#ball-1 { transition: -webkit-transform .5s ease; -webkit-transform: translate3d(0, 0, 0);}#ball-1.slidein { -webkit-transform: translate3d(500px, 0, 0);}#ball-2 { transition: left .5s ease; left: 0;}#ball-2.slidein { left: 500px;}

注:3D形变会消耗更多的内存与功耗,应确实有操控性难题时才去采用它,兼在权衡

尽量少的采用 box-shadows 与 gradients

box-shadows 与 gradients 往往都是页面的操控性杀手,尤其是在一个元素同时都采用了它们,所以拥抱扁平化设计吧。

尽量的让动画电影元素不在文档流中,以减少重排

position: fixed;position: absolute;

优化 DOM layout 操控性

他们从实例已经开始描述这个主题:

var newWidth = aDiv.offsetWidth + 10;aDiv.style.width = newWidth + px;var newHeight = aDiv.offsetHeight + 10;aDiv.style.height = newHeight + px;var newWidth = aDiv.offsetWidth + 10;var newHeight = aDiv.offsetHeight + 10;aDiv.style.width = newWidth + px;aDiv.style.height = newHeight + px;

这是两段潜能上完全等同的代码,显式的差异正如他们所见,只有执行顺序的区别。但真是如此吗?上面是加了说明注释的代码版本,很好的阐述了其中的进一步差异:

// 触发两次 layoutvar newWidth = aDiv.offsetWidth + 10; // ReadaDiv.style.width = newWidth + px; // Writevar newHeight = aDiv.offsetHeight + 10; // ReadaDiv.style.height = newHeight + px; // Write// 只触发一次 layoutvar newWidth = aDiv.offsetWidth + 10; // Readvar newHeight = aDiv.offsetHeight + 10; // ReadaDiv.style.width = newWidth + px; // WriteaDiv.style.height = newHeight + px; // Write

从注释中可找到规律,连续的读取offsetWidth/Height属性与连续的设置width/height属性,较之分别读取设置单个属性可少触发一次layout。

从结论看似乎与执行队列有关,没错,这是应用程序的优化策略。所有可触发layout的操作都会被暂时放入 layout-queue 中,等到必须更新的这时候,再计算整个队列中所有操作影响的结果,如此就可只进行一次的layout,从而提高操控性。

关键一,可触发layout的操作,哪些操作下会layout的更新(也称为reflow或者relayout)?

他们从应用程序的源码同时实现入手,以开源 Webkit/Blink为例, 对layout的更新,Webkit 主要就透过Document::updateLayoutDocument::updateLayoutIgnorePendingStylesheets 两个方式:

void Document::updateLayout(){ ASSERT(isMainThread()); FrameView* frameView = view(); if (frameView && frameView->isInLayout()) { ASSERT_NOT_REACHED(); return; } if (Element* oe = ownerElement()) oe->document()->updateLayout(); updateStyleIfNeeded(); StackStats::LayoutCheckPoint layoutCheckPoint; if (frameView && renderer() && (frameView->layoutPending() || renderer()->needsLayout())) frameView->layout(); if (m_focusedNode && !m_didPostCheckFocusedNodeTask) { postTask(CheckFocusedNodeTask::create()); m_didPostCheckFocusedNodeTask = true; }}void Document::updateLayoutIgnorePendingStylesheets(){ bool oldIgnore = m_ignorePendingStylesheets; if (!haveStylesheetsLoaded()) { m_ignorePendingStylesheets = true; HTMLElement* bodyElement = body(); if (bodyElement && !bodyElement->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) { m_pendingSheetLayout = DidLayoutWithPendingSheets; styleResolverChanged(RecalcStyleImmediately); } else if (m_hasNodesWithPlaceholderStyle) recalcStyle(Force); } updateLayout(); m_ignorePendingStylesheets = oldIgnore;}

从 updateLayoutIgnorePendingStylesheets 方式的内部同时实现可知,其也是对 updateLayout 方式的扩展,并且在原有的 layout 更新商业模式中,大部分情景都是调用 updateLayoutIgnorePendingStylesheets 来进行layout的更新。

搜索 Webkit 同时实现中调用 updateLayoutIgnorePendingStylesheets 方式的代码, 得到以下可导致触发 layout 的操作:

Element: clientHeight, clientLeft, clientTop, clientWidth, focus(), getBoundingClientRect(), getClientRects(), innerText, offsetHeight, offsetLeft, offsetParent, offsetTop, offsetWidth, outerText, scrollByLines(), scrollByPages(), scrollHeight, scrollIntoView(), scrollIntoViewIfNeeded(), scrollLeft, scrollTop, scrollWidthFrame, HTMLImageElement: height, widthRange: getBoundingClientRect(), getClientRects()SVGLocatable: computeCTM(), getBBox()SVGTextContent: getCharNumAtPosition(), getComputedTextLength(), getEndPositionOfChar(), getExtentOfChar(), getNumberOfChars(), getRotationOfChar(), getStartPositionOfChar(), getSubStringLength(), selectSubString()SVGUse: instanceRootwindow: getComputedStyle(), scrollBy(), scrollTo(), scrollX, scrollY, webkitConvertPointFromNodeToPage(), webkitConvertPointFromPageToNode()

进一步深入 Layout,那上文中必须更新的必要条件是什么? 在 Stoyan Stefanov 的 Rendering: repaint, reflow/relayout, restyle一文中已做比较详细的解答,可移步了解~

相关阅读

举报/反馈

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务