nanopage icon indicating copy to clipboard operation
nanopage copied to clipboard

Multiple image sizes

Open s3ththompson opened this issue 7 years ago • 14 comments

I've been trying to figure out an elegant way to support multiple image sizes with hypha, but perhaps there's an opportunity for nanopage to smooth this over.

Is there any way to associate multiple files with a single identifier? E.g. image.jpg and [email protected]?

Understood if this is out of scope.

s3ththompson avatar Apr 22 '18 04:04 s3ththompson

This might not be quite what you're talking about since it seems like you are wanting to resolve multiple files to a single key via hypha, but nonetheless this might give some ideas? I've been using multiple image sizes with a hypha-ish content structure (using Kirby to spit this out). My content is shaped a little something like (only showing the bare minimum of keys here):

{
  '/some-page': {
    files: {
      'some-file.jpg': {
        sizes: {
          500: '/path/to/some-page/some-file-500.jpg',
          1000: '/path/to/some-page/some-file-1000.jpg',
          1500: '/path/to/some-page/some-file-1500.jpg'
        }
      }
    }
  }
}

This pattern seems to work pretty well for consolidating image sizes. You could do something like:

var sizes = page('/some-page').file('some-file.jpg').value('sizes')

fwiw, I use this with a little nanocomponent to render an appropriate image size based on it's parent's size (kinda like a context aware srcset). I'll try to get a repo up for that after current build I'm working on is wrapped.

jongacnik avatar Apr 25 '18 20:04 jongacnik

That’s pretty solid @jongacnik, hmm. Perhaps we could structure that simply by checking to see if there is a file appended with filename-{INT}.jpg the same way we check for metadata by checking by seeing if there is filename.jpg.txt.

jondashkyle avatar Apr 25 '18 21:04 jondashkyle

@jongacnik yeah, that's absolutely perfect @jondashkyle that would be great.

I'm using gulp-responsive to generate different sizes with a known naming pattern. I also use gulp to write out the aspect ratio to a metadata file:

var probe = require('probe-image-size')

var size = probe.sync(file.contents)
if (size !== null) {
  metadata = merge(metadata, {
    data: {
      aspect: (size.width / size.height)
    }
  })
}

Then I've hacked hypha/transform to run the site object through this function:

module.exports = removeResponsiveImages

function removeResponsiveImages(site) {
  for (var href in site) {
    var files = site[href].files
    for (var file in files) {
      if (isResponsive(files[file])) delete files[file]
    }
  }
  return site
}

function isResponsive(file) {
  if (file.extension == '.webp') return true
  var suffixes = ['-md', '-l', '-xl']
  for (var suffix of suffixes) {
    if (file.name.endsWith(suffix)) return true
  }
  return false
}

And then I basically reconstruct the sizes dynamically when I'm formatting them.

But it would definitely be preferable for hypha to append the different sizes to the file object.

@jongacnik also, I totally agree that there should be a nanocomponent to render images intelligently. There are a lot of nice ideas in lazysizes.

Right now my component constructs a picture element with srcset for webp and jpg, fades in the image once it's loaded, and adds padding based on the aspect ratio to keep intrinsic sizes:

function calcPadding (aspect) {
  return `padding-bottom: ${100 / aspect}%;`
}

Would def be curious to see what you've come up with.

s3ththompson avatar Apr 25 '18 21:04 s3ththompson

@s3ththompson nice, i’m thinking about this for the Enoki Panel too, but entirely clientside within the panel and using canvas to resize, get metadata, etc… @jongacnik could be cool to throw that little nanocomponent into a repo and we could spec this out a bit more.

jondashkyle avatar Apr 25 '18 21:04 jondashkyle

Btw this makes me want file data stored alongside pages as per https://github.com/jondashkyle/nanopage/issues/7 even more.

jondashkyle avatar Apr 25 '18 21:04 jondashkyle

Btw this makes me want file data stored alongside pages as per https://github.com/jondashkyle/nanopage/issues/7 even more.

jondashkyle avatar Apr 25 '18 21:04 jondashkyle

Yep totally. Although I do worry about ballooning size of the site object. My index.js (which contains the site object) for this choo app is now 1/2 the size of my total bundle. I probably need to figure out some sort of async loading for site data...

s3ththompson avatar Apr 25 '18 22:04 s3ththompson

@jondashkyle I think the filename pattern matching for hypha is cool. Perhaps it could catch different dimension formats: /-\d*x?\d*\./ for things like: filename-500.jpg, filename-500x500.jpg, filename-500x.jpg, filename-x500.jpg

@s3ththompson I had the same thought re: site object size, but might be ok. I'll drop this thought into https://github.com/jondashkyle/nanopage/issues/7 though so we don't get sidetracked here.

Will try to package up that nanocomponent late today/ tomorrow!

jongacnik avatar Apr 26 '18 00:04 jongacnik

@s3ththompson heads up I pushed that image component up https://github.com/jongacnik/monoimage. It assumes the file object is shaped like what is above with the sizes field.

jongacnik avatar Apr 30 '18 01:04 jongacnik

@jondashkyle monoimage looks great. just to confirm, you're getting the sizes part of the file object from Kirby, not hypha, right?

s3ththompson avatar Apr 30 '18 18:04 s3ththompson

err sorry meant @jongacnik

s3ththompson avatar Apr 30 '18 18:04 s3ththompson

@s3ththompson correct. Ya, that is still an open q in regards to the best way to generate via hypha, or enoki, or etc.

jongacnik avatar Apr 30 '18 19:04 jongacnik

yeah, to do that in a unified way both client and server side requires a bit of thinking. seeing as hypha accepts fs as a param, we could simply see if the relevant function is available, and if so we can read meta information like dimensions. that also enables you to pass in any arbitrary function of your choosing via fs to get the job done.

where that gets a little hairy is when running client side within beaker. the only way to obtain (i can think of) dimension like that is via reading the image buffer into canvas. that’s obviously a super slow operation, hahah.

anyway, could be cool to add support for this if the environment enables it, and progressively fall back if not.

jondashkyle avatar May 04 '18 00:05 jondashkyle

anyway, could be cool to add support for this if the environment enables it, and progressively fall back if not.

👍

s3ththompson avatar May 07 '18 19:05 s3ththompson