å‘下滑动时å‘åŽæ»‘动滑å—

时间:2018-09-10 14:18:35

标签: javascript css performance css3 css-transforms

我跟éšthis article使用了垂直å¯æ»‘动å¼å¡ç‰‡æ»‘å—。

这个问题分为两个部分。

1。我ä¸æ˜Žç™½åœ¨å‘下滑动时如何å转滑å—çš„æ–¹å‘?

以下是相关的密ç ç¬”-https://codepen.io/bmarcelino/pen/vRYPXV

æ›´æ–°å¡çš„相关功能

function updateUi() {
    requestAnimationFrame(function(){
        elTrans = 0;
        var elZindex = 5;
        var elScale = 1;
        var elOpac = 1;
        var elTransTop = items;
        var elTransInc = elementsMargin;

        for(i = currentPosition; i < (currentPosition + items); i++){
            if(listElNodesObj[i]){
                listElNodesObj[i].classList.add('stackedcards-bottom', 'stackedcards--animatable', 'stackedcards-origin-bottom');

                listElNodesObj[i].style.transform ='scale(' + elScale + ') translateX(0) translateY(' + (elTrans - elTransInc) + 'px) translateZ(0)';
                listElNodesObj[i].style.webkitTransform ='scale(' + elScale + ') translateX(0) translateY(' + (elTrans - elTransInc) + 'px) translateZ(0)';
                listElNodesObj[i].style.opacity = elOpac;
                listElNodesObj[i].style.display = 'block';
                listElNodesObj[i].style.zIndex = elZindex;

                elScale = elScale - 0.04;
                elOpac = elOpac - (1 / items);
                elZindex--;
            }
        }

    });

};

我ä¸å¤ªç²¾é€šJava。
截至目å‰ï¼Œæ»‘å—在å‘åŽæ»‘动时åªèƒ½å‘一个方å‘移动-å‘å‰ç§»åŠ¨ã€‚我想了解å‘滑å—添加åŽé€€è¿åŠ¨çš„实现。

2。关于性能

此外,requestAnimationFrame确实有助于在滑动时æä¾›æµç•…的体验。但是,在DOM中应该有多少张å¡æœ‰é™åˆ¶ï¼Ÿæˆ‘将调用APIæœåŠ¡æ¥èŽ·å–内容,因为它将返回媒体,因此将opacity设置为0会以任何方å¼å‡å°‘内存使用å—?

作者认为删除DOM会迫使æµè§ˆå™¨é‡æ–°ç»˜åˆ¶ï¼Œè¿™ä¼šä¸¥é‡å½±å“性能å—?但是,该虚拟列表ä¸æ˜¯å—?在这ç§æƒ…况下,性能/æˆæœ¬æ¯”是多少?

2 个答案:

答案 0 :(得分:1)

è¿™ä¸ä¼šæ˜¯ä¸€ä¸ªå®Œæ•´çš„答案,但是由于没有其他人åšå‡ºå›žåº”,我将为您回答问题的第1部分æ供帮助。请注æ„,这åªæ˜¯ä¸€ä¸ªç¤ºä¾‹ï¼Œå¯ä»¥å¸®åŠ©æ‚¨äº†è§£å¦‚何使å¡å‘åŽé€€è€Œä¸æ˜¯å¯ç”¨äºŽç”Ÿäº§çš„解决方案。

è¦é‡æ–°è¿žæŽ¥â€œé¡¶éƒ¨â€æŒ‰é’®ä»¥å‘åŽç§»åŠ¨ï¼Œæ‚¨åªéœ€è¦è¿›è¡Œä»¥ä¸‹æ›´æ”¹ï¼š

  • 在onSwipeTop()中,将currentPosition = currentPosition + 1;更改为currentPosition = currentPosition - 1;
  • 还å¯ä»¥åœ¨onSwipeTop()中将transformUi(0, -1000, 0, topObj);更改为transformUi(0, 0, 0, topObj);。这会éšè—å¡ç‰‡ä¸Šå‡åŠ¨ç”»ã€‚
  • 在updateUi()中将i < (currentPosition + items)更改为i <= (currentPosition + items)。这修å¤äº†ä¸‰ä¸ªå¡ä¸­åªæœ‰ä¸¤ä¸ªè¢«æ›´æ–°çš„错误。

