Easily make a swipe-able image carousel

@West , @skar

Here’s my latest, it uses @JakAttak’s circle mesh as suggested to make all the dots into preview images.

It also uses the radius-size-clamping code as suggested, but tweaked a little to make the dots smaller.

It’s got some problems: the dots are off-center now, I don’t know why, and the dot tapping is super broken.

there’s a problem in this project that the “x” position is not correct
141: local x,y = WIDTH/2-s+i*50,75 idk what the math here is supposed to be but it’s not the correct positions of the dots

so i’ve been thinking a lot about touch and how it works
basically the x,y is tied to the screen, so you have to figure out if your object that you want to respond to touch falls into the x,y and having to loop through every object can get huge since it’s O(n)

so one thing i was thinking that would be unconventional but probably way easier is to add a circle physics body that is just a sensor behind every dot and then do a raycast on touch, i think that’s much easier and less performance intensive, i’m going to try it eventually but maybe you guys can try it out of it have the time

I don’t understand how the fancy sizing thing works so I tried to do it my own dumb way and it doesn’t work either:


    local sidePadding = WIDTH / 20
    local totalSpaceForDots = WIDTH - (sidePadding * 2)
    local spacePerDot = totalSpaceForDots / #self.images
    local calculatedSize = spacePerDot * 0.85
    local maxDotSize = WIDTH / 30
    if calculatedSize < maxDotSize then
        dotRadius = calculatedSize
        else
        dotRadius = maxDotSize
    end
    dotRadius = dotRadius * 0.75 --ugh why do I even need this
    -- but withkut it the dots are way too big

Without the multiplier at the end the dots are way too big and I don’t know why.

About the dot-tapping, the code as is worked with the default dots in @Dwins’s code, and in fact it still works, it’s just that the tappable areas are not aligned with the dots correctly. So rather than implementing an entirely new system I’d like to just figure out how to re-align the tap spots.

The problem is I just have no idea where in the touched(touch) function it’s detecting those taps. Honestly almost all the touched(touch) function is way beyond my ability to decipher. I can tell it must be in the part for touch.state == ENDED, but not much more than that.

@West , @skar

I think I got the dot-tapping working.

The only two things bugging me now are the size calculations and the fuzziness of the white circle around the current page—why is it so fuzzy?

Also I made a new icon because the old one didn’t show our nice new preview dots.

Also also the Carousel class has been renamed ImageCarousel, and moved to a separate tab so it can be used as a dependency if desired.

@UberGoober Here is a cleaned up version which now (hopefully) clarifies the size calculations of the dots and also allows you to limit the span of the thumbnail.

I’m not sure what you mean about the fuzzyness- is it the slight antialiasing effect on the circle?

I’ve also tidied up the touch code from main - not sure what was going on there before but when the main touch function is called it is just a case of calling the carousel touch code.

@West, that’s great work! Your clarification is very helpful for a slow-at-math type like me.

I made a few aesthetic tweaks and a bug fix and one feature addition.

  • the feature is an optional Boolean used when initializing the carousel that tells it whether or not to use thumbnails in the dots. Useful when there are too many dots and they’re very small, in which case the whole effect is ruined, or when you just don’t want thumbnails for whatever reason.

  • the bug fix is a tweak to the calculation of s in the dot-drawing section. You’d done an efficient simplification of the calculation but I think you removed a slight adjustment that resulted in them looking off-center at some sizes. I don’t think this was a mistake on your part, because it wasn’t noticeable that all until I started adjusting the sizes of the dots. It wouldn’t even have seemed like a bug before then.

  • when not using thumbnails, the maximum dot size is dramatically smaller, more in keeping with their general size in carousels

  • when using thumbnails, I made the dot size, the overall dot space width, and the maximum dot size larger, so it’s easier to see the images on them.

  • otoh I made the selected-dot size smaller, because when using thumbnails I think the combination of the white outline and the size bump makes it easy enough to tell which one is selected, and when not using them it looks odd for the size to bump up too dramatically.

  • speaking of which I slightly narrowed the white outline. I would have preferred to make it thinner in landscape, but that makes it too thin in portrait, so I think I chose a happy medium.

  • I modified the version numbering in the title to follow the “major update/minor update” tradition :wink:

…oh and yes, by “fuzziness” I meant the anti-aliasing. I wish the ellipses were crisper, but it’s not a big deal.

@West, @skar :

I think this is a cool addition but I can only get it working 90%.

I thought I would be neat you could have multiple image carousels in different places on screen.

As you’ll see, it’s working, but with one teeny weeny massive problem.

@Ubergoober I don’t think multiple instances will work out of the box - and it’s not a simple fix. There are issues if you start allowing the individual images to have different widths and heights. I would probably look at an alternative way of rendering the image - probably be using image copy with x percentage of one image on 100%-x% of the neighbouring image. I think it’s probably run its course at the current feature set.

@West have you run the project I attached?

It seems to work swimmingly except for the issue of drawing the images to the left and right.

If I could hide the “off-screen” images, I think it would be working perfectly, or close to it.

@UberGoober Yes - and there are a few issues with it. On iPad the circle thumbnails are bunched, the current image thumbnail isn’t scaled up (caused by non-square images). Touching the thumbnail bar no longer works. There is bleed across to the full strip (as you’ve mentioned). Bottom carousel only responds to touches on certain parts of it.

Happily resolving the offscreen images could be simply solved by using the clip command. Here is a simple example of it in action:


function setup()
  parameter.number("splitpoint",0,1,0.5)
  srcimg1=readImage(asset.builtin.Blocks.Brick_Grey)
  srcimg2=readImage(asset.builtin.Blocks.Cactus_Inside)
end

function draw()
  background(57, 9, 252)
  strokeWidth(5)
  destsize=400
  clip(WIDTH/2-destsize/2,HEIGHT/2-destsize/2,destsize,destsize)
  sprite(srcimg1,WIDTH/2-splitpoint*destsize,HEIGHT/2,destsize,destsize)
  sprite(srcimg2,WIDTH/2-splitpoint*destsize+destsize,HEIGHT/2,destsize,destsize)
  clip()
end

And I looked at the image copy approach that I’d suggested previously- not going to be a viable solution as you run into problems with being restricted to whole pixels which leads to non-smooth transitions

@West You can get at the half pixels using rawget and rawset . Of course that only works for images that have the half pixels.

@dave1707 not come across those commands before - thanks. Was exploring the image copy function to grab the left/right hand portions of two images, but it didn’t really work out - pasting two images and clipping is much more straightforward (and closer to the original approach)

@West Are you just trying to resize an image. Not clear by reading all the above discussions.

@West This version has four carousels, of differing sizes and positions, and as far as I can tell they all work great.

I think even the dots work pretty good now, and you can also now configure a carousel to have no dots at all.

I think you’re right that there’s not much more to do with this, but it does seem to me that this last feature is working just fine.

@UberGoober looks good. I think there is a difference in expectations though. I was thinking a set thumbnails would be associated with each carousel regardless of size and position whereas you have constrained it to only if the carousel is the width of the screen (regardless of starting x position) and the thumbnails will appear in same position regardless of the number of valid instances.

For example having two full width carousels stacked vertically both full width.


    imgCarousel = ImageCarousel(images, true,0,0,WIDTH,HEIGHT/4)
  imgCarousel2 = ImageCarousel(images2, true,0,HEIGHT*0.7,WIDTH,HEIGHT/4)

Thumbnails are wrong for one of the carousels.

The “only show thumbnails if full width” constraint seems excessively strict - what happens if I wanted to use this at nearly full width - say 98% but have a small surrounding border?

@West I updated my previous post a little while after first posting. I think I figured out the whole dots problem anyway and you can now have dots or not no matter the size or position of the carousel. The link above should download this version now, if it doesn’t please let me know.

@UberGoober the version you posted above (1.5) will always draw the thumbnails in the same y position, 75 pixels up from the bottom of the screen and they will always be in the spread around the centre of the screen (WIDTH/2). If you’ve changed this, then these changes haven’t shown in the code you posted.


            translate(WIDTH/2-s+i*spacingConstant,75)

@West you’re right, it didn’t update for some reason.

I just edited it, re-attached the up-to-date version, and then downloaded it from that post again to be sure it’s the right one.

It should be right now. Also it now draws non-thumbnail dots at a consistent size no matter what size the carousel is, to more closely match standard iOS behavior.

@UberGoober works great now! Good job!