Przeglądaj źródła

Merge pull request #1096 from richartkeil/master

Allow to constrain thumbnail height - Fixes #979
Renée Kooi 6 lat temu
rodzic
commit
5d9f947c2a

+ 36 - 10
packages/@uppy/thumbnail-generator/src/index.js

@@ -15,9 +15,11 @@ module.exports = class ThumbnailGenerator extends Plugin {
     this.title = 'Thumbnail Generator'
     this.title = 'Thumbnail Generator'
     this.queue = []
     this.queue = []
     this.queueProcessing = false
     this.queueProcessing = false
+    this.defaultThumbnailDimension = 200
 
 
     const defaultOptions = {
     const defaultOptions = {
-      thumbnailWidth: 200
+      thumbnailWidth: null,
+      thumbnailHeight: null
     }
     }
 
 
     this.opts = {
     this.opts = {
@@ -37,7 +39,7 @@ module.exports = class ThumbnailGenerator extends Plugin {
    * @param {number} width
    * @param {number} width
    * @return {Promise}
    * @return {Promise}
    */
    */
-  createThumbnail (file, targetWidth) {
+  createThumbnail (file, targetWidth, targetHeight) {
     const originalUrl = URL.createObjectURL(file.data)
     const originalUrl = URL.createObjectURL(file.data)
 
 
     const onload = new Promise((resolve, reject) => {
     const onload = new Promise((resolve, reject) => {
@@ -55,8 +57,8 @@ module.exports = class ThumbnailGenerator extends Plugin {
 
 
     return onload
     return onload
       .then(image => {
       .then(image => {
-        const targetHeight = this.getProportionalHeight(image, targetWidth)
-        const canvas = this.resizeImage(image, targetWidth, targetHeight)
+        const dimensions = this.getProportionalDimensions(image, targetWidth, targetHeight)
+        const canvas = this.resizeImage(image, dimensions.width, dimensions.height)
         return this.canvasToBlob(canvas, 'image/png')
         return this.canvasToBlob(canvas, 'image/png')
       })
       })
       .then(blob => {
       .then(blob => {
@@ -64,6 +66,35 @@ module.exports = class ThumbnailGenerator extends Plugin {
       })
       })
   }
   }
 
 
+  /**
+   * Get the new calculated dimensions for the given image and a target width
+   * or height. If both width and height are given, only width is taken into
+   * account. If neither width nor height are given, the default dimension
+   * is used.
+   */
+  getProportionalDimensions (img, width, height) {
+    const aspect = img.width / img.height
+
+    if (width != null) {
+      return {
+        width: width,
+        height: Math.round(width / aspect)
+      }
+    }
+
+    if (height != null) {
+      return {
+        width: Math.round(height * aspect),
+        height: height
+      }
+    }
+
+    return {
+      width: this.defaultThumbnailDimension,
+      height: Math.round(this.defaultThumbnailDimension / aspect)
+    }
+  }
+
   /**
   /**
    * Make sure the image doesn’t exceed browser/device canvas limits.
    * Make sure the image doesn’t exceed browser/device canvas limits.
    * For ios with 256 RAM and ie
    * For ios with 256 RAM and ie
@@ -149,11 +180,6 @@ module.exports = class ThumbnailGenerator extends Plugin {
     })
     })
   }
   }
 
 
-  getProportionalHeight (img, width) {
-    const aspect = img.width / img.height
-    return Math.round(width / aspect)
-  }
-
   /**
   /**
    * Set the preview URL for a file.
    * Set the preview URL for a file.
    */
    */
@@ -184,7 +210,7 @@ module.exports = class ThumbnailGenerator extends Plugin {
 
 
   requestThumbnail (file) {
   requestThumbnail (file) {
     if (isPreviewSupported(file.type) && !file.isRemote) {
     if (isPreviewSupported(file.type) && !file.isRemote) {
-      return this.createThumbnail(file, this.opts.thumbnailWidth)
+      return this.createThumbnail(file, this.opts.thumbnailWidth, this.opts.thumbnailHeight)
         .then(preview => {
         .then(preview => {
           this.setPreviewURL(file.id, preview)
           this.setPreviewURL(file.id, preview)
           this.uppy.log(`[ThumbnailGenerator] Generated thumbnail for ${file.id}`)
           this.uppy.log(`[ThumbnailGenerator] Generated thumbnail for ${file.id}`)

+ 38 - 14
packages/@uppy/thumbnail-generator/src/index.test.js

@@ -19,12 +19,16 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
     expect(plugin instanceof Plugin).toEqual(true)
     expect(plugin instanceof Plugin).toEqual(true)
   })
   })
 
 
-  it('should accept the thumbnailWidth option and override the default', () => {
+  it('should accept the thumbnailWidth and thumbnailHeight option and override the default', () => {
     const plugin1 = new ThumbnailGeneratorPlugin(new MockCore()) // eslint-disable-line no-new
     const plugin1 = new ThumbnailGeneratorPlugin(new MockCore()) // eslint-disable-line no-new
-    expect(plugin1.opts.thumbnailWidth).toEqual(200)
+    expect(plugin1.opts.thumbnailWidth).toEqual(null)
+    expect(plugin1.opts.thumbnailHeight).toEqual(null)
 
 
     const plugin2 = new ThumbnailGeneratorPlugin(new MockCore(), { thumbnailWidth: 100 }) // eslint-disable-line no-new
     const plugin2 = new ThumbnailGeneratorPlugin(new MockCore(), { thumbnailWidth: 100 }) // eslint-disable-line no-new
     expect(plugin2.opts.thumbnailWidth).toEqual(100)
     expect(plugin2.opts.thumbnailWidth).toEqual(100)
+
+    const plugin3 = new ThumbnailGeneratorPlugin(new MockCore(), { thumbnailHeight: 100 }) // eslint-disable-line no-new
+    expect(plugin3.opts.thumbnailHeight).toEqual(100)
   })
   })
 
 
   describe('install', () => {
   describe('install', () => {
@@ -206,7 +210,8 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
         expect(plugin.createThumbnail).toHaveBeenCalledTimes(1)
         expect(plugin.createThumbnail).toHaveBeenCalledTimes(1)
         expect(plugin.createThumbnail).toHaveBeenCalledWith(
         expect(plugin.createThumbnail).toHaveBeenCalledWith(
           file,
           file,
-          plugin.opts.thumbnailWidth
+          plugin.opts.thumbnailWidth,
+          plugin.opts.thumbnailHeight
         )
         )
       })
       })
     })
     })
@@ -282,19 +287,38 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
     })
     })
   })
   })
 
 
-  describe('getProportionalHeight', () => {
-    it('should calculate the resized height based on the specified width of the image whilst keeping aspect ratio', () => {
+  describe('getProportionalDimensions', () => {
+    function resize (thumbnailPlugin, image, width, height) {
+      return thumbnailPlugin.getProportionalDimensions(image, width, height)
+    }
+
+    it('should calculate the thumbnail dimensions based on the width whilst keeping aspect ratio', () => {
+      const core = new MockCore()
+      const plugin = new ThumbnailGeneratorPlugin(core)
+      expect(resize(plugin, { width: 200, height: 100 }, 50)).toEqual({ width: 50, height: 25 })
+      expect(resize(plugin, { width: 66, height: 66 }, 33)).toEqual({ width: 33, height: 33 })
+      expect(resize(plugin, { width: 201.2, height: 198.2 }, 47)).toEqual({ width: 47, height: 46 })
+    })
+
+    it('should calculate the thumbnail dimensions based on the height whilst keeping aspect ratio', () => {
+      const core = new MockCore()
+      const plugin = new ThumbnailGeneratorPlugin(core)
+      expect(resize(plugin, { width: 200, height: 100 }, null, 50)).toEqual({ width: 100, height: 50 })
+      expect(resize(plugin, { width: 66, height: 66 }, null, 33)).toEqual({ width: 33, height: 33 })
+      expect(resize(plugin, { width: 201.2, height: 198.2 }, null, 47)).toEqual({ width: 48, height: 47 })
+    })
+
+    it('should calculate the thumbnail dimensions based on the default width if no custom width is given', () => {
+      const core = new MockCore()
+      const plugin = new ThumbnailGeneratorPlugin(core)
+      plugin.defaultThumbnailDimension = 50
+      expect(resize(plugin, { width: 200, height: 100 })).toEqual({ width: 50, height: 25 })
+    })
+
+    it('should calculate the thumbnail dimensions based on the width if both width and height are given', () => {
       const core = new MockCore()
       const core = new MockCore()
       const plugin = new ThumbnailGeneratorPlugin(core)
       const plugin = new ThumbnailGeneratorPlugin(core)
-      expect(
-        plugin.getProportionalHeight({ width: 200, height: 100 }, 50)
-      ).toEqual(25)
-      expect(
-        plugin.getProportionalHeight({ width: 66, height: 66 }, 33)
-      ).toEqual(33)
-      expect(
-        plugin.getProportionalHeight({ width: 201.2, height: 198.2 }, 47)
-      ).toEqual(46)
+      expect(resize(plugin, { width: 200, height: 100 }, 50, 42)).toEqual({ width: 50, height: 25 })
     })
     })
   })
   })