现在å°è¯•å‡ æ¬¡å•å‡»â€œå‘å·¦â€æˆ–“å³â€ï¼Œç„¶åŽå•å‡»â€œé¡¶éƒ¨â€ä¸¤æ¬¡ã€‚æ¯æ¬¡å•å‡»â€œé¡¶éƒ¨â€ï¼Œæ‚¨åº”该会看到一张å¡ç‰‡å›žæ¥ã€‚

大概您想将新按钮设置为“底部â€ï¼Œè€Œä¸æ˜¯é‡æ–°å¸ƒçº¿â€œé¡¶éƒ¨â€ï¼Œå¹¶ä¸”您å¯èƒ½è¿˜å¸Œæœ›é™åˆ¶å¯¹currentPosition的更改,因此您ä¸èƒ½è¶…越第一个/最åŽä¸€å¼ å¡ï¼Œä½†è¿™è‡³å°‘应该å¯ä»¥å¸®åŠ©æ‚¨å…¥é—¨ã€‚

我希望这会有所帮助。

答案 1 :(得分:1)

å转滑å—

以下内容是有关脚本工作方å¼çš„éžå¸¸ç®€çŸ­çš„解释,包括有关建议使脚本å转方å‘和“å–消刷å¡â€çš„建议。åå‘方法的çµæ„Ÿæ¥è‡ªRocky的出色回答-ä»–ç†åº”得到这个想法的充分肯定。

  1. 文档加载åŽï¼Œè„šæœ¬å°†èŽ·å¾—所有å¯ç”¨å¡çš„列表。在您的示例中,å¡ç‰‡æ˜¯DOM中的硬编ç å…ƒç´ ï¼Œå¡ç‰‡åˆ—表listElNodesObj是这些元素的列表。è¦è®°ä½è¿™ä¸€ç‚¹å¾ˆé‡è¦ï¼šå¡ç‰‡ä¸æ˜¯æŠ½è±¡çš„,它们从根本上讲是页é¢ä¸­çš„元素。当您å‘å¡ä¸­æ·»åŠ åª’体和数æ®æ—¶ï¼Œå¿…须将其附加到DOM中的元素上(例如,具有数æ®å±žæ€§ï¼‰ã€‚

  2. 该脚本获å–å为currentPosition的当å‰å¡ç´¢å¼•ï¼›é¦–先,这是头牌。然åŽï¼Œå®ƒæ˜¾ç¤ºå½“å‰å¡åŠå…¶åŽçš„两张å¡ï¼ˆcurrentPosition + 1å’ŒcurrentPosition + 2)。

  3. 在输入时,该å¡å…·æœ‰é€‚当的动画效果,å¯ä»¥ä»Žå·¦ä¾§ï¼Œå³ä¾§æˆ–顶部飞出。当å‰çš„å¡ç´¢å¼•å°†å¢žåŠ 1,å†å¢žåŠ 1进入堆栈。显示新的当å‰å¡åŠå…¶åŽçš„两张å¡ã€‚

ç›®å‰ï¼Œæ‰€æœ‰åŠ¨ä½œ-å‘左,å‘å³å’Œå‘上滑动-全部进入堆栈。è¦å转方å‘,您需è¦ä¾¦å¬æ–°åŠ¨ä½œï¼ˆæˆ–é‡æ–°ä½¿ç”¨å½“å‰åŠ¨ä½œï¼Œä¾‹å¦‚滑动顶部),并且在该动作上,当å‰å¡ç´¢å¼•ä¼šå‡å°‘1。添加å°äºŽé›¶çš„校验。 currentPosition = Math.max( 0, currentPosition - 1 );

Rocky回答了一个出色的解决方案。

