is there a good way to make the container div expand to the left and top when a draggable is dragged outside of its borders?
When you drag to the right or down the container div is properly extended, and scrollbars appear as needed. Yet moving to left or top means that the draggable items has negative top / left position, so the container is not expanded.
Here's a fiddle that demonstrates the existing dragging behaviour: http://jsfiddle.net/NPC42/Un23w/1/, but this can also be seen on the official jQueryUI demos too (http://jqueryui.com/demos/draggable/#default).
I'd like to be able to expand to the top / left too :)
A brute-force approach would be to:
Reset all of the object's positions on the container div to that no negative top / left is required (including the object being dragged).
Change the scrolling position to make it look as if the objects are still on their spots.
But for many objects in the container this could cause a lot of flicker, or even slowdown, so I don't really want to go in that direction. Any suggestions are welcome!
The problem is that every html element has an absolute (0,0) origin coordinate in the top left corner. When you drag in that direction the coordinates for the dragable become negative. However the scrollbars can not become negative, their size can only grow in a positive direction.
I can imagine a custom scrollbars widget that can adjust in a negative direction when you drag below (0,0). Also try having a container inside of another container with the inner one move around so that all of the objects inside it don't have to be individually moved. I don't know of any in existence as it would be kinda weird to have a negative scroll offset.
Related
Does anyone know how to do something like that?
I would like to get a continuous scrolling of the image.
Example: https://vimeo.com/262632459
Here is a simple way of doing it.
Set it up
Create the image you want to scroll in the background. You need to make it minimum as wide as the widest screen you want to support.
Place two instances of the image you created next to each other inside a regular UIView.
Place the view on the screen with the x position at 0.
Animate
Animate the view repeatedly forever, moving the x position from 0 to -width. The width is the width of your image (just the width of one instance). Note that since you want to pull the view left, you must pull x in the negative direction.
The image will now slide left until the second instance x is at 0. At this position the animation will start over, moving the view one whole image size to the left. This movement will not be noticeable since you use two identical images.
You need to use scrollview or subclass of scrollview and in that scrollview add your image you want to scroll.
override scrollViewDidScroll delegate method of scrollview, here you can control the animation (how much user can scroll or other behaviours)
https://developer.apple.com/documentation/uikit/uiscrollviewdelegate/1619392-scrollviewdidscroll?language=objc
And if you want circular image(when image reach to last start again) add two copy of same image, One at zero position, before your acutal image and one at last position after actual image and as soon as image reaches to last remove the font image and add in the last, and if user scrolling in right direction remove the last image and add in front.
In scrollview add three imageview and keep adding and removing from the front and last based on the scroll direction. In scrollViewDidScroll you will get direction of scoll based on change in x value
I'm using Constraints within my app and have have a reasonable level of success so far; everything visual object in the gif below is Constrained.
The issue is that when selected, tiles leap to another location before animating to the final, correct destination.
From a code perspective, on a tile click, higher priority positioning Constraints are applied to the tile, the tile is added as a subview to the blue area, then animation is performed.
Can anyone shed a little light on what's happening here?
Thanks
Based on the behavior I'm seeing in your gif, I would guess that when you move the tile views between superviews (the blue area vs. the larger white area), the view jumps to it's current frame position (within the coordinate system of the old superview), but now in the coordinate system of the new superview.
The solution, I think, would be to translate the final position in the new superview to a position in the current superview, perform the animation, and only when the animation completes would you move the view to it's new superview.
Does that make sense?
I'm trying to have an image inside a div of same width to be draggable in the limit of the div. It's difficult to explain but one side of the image (top or bottom) can leave the div but you cannot have a gap between the edge of the image and the border of the div.
To resume the image has the same width of the parent div but its height is bigger so a part of the image is hidden.
Well here is what I want to do:
http://jsfiddle.net/maxwell2022/DerNa/165/
It's working perfectly... because there is nothing above the div. If there is a gap between the document and the div, it's not working anymore. I think Draggable is taking the document as reference for the top of the image. As soon as you start dragging the image, the image move and stuck its top edge to the top of the document:
http://jsfiddle.net/maxwell2022/DerNa/164/
I don't know how I can achieve this with the containment option.
Cheers,
Maxime
UPDATE
Another attempt with relative positioning but no luck: http://jsfiddle.net/maxwell2022/DerNa/166/
I found a solution to fix it getting the top position of the parent div using offset() and add it to the containment boundary. I'm not sure it's the best solution but it looks like it's working.
I just have a difference of 1% in the offset at the top which is quite annoying: if you drag the image and make it stick to the top as much as possible it returns 99% offset instead of 100% (see the result in the console).
The bottom one is correct (0%). I think it's due to rounding the size but I'm not sure.
Here is the jsfiddle: http://jsfiddle.net/maxwell2022/DerNa/167/
If you have a better idea please, please, let me know.
Thanks, Maxime
Backstory
I have an iPad app that needs to allow the user to navigate through groups of images. Each group is laid out in its own vertical UIScrollView (paged) so the user can swipe up and down down to see each image. Each of the group UIScrollViews is placed in a single (only one exists in the app) outer horizontal UIScrollView (also paged). This works great.... I can swipe up and down to view the images in a group and swipe left and right to go to the next or previous group.
Problem
The problem started when I needed to add zooming for each image. I accomplished this by placing each image inside its own UIScrollView. When the image is zoomed I can pan around the image and when I get to the top or the bottom of the zoomed image the group's vertical UIScrollView pages to the next or previous image as expected. Unfortunately the outer horizontal scrollview will not page to the next group when the image is zoomed and I pan to the leftmost or rightmost edge.
Is there a better(more correct) approach than triple nesting UIScrollViews or can I somehow forward touches to the outer horizontal scrollview?
Any help or suggestions would be greatly appreciated.
hope i'm not too late but I think I have a solution for your problem.
Here you can find an Xcode project demonstrating the scrollview setup you have, your problem and the proposed solution: https://bitbucket.org/reydan/threescrollviews
Basically the solution was to add 1 pixel to the contentSize.width of the vertical scrollviews. This forces the vertical scrollview to scroll a little when you pan to the edge of the zoomed image. It scrolls a little and then continues to the next vertical scrollview.
If you download the project you will see that I've created some scrollviews in the viewDidLoad method. There, I create one horizontal scrollview containing 3 vertical scrollviews, each containing 5 images. Each image is actually incapsulated in a scrollview to enable per-image zooming. In total... triple nested scrollviews.
I've also left some colored borders so that I can easily see how each scrollview scrolls.
the magenta = horizontal scrollview
the white = vertical scrollview
the blue = the image scrollview (the one that contains the image and allows for zooming)
the red = the UIImageView
You will see that I've tagged each image scrollview with value 10. This is used in the implementation of - (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView delegate method where I return nil unless the event came from one of the image scrollviews.
If you have any questions about the project I made feel free to ask.
In the end, I would like to say that this browsing method is a little quirky for me as I sometimes scroll in the unwanted direction. Often I think I flick my finger vertically only to find the scrollview going left or right because it interpreted some tiny horizontal movement I had.
The problem I found with paging enabled for both horizontal and vertical movement is that the scrollviews are direction-locked, or so it seemed to me.
EDIT:
Today I've investigated the problem even more. These are my conclusions:
it's not a problem with zooming, it's a problem with having larger content in the innermost scrollview than the visible area(you can try this by zooming or simply initializing the content size larger than the bounds). This enables panning inside the inner-most scrollview and completely changes the behaviour of the touch events.
the bounce for a scrollview flag affects the behaviour of the panning(dragging) gesture when it reaches the edges of the content. If bounces=false then your panning gesture will stop at the edge, not forwarding the drag event up the chain (and thus not scrolling the parent scrollviews to show you other images). If bounces=true then, when you reach the edge and continue to drag the events will be forwarded to the parent scrollview and that scrollview will also be dragged. However, I've found that the dragging while bouncing reduces the distance dragged by aproximately 50%. This also happens in the Photos app.
if you start the dragging while the innermost scrollview is at the edge of the content then the scrollview is smart and will forward all events to the parent scrollview.
for some reason, triple nested scrollviews are problematic as the events are simply not forwarded between the topmost and middle scrollviews while panning inside the innermost scrollview. I have no idea why.
My solution with that +1 pixel to the content size, partially solves the problem.
EDIT 2013
Boy, these scrollviews are something out of this world :(
After more than a year of searching (just kidding... it was actually 2 days) I think I found a good elegant solution to the triple nested scrollviews.
I created a test project here:
https://github.com/reydanro/TripleNestedScrollViews
Inside the app, there is a switch which you can use to test with/without the fix.
The setup I am using in my app is a little different than this question. I have 1 vertical paged scrollview. Inside it, I have multiple horizontal paged scrollviews.
Inside some of the horizontal scrollviews I have another vertical paged scrollview.
Without the fix, once you get to the page with the inner-most scrollview you are pretty much stuck there as the vertical scrolling gestures are not forwarded to the outer-most scroll.
The fix is a custom UIGestureRecognizer that you need to add to the inner-most scrollviews. This recognizer follows touch events and if it detects a drag beyond the contentArea, then it will temporarily disable the rest of the scrollview's recognizers. This is the only method I discovered to make the scrollview forward the events up the chain
The gesture recognizer code is very rough with limited customization but should get the job done. At the moment I am focused on the app I develop, but will continue to update the repository.
PS: I haven't tested what happens with zoom but I see no reason why this method should not work (or be adapted to work).
Basically the same as this question: How to make an infinitely long scroll view on iPhone? but using jQuery Mobile not objective C.
I'm using this plugin: http://jquerymobile.com/test/experiments/scrollview/scrollview-direction.html in particular the example under "Horizontal Scrollview". I want it to loop back on itself so when the user gets to the far right, it will go back to the start and if they scroll left from the start it will go to the end.
I'm not bothered if the solution uses the scrollview plugin in particular or not just that it can have a similar effect.
UPDATE: I eventually did a different way as moving elements to the end or the start of the list seemed flickery with jQuery Mobile scrollview on an iPhone.
What I did was copy all of the li elements within the ul 3 times, so that it was 4 times longer. Then at the start of the script, position the scroll point at the start of the 3rd copy (so the left most point of the screen was exactly half way along the length of the list).
Then whenever the scroll position went beyond the start of the 4th copy, simply move the scroll position back to the middle (offset by how many pixels over it went). Then the same in reverse, triggering it went it went beyond the start of the 2nd copy. Reason I needed 4 copies was so there was a bit of leeway when you scrolled left fast and it went beyond the start of the 2nd copy.
So essentially you want to do something simular to what I did for: http://bbh.co.uk?
The logic is very simple, let's say you have 7 panels, the first thing I did was work out where the 0 point of the movement, that is where the centre of the 7 panels, in this case it's the 4th as we'd have 3 on the left and 3 on the right.
With this 0 point we can then decide where panels will go onces a scroll has occurred, say the user scrolls 2 from the left to the right, this means our 0 point becomes -2, therefore we move two from the right to the front of the left, i.e. we prepend them to the list.
The easiest way to manage it was with an array, since we can .push(), .pop(), .shift() and .unshift() the panels.
Once we had the logic in order we placed each set the CSS position of each panel as absolute and then calculated its position depending on where it was within the array, for example panel 0 would be at 0px left in the container and panel 7 would be at panel.width * 7 and so on.
You then need to make sure that the container is at the centre, that initial 0 point and boom, you've got some infinite scrolling.