Share Posted June 15, 2016 I keep getting a lot of questions asking about creating sortable lists with Draggable, so I'm just going to make a post about it. My See the Pen RNLdpz by osublake (@osublake) on CodePen example is outdated, and I no longer use that technique, so I'm not going to update it. It relies on hit testing, which I would no longer recommend doing for grids/lists. A better way is to create a model of your list, and map the location of your draggable to that model. This is real easy to do using arrays. You can use the index of an array to represent a cell location in the grid. Draggable already creates an array for you if you use the .create() method, so you could use that if you really wanted to. But first you need to figure out the size of the cells in your list. If everything is uniform, you could probably just divide the size by the number of items in that dimension. If my list is 400px high, and there are 4 elements, the cell size for a row is 100. Notice how the cell size may not be the same size as your element. The cells are in red. When you drag, you can figure out the index of a cell like this. var index = Math.round(this.y / rowSize); This can result in errors if you drag outside of your list, so you should clamp the values like this. var index = clamp(Math.round(this.y / rowSize), 0, totalRows - 1); function clamp(value, a, { return value < a ? a : (value > b ? b : value); } Now you can easily determine where everything is. You also need to keep track of the last index, and compare it to the index you calculate while dragging. If they are different, this means your draggable is inside a different cell, so you need to update your layout. Before you can change the layout, your first need to change the items in your array. Here's a function you can use to move stuff around in an array. arrayMove(myArray, oldIndex, newIndex); function arrayMove(array, from, to) { array.splice(to, 0, array.splice(from, 1)[0]); } Now that your array is in the correct order, you can update the layout. If you were using an array of draggables, you could animate the entire layout like this. myArray.forEach((draggable, index) => { if (!draggable.isDragging) { TweenLite.to(draggable.target, 0.4, { y: index * rowSize }); } }); That's pretty much it! Doing it this way is not only easier, but it performs a lot better, making it really smooth. I made a demo based off of this Framer.js example. It's about 100 lines of code, and is pretty easy to understand. For comparison, The Framer.js example is about 180 lines of code. See the Pen jrqjdy by osublake (@osublake) on CodePen 10 Link to comment Share on other sites More sharing options...
Share Posted June 15, 2016 That is great Blake! I just wanted to take a moment and thank you for hanging out here on the forum. I can honestly say I've learned just as much (if not more) by reading your posts and deconstructing your pens than I have by reading books and viewing online tutorials. You are truly an amazingly talented coding rock star and we're lucky to have you as an inspirational teacher around here. Thank you Blake. 7 Link to comment Share on other sites More sharing options...
Share Posted June 15, 2016 Yeah, great stuff Blake. Thanks for sharing this. Link to comment Share on other sites More sharing options...
Author Share Posted June 20, 2016 Thanks PointC! That's how I learn any new concept. I find something interesting, and deconstruct the code line-by-line. This is pretty much the only book you'll ever need. 4 Link to comment Share on other sites More sharing options...
Author Share Posted June 20, 2016 I should add that converting a list to a grid is real easy. First, map the cell locations to an array. var cells = []; for (var row = 0; row < totalRows; row++) { for (var col = 0; col < totalCols; col++) { cells.push({ x: col * colSize, y: row * rowSize }); } } Now modify the drag method to find the index of a cell. var col = clamp(Math.round(this.x / colSize), 0, totalCols - 1); var row = clamp(Math.round(this.y / rowSize), 0, totalRows - 1); var index = totalCols * row + col; Now you can easily layout the grid using the saved cell locations. Everything else is pretty much the same! See the Pen NrRJwm by osublake (@osublake) on CodePen 6 Link to comment Share on other sites More sharing options...
Share Posted June 21, 2016 Blake... I WANT YOUR CHILDREN! Think of the possibilities of such talented DNA. 3 Link to comment Share on other sites More sharing options...
Author Share Posted June 22, 2016 That's actually not a bad idea. Do you know any filmmakers? I'd like to document the process. 1 Link to comment Share on other sites More sharing options...
Share Posted June 22, 2016 I know this lot: 6 Link to comment Share on other sites More sharing options...
Share Posted June 22, 2016 Pedro, I've never been so extremely horrified yet equally humored at the same time. 3 Link to comment Share on other sites More sharing options...
Share Posted June 22, 2016 He's the one who wants to film it. I'm not so keen in this new ideas the youngster have but hey, Blake's calling the shots on this one. 1 Link to comment Share on other sites More sharing options...
Share Posted June 22, 2016 This thread has taken an unusual turn. What is happening here? I'm amused and confused. I'll be in my lab inventing a time travel machine so I can somehow warn myself not to look at that picture. Link to comment Share on other sites More sharing options...
Author Share Posted June 22, 2016 I'm framing that!!! On a side note, somebody suggested swapping positions vertically. Another easy modification. Instead of shifting the array around, you can swap positions in the array like this... var temp = sortables[to]; sortables[to] = item; sortables[item.index] = temp; I changed it so that it will use the swap method if the new position is adjacent to the last position. See the Pen NrRJwm by osublake (@osublake) on CodePen 2 Link to comment Share on other sites More sharing options...
Share Posted September 4, 2016 Pretty cool stuff. I used this demo to created a few connected lists. Check it out See the Pen mAyyQP by joelcoxokc (@joelcoxokc) on CodePen 5 Link to comment Share on other sites More sharing options...
Author Share Posted September 4, 2016 That's awesome! And thanks for sharing this. We get a lot of request asking how to make drag and drop containers, but I haven't had to time make another version, so this is perfect. 1 Link to comment Share on other sites More sharing options...
Share Posted September 5, 2016 JoelCox, Very nice! Thanks for sharing. Link to comment Share on other sites More sharing options...
Share Posted September 19, 2016 I am trying to set a bounds to the example you have done @OSUBlake, however it seems that I can't apply a bounds? If I do that, when I start dragging, the element will jump to a odd spot instantly? The reason I am looking at applying bounds is so that I can do things like: throwProps: true, edgeResistance: 0.9, overshootTolerance: 0.1, maxDuration: 0.2, I don't want the draggable element to be able to drag to where ever but contained within an area with momentum applied. Updates* Ah, I tried again and it seems to work (: Link to comment Share on other sites More sharing options...
Author Share Posted September 21, 2016 It should be just as simple as defining the bounds on the Draggable. bounds: ".container" See the Pen 732069136a5b69e3e985c667345aad4a by osublake (@osublake) on CodePen Can you make of demo of what you're trying? There are other ways of handling the bounds if needed. 1 Link to comment Share on other sites More sharing options...
Share Posted October 6, 2016 Hello guys! Exist any example with Angular 1.x using directives? I want to do that See the Pen jrqjdy by osublake (@osublake) on CodePen but using Ionic Framework. Using Ionic list component <ion-list> <ion-item draggable ng-repeat="item in items"> Hello, {{item}}! </ion-item> </ion-list> And using Angular directives => app.directive('draggable', ['$ionicGesture', function ($ionicGesture) { return { restrict: 'A', link: function (scope, element, attrs) { //Ionic list var container = element.parent()[0]; var animation = TweenLite.to(element, 0.3, { boxShadow: "rgba(0,0,0,0.2) 0px 16px 32px 0px", force3D: true, scale: 1.1, paused: true }); var dragger = new Draggable(element, { onPress: onPress, onDragStart: downAction, onRelease: upAction, onDrag: dragAction, cursor: "inherit", type: "y" }); //Any example please? } } }]); With the following code doesn't work well => https://gist.github.com/jdnichollsc/4c1ae672bfbad6bc364aa42f4dacd38e And other PoC in Codepen See the Pen kkvpwb?editors=1010 by jdnichollsc (@jdnichollsc) on CodePen Thanks in advance, Nicholls Link to comment Share on other sites More sharing options...
Share Posted October 6, 2016 Hi guys! Check my last PoC See the Pen WGdaVQ?editors=0010 by jdnichollsc (@jdnichollsc) on CodePen But I want to move the other items while is scrolling mmm Regards, Nicholls Link to comment Share on other sites More sharing options...
Author Share Posted October 6, 2016 Hi jdnichollsc, It looks you're off to a good start. I'm going to come back and look at this in more detail later today, but for now try adding autoScroll to your Draggable instance. dragger = new Draggable(element, { autoScroll: 1, ... }); BTW, I really like all the work you've done with Ionic, Angular, and Phaser. It's really impressive! 2 Link to comment Share on other sites More sharing options...
Share Posted October 6, 2016 Hi jdnichollsc, It looks you're off to a good start. I'm going to come back and look at this in more detail later today, but for now try adding autoScroll to your Draggable instance. dragger = new Draggable(element, { autoScroll: 1, ... }); BTW, I really like all the work you've done with Ionic, Angular, and Phaser. It's really impressive! Wowwww is beautiful!! Thanks for your examples! Check the repo with the last fix https://jdnichollsc.github.io/Ionic-Drag-and-Drop/ What do you think? Regards, Nicholls Link to comment Share on other sites More sharing options...
Share Posted October 7, 2016 Hi guys! Any tips to improve the performance on Android? If you want, check please the repo and let me know your comments https://github.com/jdnichollsc/Ionic-Drag-and-Drop/blob/master/app/js/directives/draggable.js PD: GSAP should create components for Ionic 1 and 2... Regards, Nicholls Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now