Collection-repeat is "jumpy" when scrolling with photos


#1

Hi all, I’m trying to develop an app that uses collection-repeat to scroll through photos from the Camera Roll. The results are not as smooth as native, and I’m wondering if that is my problem, or if I’m expecting too much from ionic/cordova. Specifically, I wanted to make sure I have mitigated this issue:

“Whenever you set the src of an img on iOS to a non-cached value, there is a freeze of anywhere from 50-150ms–even on an iPhone 6.” http://blog.ionic.io/collection-repeat-iteration-two/

I’ve posted a test project on github and would welcome any ideas or suggestions on how to get better performance.

https://github.com/mixersoft/collection-repeat


CameraRoll Plugin for iOS (Android help needed)
#2

Bump. I’m still stumped with this issue, and it makes me feel like I have to go native to show cameraRoll photos properly. I’m using this code for my collection-repeat

<ion-view view-title="CameraRoll {{watch.targetWidth}}px">
  <ion-content delegate-handle="collection-repeat-wrap" class="has-header">
    <div collection-repeat="item in watch.items track by UUID"
    item-height="watch.getHeight($index)"
    item-width="100%"
    item-render-buffer="3"
    force-refresh-images="true"
    >
      <div class="card-wrap">
        <div class="card camera-roll">
          <div class="item item-divider item-stable padding-horizontal card-header">
            <div class="caption capitalize">{{$index}}:
              {{(item.dateTaken | date:'MM/dd/yyyy@h:mma')}} [H={{item.scaledH}}] {{item.UUID}}
            </div>
          </div>
          <div class="item item-image">
            <div class="photo-wrap">

              <img 
              ng-src="{{ watch.fetchSrc(item, $index) }}" 
              ng-class="item.isLoading ? 'invisible' : '' "
              height="{{item.scaledH}}"
              on-img-load='on.load($event, item, $index)'
              >

            </div>
          </div>
          <div class="item tabs card-footer"
          ng-class="{'item-calm':watch.targetType=='FILE_URI',
          'item-royal':watch.targetType=='DATA_URL'}">
            <div class="tab-item icon ion-heart"></div>
            <div class="tab-item icon ion-ios-upload-outline"></div>
            <div class="tab-item icon ion-ios-compose"></div>
          </div>
        </div>
      </div>
    </div>
  </ion-content>
</ion-view>

The on-img-load directive just shows/hides a spinner until the img completes loading - looks like this:

directive('onImgLoad', [
  '$parse', function($parse) {
    var _handleLoad, spinnerMarkup;
    spinnerMarkup = '<i class="icon ion-load-c ion-spin light"></i>';
    _handleLoad = function(ev, photo, index) {
      var $elem, fn, onImgLoad, scope;
      $elem = angular.element(ev.currentTarget);
      $elem.removeClass('loading');
      $elem.next().addClass('hide');
      onImgLoad = $elem.attr('on-photo-load');
      fn = $parse(onImgLoad);
      scope = $elem.scope();
      scope.$apply(function() {
        fn(scope, {
          $event: ev
        });
      });
    };
    return {
      restrict: 'A',
      link: function(scope, $elem, attrs) {
        attrs.$observe('ngSrc', function() {
          $elem.addClass('loading');
          $elem.next().removeClass('hide');
        });
        $elem.on('load', _handleLoad);
        scope.$on('destroy', function() {
          return $elem.off(_handleLoad);
        });
        $elem.after(spinnerMarkup);
      }
    };
  }
])

The scroll is very jumpy while images from the CameraRoll are loading, much more so than when I am loading images from the cloud. Plus, when I scroll back to the top, all the CameraRoll JPGs have already been cached but scrolling is still only “less” jumpy.

All JPGs are reduced to 320px wide. Is this the best performance I can expect from ionic/javascript, or am I possible doing something dumb?


#3

Also, collection-repeat allocates 20 rows of which only 3 are ever visible at any given time. Assuming the photos are cached in cordova.file.applicationStorageDirectory, there should be no performance difference between 20 or 2000 photos right?


#4

I have noticed that collection-repeat buffers out to 20 items if you have less in your collection also.
I ran into this when doing some protractor tests, I only had 5 items but my protractor test was responding with 20. Looking into the DOM there are 15 empty items.