在移动浏览器中流畅的Ionic App生涩

时间:2015-09-15 23:13:06

标签: javascript performance ionic

我已经写了一个离子应用,其中9个图像位于DIV内。这是我的CSS文件中的相关代码段:

.mydiv {
    position: relative;
    overflow: hidden;
}
.mydiv > img {
    position: absolute;
    box-shadow: 6px 6px 8px #aaaaaa;
}

我使用$ionicGesture.on('drag', function(e) {})在我的手指移动后移动这些图像。这是我的controller.js的相关部分:

jQuery('.mydiv > img').each(function(i, myImg) {
    jQuery(myImg).css('left', initLeft + e.gesture.touches[0].pageX - initX);
    jQuery(myImg).css('top', initTop + e.gesture.touches[0].pageY - initY);
}

所以,基本上,每次drag事件发生时,我都会通过改变他们的“左”来移动图像。和' top'属性。

问题是,这个解决方案在浏览器中运行得非常好,但是在我的iPhone 5上作为Ionic应用程序非常落后。当我把Ionic的内容放到了www#www;在Web服务器上的文件夹,并使用我的iPhone的Web浏览器访问Web应用程序,运动非常顺利。因此,显然,它不是性能问题,但Ionic正在做一些使应用程序口吃的事情。在我的Mac上使用Chrome Profiler,我了解到几乎所有的时间都被内部Ionic功能使用,而不是我的客户端代码。这似乎是另一个暗示,这是某种离子问题。

为什么我的应用程序在我的移动浏览器中在同一台设备上运行得非常顺畅,当它作为Ionic应用程序打包时会变得如此糟糕?

其他信息:

我拖动的那些图像使用jQuery(myImg).width()进行缩放。我现在用预先缩放的图像文件替换它们并摆脱了box-shadow样式。现在滞后减少但仍然比移动浏览器更糟糕。是否有可能,我的iPhone上的移动Safari使用GPU进行Javascript引发的样式更改,而对于Cordova应用程序,不使用GPU?

3 个答案:

答案 0 :(得分:1)

我没有看过你的动画或你的代码,但我的猜测是设备GPU没有承载应有的重量。

显然没有看到你的应用,我在这里做一些猜测 - 但从你所描述的可能是这个问题:

有几种方法可以让GPU进入,但最基本的是不使用“top”和“left”进行动画制作。使用标准的CSS定位,如top / left to animate DOM元素有效,但它是最慢的方式,正如您所发现的那样:在许多环境中,性能往往很糟糕。 (特别是当您使用复杂的图像或模糊/阴影时)。

更好的方法是使用与GPU相关的 translateX / translateY 。这应该会给你丝般顺畅的表现。使用translateX和translateY也将允许子像素渲染,并提供比使用顶部/左边逐个像素点亮的更光滑的外观。

Chrome团队成员对此进行了很好的讨论: https://www.youtube.com/watch?v=NZelrwd_iRs

最后,如果由于某种原因你必须使用top / left - 一个快速而有点hacky的方法让GPU启动就是将父DIV设置为translate3d(0,0, 0);

这会在浏览器绘制期间强制将父图层置于GPU的手中(通过3D变换),并且您正在使用的后续标准CSS顶部/左侧更改现在应使用GPU进行渲染。 毋庸置疑,第二种方法并不是最佳实践的最佳方法,因此如果可以选择首先使用CSS转换。

答案 1 :(得分:1)

看起来你有动画问题。 Here是来自Ionic团队的一篇文章,解释了如何处理这个问题。

  

当您尝试为左侧属性设置动画时,会发生什么   这些项目,网页视图将不得不返回并尝试重新计算   那个项目的位置。这种情况发生在许多CSS属性中。

     

值得庆幸的是,我们还有其他方法来动画这些项目。

     

让我们更改左边的属性进行转换并设置要使用的值   translate3d。 Translate3d实际上是一个特殊的CSS值   将动画移动到设备的GPU。这称为硬件   加速动画。

@-webkit-keyframes slideIn {
  0% {
    left: -100%;
  }
  100% {
    left: 0;
  }
}

@-webkit-keyframes slideInSmooth {
  0% {
    -webkit-transform: translate3d(-100%,0,0);
  }
  100% {
    -webkit-transform: translate3d(0,0,0);
  }
}


.slide-in{
   -webkit-animation: slideInSmooth ease-in 1; 
  animation: slideInSmooth ease-in 1;
  -webkit-animation-fill-mode: forwards;
  animation-fill-mode: forwards;
  -webkit-animation-duration: 750ms;
  animation-duration: 750ms;
}

答案 2 :(得分:0)

使用transform: translate3d()可以解决问题。动画现在非常流畅。因为我将我的代码从CSS左上角样式转换为使用translate3d()时遇到了一些麻烦,所以这是我为其他用户做的参考:

jQuery('.mydiv > img').each(function(i, myImg) {
    var x = initLeft + e.gesture.touches[0].pageX - initX;
    var y = initTop + e.gesture.touches[0].pageY - initY;
    jQuery(myImg).css({
        '-webkit-transform' : 'translate3d('+x+'px, '+y+'px, 0px)',
        'transform'         : 'translate3d('+x+'px, '+y+'px, 0px)'
    });
}

我甚至可以再次打开box-shadow,动画保持柔滑。