现在,此实现从DOM中已ç»å­˜åœ¨çš„所有å¡å¼€å§‹ã€‚您似乎想从åŽç«¯APIæ›´æ–°å¡å †æ ˆã€‚为此,您需è¦ä¸€ç§åœ¨åˆ·å¡æ—¶ä»Žä¸€ç«¯å¼¹å‡ºå¡å¹¶åœ¨å¦ä¸€ç«¯æ·»åŠ æ–°å¡çš„方法。如上所述,您的å¡ç‰‡åˆ—表与DOM紧密相关,因此您需è¦å¯¹å…¶è¿›è¡ŒæŠ½è±¡ä¸€äº›ä»¥å®žçŽ°æ­¤ç›®çš„。创建一个从API填充的元素列表,并用它填充åˆå§‹æ–‡æ¡£ï¼ˆè€Œä¸æ˜¯ç›¸å)。滑动时,无论å‘å‰è¿˜æ˜¯å‘åŽï¼Œè¯·ä»ŽåŽé€€ç«¯å¼¹å‡ºä¸€ä¸ªå…ƒç´ ï¼Œç„¶åŽå°†ä»ŽAPI填充的新元素添加到å‰è¿›ç«¯ã€‚有趣的是,列表大å°å’Œå½“å‰ä½ç½®å°†å§‹ç»ˆä¿æŒä¸å˜ã€‚

如果您当å‰çš„ä½ç½®å§‹ç»ˆæ˜¯æœ€é¡¶å±‚å¡ç‰‡çš„åŽé€€ä½ç½®ï¼Œå¹¶ä¸”堆栈中的最åŽä¸€å¼ å¡ç‰‡æ¯”最åŽä¸€å¼ å¯è§çš„å¡ç‰‡å¤šä¸€ä¸ªï¼Œåˆ™æ‚¨å°†å§‹ç»ˆæœ‰ä¸€å¼ å¡ç‰‡å¯ä»¥è¿›è¡ŒåŠ¨ç”»æ˜¾ç¤ºã€‚

性能

此处的术语ç¨ä½œæ¾„清:更改类似opacity的内容会导致é‡æ–°ç»˜åˆ¶ï¼Œä»ŽDOM中删除元素(无论是软删除还是硬删除)都会导致é‡æŽ’。é‡ç»˜æ˜¯æ˜‚贵的,因为æµè§ˆå™¨å¿…须检查DOM中æ¯ä¸ªå…ƒç´ çš„å¯è§æ€§ã€‚由于必须é‡æ–°è®¡ç®—布局,因此回æµç„Šç”šè‡³æ›´åŠ æ˜‚贵。å‚è§What's the difference between reflow and repaint?

有两ç§æ–¹æ³•å¯ä»¥é™åˆ¶DOM中的å¡æ•°ã€‚您å¯ä»¥è®¾ç½®display: none,将其ä¿ç•™åœ¨å†…存和DOM中,但阻止æµè§ˆå™¨åœ¨é‡æŽ’或é‡æ–°ç»˜åˆ¶æ—¶è€ƒè™‘它。或者,您å¯ä»¥ä½¿ç”¨parent.appendChild(child)添加å¡ï¼Œå¹¶ä½¿ç”¨parent.removeChild(child)删除å¡ï¼Œä»¥ç¡®ä¿JavaScript在删除åŽå°±ä¸å­˜åœ¨å¯¹è¯¥å…ƒç´ çš„引用,并且一旦垃圾收集器è¿è¡Œï¼Œè¯¥åˆ é™¤çš„元素将被物ç†åœ°ä»Žå†…存中删除。两者都会触å‘回æµã€‚带有opacity: 0的元素将完全ä¿ç•™åœ¨DOM中,以进行é‡æŽ’å’Œé‡ç»˜ã€‚

关于什么能æ供最佳性能:更改ä¸é€æ˜Žåº¦æˆ–从内存中删除,这实际上å–决于您的实现。我å¯ä»¥ç»™ä½ ä¸€äº›ç›¸å…³çš„指示。

内存é™åˆ¶â€œ 在DOM中应有多少å¡æœ‰é™åˆ¶ï¼Ÿâ€ç»å¯¹å¯ä»¥ï¼Œä½†è¿™å–决于您的数æ®ã€‚如果您的å¡æ€»æ•°å¾ˆå°‘,则确实å¯ä»¥ä¸€å¼€å§‹å°±å…¨éƒ¨åŠ è½½ï¼Œå¹¶ç”¨opacity: 0或display: noneéšè—刷过的å¡ã€‚甚至å¯ä»¥æ”¹å–„动画的æµåŠ¨æ€§ï¼ˆè¯·å‚è§ä¸‹é¢æœ‰å…³åŠ¨ç”»å—计算的è¦ç‚¹ï¼‰ã€‚纯粹由于更高的内存使用而导致的性能差异几乎肯定ä¸ä¼šå¼•èµ·æ³¨æ„,因为现代æµè§ˆå™¨å…·æœ‰å¤§é‡å†…存,并且会在需è¦é¡µé¢æ–‡ä»¶æˆ–交æ¢ä¹‹å‰å°†è„šæœ¬åœæ­¢è¿è¡Œã€‚如果您确实会在内存中拥有如此巨大的DOM以至于性能会明显下é™ï¼Œé‚£ä¹ˆæ‚¨çš„内容下载时间将是一个更大的问题。

