I am building a photoshop like color picker in my perspective application, and I have done some fancy math to determine where in a color gradient the user clicks, and calculate the color code accordingly. I even added a cursor Icon, to make it more clear where they have clicked.
However I am looking to make it so they can “grab” the cursor and drag it around, or at least if they hold their mouse down it will bring the cursor with it.
Is there anyway to detect where the mouse is at if it is clicked and dragged while on top of a component?
There are properties to provide the location within the scope of the page, the client, or the screen:
def runAction(self, event):
Method that will run whenever the selected event fires.
self: A reference to the component that is invoking this function.
event: Events fired by the relevant mouse/touch interaction.
altKey (bool): True if the 'alt' key was held down when the event
button (int | float): The button number that was pressed when the
event was fired.
buttons (int | float): The buttons being depressed when the event
clientX (int | float): The X coordinate in local coordinates.
clientY (int | float): The Y coordinate in local coordinates.
ctrlKey (bool): True if the 'ctrl' key was held down when the event
metaKey (bool): True if the 'meta' key was held down when the event
pageX (int | float): The X coordinate relative to the whole
pageY (int | float): The Y coordinate relative to the whole
screenX (int | float): The X coordinate in global (screen)
screenY (int | float): The Y coordinate in global (screen)
shiftKey (bool): True if the 'shift' key was held down when the
event was fired.
These are available for onClick, onMouseMove, and onMouseUp.
I’m pretty sure these properties are available for >8.0.0 (but don’t quote me) though they weren’t made visible in the docstring until 8.0.4.
Thanks Cody, I am actually using several of those current functions right now, but the “clientX” and “clientY” values don’t change if the mouse is held and repositioned (Or maybe I am using them wrong). I am trying to figure out how monitor the mouse location as it is held down and moved across the component.
EDIT: I just now saw the “onMouseMove” part, that actually should give me what I need. Thanks Cody!
A further note to this for anyone else who needs to accomplish something similar, to avoid the “onDrag” event for the image component, of you place a label over the whole thing that it won’t happen and you can click and drag.
The background image for the colorpicker is just an Image component, trying to implement the “Click and drag” functionality to adjust the currently selected image, highlighted that it automatically tried to “Click and Drag” the image itself (As if you were trying to drag and drop it somewhere).
This warning was a way to ignore the “Drag and Drop” functionality of the image component, not sure if there is a setting to disable that.
Hey, I know this is a bit old, but I am revisiting it for a different task.
The properties you mention here on the event object do not seem to have any way of determining their position within the view itself. I.e. the pageX and clientX can only give you the X position over the entire page, and not within the specific view of the item being clicked on. Do you know of a way to do that?
I am trying to accomplish something like this, but am unable to figure out a way to do it with the properties you mentioned.
If you want something like that you’ll need to switch over to using the View Canvas. The View Canvas is essentially a relatively new component (which didn’t exist when we originally started this thread. It exposes the positioning of each instance within the View Canvas itself. By using the onInstanceClicked Event, you can move the logic into the View Canvas and out of the individual component - or you can still use external components to modify the instance.
I spun something up to test this out, however I have found that the event.position[“left”] and event.position[“top”] properties are only referencing the value that the instance is sitting at, and do not track mouse movement at all.
Any ideas on how to include the dragging of the component into this?
You need to use onMouseDown to set the page object properties.
In the event mouseDown is true, then onMouseMove needs to update the deltaX and deltaY appropriately, where they describe the difference between the original click position and the distance dragged.
Place a Change Script on mouseDown which resets ALL of the other properties to their default values is mouseDown is false.
onMouseUp AND onMouseLeave need to set mouseDown to false.
Bind instance.position.top to delta.y.
Place a change script on instance.position (the object), which sets the position of the instance by using the index property.
So I think I have most of this working, however the onInstanceClicked script does not run until AFTER the onMouseUp event, and so the index does not get set in time to reference it in the instance.position change script.
Ah, yah, what that component really needs is onInstanceMouseDown for an Event, along with an accompanying onInstanceMouseUp. It looks like for now there is not a way to get the mouseDown or click location within the View.
So, I managed to accomplish this with a mouseOver event on the embedded view, that changes an output parameter called mouseOver and then I call a messageHandler to check for any instances where mouseOver = True. That allows me to get my index value before I start moving, and it works great when moving from 0,0!
However, whenever I click the item again, the delta goes to 0, 0 and the instance moves to 0,0 with it (because of the script on the instances.position custom property), any idea what could be causing this?
I feel like maybe I am missing something when changing my instance position, as if maybe it should be the delta from its starting position and not just its current position?
Ah, there needs to be a sort of go-between variable which registers the initial original.instanceLeft and original.instanceTop. These values should not change during the drag, but they should be used to define the new position. So custom.instance.position.left should be expression bound to
I think we have a winner! It is not perfect, I think because of having to use the messagehandlers and timing, and with an onInstanceMouseDown and onInstanceMouseUp would really smooth that out. That would also eliminate the need to have the messageHandlers and output parameter too, making it a much smoother design.