Is it possible to restrict an Angular Drag and Drop element to a circular boundary?
Looking at the documentation below
Restricting movement within an element
If you want to stop the user from being able to drag a cdkDrag element outside of another element, you can pass a CSS selector to the cdkDragBoundary attribute. The attribute works by accepting a selector and looking up the DOM until it finds an element that matches it. If a match is found, it'll be used as the boundary outside of which the element can't be dragged. cdkDragBoundary can also be used when cdkDrag is placed inside a cdkDropList.
I tried changing the css (see stackblitz) to be circular but my understanding from the result is this only changes the appearance and not the boundary of the DOM element.
With everything in the DOM essentially being a rectangle does this mean circular or very close to a circle restriction is not possible?
https://stackblitz.com/edit/angular-gughvc
As far as I can tell, there's no direct way to do what you want.
However, you could probably monitor the drag, do a "hit test" for your circular boundary, and stop the drag yourself when the boundary is exceeded.
I did a quick-and-dirty test at https://stackblitz.com/edit/angular-ut9fgz
This stops the drag at the mid-point of the circle, but:
It doesn't just prohibit going past the boundary, it cancels the
drag.
Having a callback for every drag event (essentially every pixel
traversed) can be expensive - your "hit test" better be very
efficient.
So, this shows the general concept, but there's still a lot left to be worked out.
Besides the official documentation, the following pages might be helpful:
https://grokonez.com/frontend/angular/angular-7/angular-7-drag-and-drop-example-angular-material-cdk
Cancel drag on key press Angular cdk Drag and Drop
Related
I have a calendar-like view that shows a table with one column per day of the week (see this image). Each row represents a specific thing that can be booked for a time. The idea is now that a booking can be extended by dragging the outer edge to the next day in the table, or shortened the same way. The active booking has a span on each side of the cell that is supposed to be the handle for dragging.
My main problem now is that the usual drag & drop features in browsers don't seem to fit my situation. I don't want to drag something and drop it anywhere else, I just want to drag to extend the item.
Is this still something that can be done with the usual HTML5 drag&drop feature or some generic drag&drop library? Or is there any other way to achieve this? Any pointers on how to approach this problem?
I'm using React for this, which might make some solutions difficult to integrate if they manipulate the DOM directly.
ummm not sure what to do here , I thinks its unlikely the link will change soon , I can describe the repo 'Allows individual or group selection of items using the mouse. Click and drag to lasso multiple items, hold the cmd/ctrl key to select non-adjacent items'. I can briefly describe what the lib code does: uses keydown, keyup and mousedown listeners to create an overlay and detect covered nodes in the DOM .
Pure JavaScript (no JQuery, D3, or other external libraries). I'm dragging SVG objects that look like columns of rectangles around. They have connecting lines between the rectangles, and when I drag one rectangle across another, I remove all elements from the DOM, check whether each rectangle in a column corresponds to a rectangle in neighboring column, and draw a new connecting line between them if that condition is true. In the console I can see that the elements are created immediately, but they aren't rendered until I release the mouse and stop the drag. Because I may drag across more than one column and need to compare the results at each position before deciding where to drop, I need to force the new elements not just to be created immediately, but also to be rendered immediately, without being blocked until I release the mouse.
[Edit: In response for downvote for "not showing research," note the following (original) paragraph. Tried all suggestions I could find, mentioning the most common ones explicitly. Perhaps my research methods are unsophisticated; can you advise so that I could do a better job next time?]
Following suggestions on this site and elsewhere, I've tried adding and deleting an element from the DOM and toggling the display property of various elements, but without success.
Sample files are at https://github.com/obdurodon/drag. To run, clone and then open textual_correspondence_static_sample/test.xhtml in a browser (from the file system, so that it can find the CSS and JavaScript files to which it's linked). Grab a drag icon at the top of a column and pull left or right. Connecting lines repaint only on drop, but I need them to repaint immediately after every crossing (I'll worry about stretching them on mousemove later).
I think the reason is because you are giving the lines a stroke colour in endMove() (after your drawLines() call). But you are not doing that in the swapColumns() function. New elements in SVG have no stroke by default.
I have made a small app that allows the user to create rectangles, and drag them around.
The implementational details are that the "green" workspace area you see is a Marionette CollectionView
and when you are drawing boxes, you're essentially instantiating new rectangle models and rendering views for them. HTML-wise, the rectangles are child nodes of #workspace.
Here's a working demo (on dropbox since jsfiddle keeps failing me all the time)
From what I know,in order to avoid the creation of a new rectangle while I'm moving around an already existing one, I need to stopPropagation of the mousedown/mousemove/mouseup events (That's what I'm using in the first place to determine if the user is dragging, to acquire mouse pointer position, calculate rectangle properties, and append the rectangle view on mouseup)
The problem is that although I stopPropagation for mousedown/mousemove/mouseup, apparently the mouseup event doesn't fire and the rectangle keeps following the cursor even after the mouse button has been released.
Also dragging a rectangle around is not as smooth as I would expect, but a bit glitchy. I'm suspecting that there must be either something horrible that I've done (most likely), or a conflict between how I'm handling events and how jQuery and jQuery UI are. (I need to comply, but I don't know how).
Please enlighten me!
In the end I've decided to write a short jQuery UI plugin that would take care of all the calculations and would allow me better control over event handling.
For more information about what I ended up doing check this post
I'm trying to pick up mouse events for svg:text elements. What I noticed is that .on("click", ...) works, but other events like "mouseover", "mousemove", and "mouseout" don't.
Looking at the Health & Wealth of Nations example, I see that the approach taken was to overlay the text with an invisible svg:rect and assign it the events instead. This is fine if there's one simple box, but if there are several it seems it would become tiresome and messy.
Is there a canonical way to handle mouse hover events for text?
For the sake of being as specific as possible, I'm trying to have a tag cloud and pick up on these hover events for each of the tags. I could probably just do it with divs and be done with it, but I'm wondering if there's an easy way to do it within an SVG container.
I suppose the problem with assigning events to the text elements is that they only fire on the actual text, i.e. not the bounding box. In theory it should work though (at least I'm not aware of any special handling of text in this respect) -- can you give a concrete example where it doesn't?
You could also try putting each text element inside an svg:g element and attaching the event handler to that.
This is related to SVG, I have a large SVG object made of paths which stays static. With a press of a button, I can create another SVG object inside the larger object. The second object can be dragged with the mousedown.
PROBLEM:
Now I want to add a restriction so that the second object created cannot venture outside of the main object.
I tried using 'mouseup' for restriction but that does not work because the restriction is applied according to the cursor point on the second object, rather than the border of the second object.
Hope someone can help.
UPDATE:
#Phrogz : We have been trying to get Kevin's code to work but are struggling to get any results. We have a function attached to onmouseup to find out the intersected points of the object on the underneath path.
The function is suppose to give the results of the intersection & give an alert that the function has been exected. Its not giving anything in response, leading us to wonder whether the function is being executed at all.
Here is the main code:
var path=svgDoc.getElementById("path");
var str=intersectPathShape(path,DragTarget);
alert(str)
Phrogz, any thoughts on this?
You will need to use an intersection library like this one by Kevin Lindsey to detect when the paths overlap and prevent it. (He also provides demos of his code.)
Depending on how you implement your dragging, you may also need to check the bounding box of the two items to ensure that one is contained in the other (since dragging the child completely outside the parent would cause them not to intersect, but also not be a legal position).
The simplest code would be to store the last position of the child and return it to that position when an intersection is detected. Under fast dragging, though, this might cause the child to stop being dragged at a spot that is not actually touching. For a better user experience, you may want to try a binary search of intermediary offsets between the last known-good position and the current position to find the closest point along that path that is legal.
Kayote,
I think I answered this in another question. The short version is have a look at this github project:
https://github.com/thelonious/js-intersections
In particular, the loadShapes function in this file:
https://github.com/thelonious/js-intersections/blob/master/samples/IntersectionUtilities.js
You will need to instantiate a specific object per node type then pass those to Intersection.intersectShapes.
HTH,
Kevin