然而,更é‡è¦çš„是,您正确地问到删除或添加元素是å¦æ˜¯è™šæ‹Ÿåˆ—表的全部内容。如果您永远ä¸ä¼šå†è®¿é—®å…ƒç´ ï¼Œä¸ºä»€ä¹ˆè¿˜è¦ä¿ç•™ä¸€ä¸ªå…ƒç´ åœ¨å†…存中,或者为什么加载一个远远超出列表å¯èƒ½æ°¸è¿œæ— æ³•åˆ°è¾¾çš„元素。实际上,您声明您将è¦é€šè¿‡API访问内容,这强烈暗示您将一次访问一张å¡ä¸Šçš„内容。等到您拥有API中的所有内容åŽï¼Œå¯èƒ½è¦èŠ±è´¹å¾ˆé•¿æ—¶é—´ã€‚您似乎已ç»çŸ¥é“,仅访问填写固定大å°åˆ—表所需的å¡ä¼šæ供更好的体验。 (如果è¦å转滑å—çš„æ–¹å‘,则应在内存中至少ä¿ç•™ä¸€å¼ å·²åˆ·å¡ï¼Œè¿™æ ·åœ¨å‘åŽåˆ·å¡æ—¶ï¼Œæ‚¨ä¸ä¼šåœ¨ç­‰å¾…下载内容时通过暂åœæˆ–å‘é€ç©ºå¡æ¥ç ´å动画)< / p>

动画阻止计算,除了下载时间以外,display: noneå’Œopacity: 0对于刷å¡æˆ–在列表中è·ç¦»å¤ªè¿œçš„å¡çš„真正性能优势在于它们的内容在DOM中已ç»å­˜åœ¨ã€‚ (并且如上所述,opacity: 0还有一个优点:它ä¸ä¼šè§¦å‘é‡æŽ’)。通过比较,从物ç†ä¸Šåœ¨DOM中添加和删除元素需è¦é¢å¤–的计算,å³åœ¨DOM树中æ’入或删除å¡èŠ‚点åŠå…¶æ‰€æœ‰å­ä»£ã€‚如果这是åŒæ­¥å®Œæˆçš„,那么您将进行动画阻止计算,从而在DOM树更新完æˆä¹‹å‰æ‰èƒ½è¿›è¡Œæ»‘动动画。

