【问题标题】:Nativescript image thumbnailsNativescript 图像缩略图
【发布时间】:2019-08-01 00:58:37
【问题描述】:

我正在使用 Angular 8.0 + NativeScript 6.0 和 NativeScript 相机插件来拍照并将它们存储在我的应用程序的图库中。当我列出我在应用中拍摄的图像时,它会加载全尺寸图像,这会减慢整个应用的速度。

有没有办法让我获得画廊图像的缩略图而不是完整图像?

目前,我通过将完整图像的 URL 存储在名为receipt_url 的字符串中并将其传递到后端来将其保存在我的数据库中。这是我拍照并存储 URL 的代码;

onTakeReceiptTap(args) {
    requestPermissions().then(
        () => {
            takePicture({width: 640, height: 480, keepAspectRatio: true})
                .then((imageAsset: any) => {
                    this.receiptImage = imageAsset;

                    console.log("Taken receipt")
                    let that = this;

                    if (imageAsset.android) {
                        this._dataItem.receipt_url = imageAsset.android;
                    } else if (imageAsset.ios) {
                        this._dataItem.receipt_url = imageAsset.ios;
                    }

                }, (error) => {
                    console.log("Error: " + error);
                });
        },
        () => alert('permissions rejected')
    );
} // onTakeReceiptTap

在执行列表时,我只需从数据库中获取所有记录,包括收据 url,然后像这样显示图片;

        <Image rowspan="2" col="1" [src]="item.receipt_url" stretch="aspectFit"></Image>

鉴于我只有一个 URL,我想知道 Android/iOS 是否创建一个缩略图,我可以在其中获取 URL 并将其存储并在我的列表中使用它,还是我必须以某种方式自己创建缩略图并且从后端发送缩略图还是保存缩略图的 URL?

更新:虚拟滚动

我尝试像这样添加虚拟滚动,并尝试了不同的高度(150、500 和 1000),所有这些滚动仍然非常缓慢和生涩。

  <GridLayout row="1" columns="*, auto">
    <RadListView [items]="dataItems"
                 [filteringFunction]="filterItems"
                 pullToRefresh="true"
                 (pullToRefreshInitiated)="onPullToRefreshInitiated($event)">

      <ScrollView height="500">
        <ng-template tkListItemTemplate let-item="item">
          <StackLayout orientation="vertical">
            <GridLayout class="itemContainer" rows="50,*" columns="*,100">

              <!-- Currently these images are full size and slowing down the listing -->
              <Image rowspan="2" col="1" [src]="item.picture_url" stretch="aspectFit"></Image>

              <Label row="0" col="0" class="nameLabel" [text]="item.name"></Label>

            </GridLayout>

            <!-- <StackLayout orientation="horizontal">
                 <Label text="Price: "></Label>
                 <Label class="gross_centsLabel" [text]="item.gross_cents"></Label>
                 </StackLayout> -->
          </StackLayout>
        </ng-template>
      </ScrollView>

    </RadListView>
  </GridLayout>

更新:使用 ImageSource

如果我尝试对列表中的每个图像使用 ImageSource,则会收到以下错误;

LOG from device Galaxy S8: ERROR Error: java.lang.OutOfMemoryError: Failed to allocate a 36578316 byte allocation with 16269904 free bytes and 15MB until OOM

这是我设置 ImageSources 的方式;

loadData() {
    this._dataItemService.listing()
        .subscribe(loadedItems => {
            loadedItems.forEach((itemObject) => {
                itemObject.picture = fromFile(itemObject.picture_url);
                this._dataItems.unshift(itemObject) ;
            });
        })
}

“图片”属性在数据模型中设置为 ImageSource。

更新:保存缩略图

我设法在前端保存了一个缩略图并将其显示在我的列表中。现在上市速度更快了。

                    const source = new ImageSource();
                    source.fromAsset(imageAsset)
                        .then((imageSource: ImageSource) => {
                            const folderPath = knownFolders.documents().path;
                            const fileName = "test.jpg";
                            const filePath = path.join(folderPath, fileName);
                            const saved: boolean = imageSource.saveToFile(filePath, "jpg");
                            if (saved) {
                                console.log("Gallery: " + this._dataItem.picture_url);
                                console.log("Saved: " + filePath);
                                console.log("Image saved successfully!");
                            }
                        });

【问题讨论】:

  • 滚动问题可能来自于您在RadListView 中插入ScrollView
  • 返回的图片资源已经有调整大小的图片,但是当你通过图片url加载它时它不会生效。从图像资产创建图像源并分配相同的图像组件。

标签: angular image android-camera nativescript thumbnails


【解决方案1】:

在 Android 上downsample 图像似乎是可能的,但他们似乎没有谈论任何针对 IOS 的优化。

但我可以建议两种方法,它们甚至可以结合起来,也可以在两个平台上工作:

  1. 利用 Angular CDK 提供的 Virtual Scroll(假设您使用 Angular 7)
  2. 探索在客户端或后端创建缩略图的可行性,正如您在自己的实现或 imagemagick 之类的库中提到的那样

【讨论】:

  • 我认为在前端会有一个标准的方法来做这件事。 Angular/iOS 必须为其各自的照片库执行此操作。
【解决方案2】:

如前所述,您可以在后端创建缩略图。 我建议使用Sharp(或libvips)更快。

您可以做的另一件好事是避免将*ngFor 用于您知道会很长的列表。请改用ListView

ListView 回收视图并仅渲染/加载应用程序需要的视图。从而避免加载到不可见的内存视图中。

<ListView [items]="countries" (itemTap)="onItemTap($event)" class="list-group">
    <ng-template let-item="item">
        <GridLayout class="itemContainer" rows="50,*" columns="*,100">
              <!-- Currently these images are full size and slowing down the listing -->
              <Image rowspan="2" col="1" [src]="item.picture_url" stretch="aspectFit"></Image>
              <Label row="0" col="0" class="nameLabel" [text]="item.name"></Lab
        </GridLayout>
    </ng-template>
</ListView>

更新:修复 RadListView 实现

RadListView 的实现中,内部有一个ScrollView

记住:

  • 在 RadListView 中,您必须仅使用项目的模板:&lt;ng-template tkListItemTemplate let-item="item"&gt;...
  • RadListView(如ListView)是一个滚动小部件。你不需要ScrollView
    <RadListView [items]="dataItems"
                 [filteringFunction]="filterItems"
                 pullToRefresh="true"
                 (pullToRefreshInitiated)="onPullToRefreshInitiated($event)">
        <ng-template tkListItemTemplate let-item="item">
            <GridLayout class="itemContainer" rows="50,*" columns="*,100">

              <!-- Currently these images are full size and slowing down the listing -->
              <Image rowspan="2" col="1" [src]="item.picture_url" stretch="aspectFit"></Image>

              <Label row="0" col="0" class="nameLabel" [text]="item.name"></Label>

            </GridLayout>
        </ng-template>
    </RadListView>

【讨论】:

    猜你喜欢
    • 2010-11-13
    • 2012-01-27
    • 2014-07-23
    • 2010-10-03
    • 2016-09-24
    • 1970-01-01
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多