jondashkyle / nanopage

super handy utilities for traversing flat content state
Apache License 2.0
42 stars 4 forks source link

Multiple image sizes #9

Open s3ththompson opened 6 years ago

s3ththompson commented 6 years ago

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 image@2x.jpg?

Understood if this is out of scope.

jongacnik commented 6 years ago

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.

jondashkyle commented 6 years ago

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.

s3ththompson commented 6 years ago

@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.

jondashkyle commented 6 years ago

@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 commented 6 years ago

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

jondashkyle commented 6 years ago

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

s3ththompson commented 6 years ago

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...

jongacnik commented 6 years ago

@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 commented 6 years ago

@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.

s3ththompson commented 6 years ago

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

s3ththompson commented 6 years ago

err sorry meant @jongacnik

jongacnik commented 6 years ago

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

jondashkyle commented 6 years ago

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.

s3ththompson commented 6 years ago

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

👍