但是,让我们ä¿æŒé€è§†ã€‚首先,从DOM树中添加和删除节点通常éžå¸¸å¿«ã€‚事实è¯æ˜Žï¼ŒinnerHTML在添加到DOM时速度ç¨å¿«ï¼Œä½†æ˜¯åœ¨åˆ é™¤æ—¶åˆ™æ…¢å¾—多,因此请谨慎选择毒è¯ã€‚但是,除éžæ‚¨è¦å‘å¡ä¸­æ·»åŠ æ•°å或数百åƒå­—节的数æ®ï¼Œå¦åˆ™æ“作将likely take less than a millisecond。其次,您声明将从API中检索列表的内容,这æ„味ç€å¼‚步连接。如果在构造异步函数时è¦å°å¿ƒï¼Œåˆ™å°†å†…容添加到DOM的函数ä¸ä¸€å®šä¼šå¹²æ‰°åŠ¨ç”»ã€‚ (这并ä¸æ„味ç€JavaScript是多线程的;它是å•çº¿ç¨‹çš„,但结构良好的异步代ç æ„味ç€å‡½æ•°æ‰§è¡Œçš„顺åºæ— å…³ç´§è¦ï¼‰ã€‚如果在没有将动画排入队列的情况下完æˆäº†æ·»åŠ æˆ–移除的å¡ç‰‡çš„æ“作,则对性能的影å“都将å˜æˆshorter and less perceivable。

最åŽï¼Œæ¯ä¸ªDOMæ“作都是一个新的渲染更新,因此您希望进行尽å¯èƒ½å°‘çš„æ“作。因此,您将在内存中创建彼此相对的元素,并且仅在最åŽå°†æœ€é«˜å…ƒç´ æ’å…¥DOM。å‚è§Fastest DOM insertion。如果您å¯ä»¥åœ¨è¯¥å¡ä¸­åŒ…å«æ‰€æœ‰å¡æ•°æ®ï¼Œåˆ™æ¯æ¬¡æ»‘动仅需è¦ä¸¤æ¬¡DOMæ“作。这å–决于å¡æ‰€åŒ…å«çš„媒体,但是å¯ä»¥æƒ³è±¡ï¼Œæœ€å的情况是,将å¡æ·»åŠ å’Œç§»é™¤åˆ°å †æ ˆä¸­çš„总时间仅需数å毫秒。

GPU 大多数渲染引擎都å¯ä»¥è®¿é—®GPU,该GPU在涉åŠå¤§é‡åƒç´ çš„绘图和åˆæˆæ“作中å¯ä»¥æ¯”CPU效率更高。默认情况下,渲染层ä¸ä½¿ç”¨GPU渲染。页é¢GPU Accelerated Compositing in Chrome指出,

  

从ç†è®ºä¸Šè®²ï¼Œæ¯ä¸ªå•ç‹¬çš„RenderLayer都å¯ä»¥å°†å…¶è‡ªèº«ç»˜åˆ¶åˆ°å•ç‹¬çš„背衬表é¢ä¸­ï¼ˆå³GPUå¯è®¿é—®çš„åˆæˆå±‚],实际上这å¯èƒ½åœ¨å†…存(尤其是VRAM)方é¢éžå¸¸æµªè´¹ã€‚

为确ä¿ä½¿ç”¨GPU渲染ä¸é€æ˜Žåº¦å˜åŒ–之类的动画,您需è¦ä»¥éšå¼åˆæˆçš„æ–¹å¼è®¿é—®è¯¥åŠ¨ç”»ã€‚上é¢çš„页é¢æ供了如何执行此æ“作的完整列表,但实际上,您将使用CSS动画æ¥æ›´æ”¹ä¸é€æ˜Žåº¦ï¼Œä»Žè€Œæ示æµè§ˆå™¨å°†å…ƒç´ æå‡ä¸ºåˆæˆå±‚。您æ供的当å‰ä»£ç ä½¿ç”¨JavaScriptæ›´æ–°æ¯ä¸ªåŠ¨ç”»å¸§çš„ä¸é€æ˜Žåº¦ï¼Œå› æ­¤ä¸é€æ˜Žåº¦æ›´æ”¹ä¸æ˜¯éšå¼åˆæˆçš„候选对象。 (您似乎对è¿åŠ¨åŠ¨ç”»ä½¿ç”¨äº†3Då˜æ¢ï¼Œè¯¥å˜æ¢è§¦å‘了éšå¼åˆæˆï¼Œå› æ­¤å¯èƒ½å·²ç»å¯¹GPU进行了优化)。更改代ç ä»¥ä½¿ç”¨CSS动画并ä¸æ˜¯ä¸€ä»¶å®¹æ˜“的事,但是很å¯èƒ½ä¼šæ高性能,特别是动画过程中的帧频。当然,需è¦é’ˆå¯¹ç‰¹å®šâ€‹â€‹æƒ…况进行基准测试,以验è¯è¿™ä¸€ç‚¹ï¼Œæœ‰å…³https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/çš„æŸäº›GPU动画为何è¿è¡Œé€Ÿåº¦è¾ƒæ…¢çš„讨论,请å‚è§{{3}}。


总而言之,由于从虚拟列表中动æ€æ·»åŠ å’Œåˆ é™¤å…ƒç´ è€Œå¯¼è‡´çš„性能æ高,虽然å¯èƒ½æ¯”完全加载整个列表略高,但æ¯æ¬¡æ»‘动å¯èƒ½ä»…多了几毫秒。使用异步实现时,动画期间的帧频ä¸åº”更改。通常,这很容易让步,因为å¯èƒ½ä¼šèŠ‚çœå¤§é‡çš„åˆå§‹ä¸‹è½½æ—¶é—´ï¼Œä½†å¿…须与特定实现的其他细节一起考虑。

相关问题