Perspective Mouse Click & Drag

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?

Here are some screenshots of the component:

Thanks for any help,
Keith G.

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.

	Arguments:
		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
			               was fired.
			button (int | float): The button number that was pressed when the
			                      event was fired.
			buttons (int | float): The buttons being depressed when the event
			                       was fired.
			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
			                was fired.
			metaKey (bool): True if the 'meta' key was held down when the event
			                was fired.
			pageX (int | float): The X coordinate relative to the whole
			                     document.
			pageY (int | float): The Y coordinate relative to the whole
			                     document.
			screenX (int | float): The X coordinate in global (screen)
			                       coordinates.
			screenY (int | float): The Y coordinate in global (screen)
			                       coordinates.
			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!

1 Like

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.

1 Like

Your recommendation/warning is unclear. What causes a problem in what situation?

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.

Not through the property editor, no, not to my knowledge, but looking at some items online leads me to believe it’s a simple feature.

1 Like

https://inductiveautomation.canny.io/ignition-features-and-ideas/p/ability-to-disable-drag-and-drop-on-perspective-images

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.

Here is an example I mocked up in Vision
com-video-to-gif%20(1)

Thanks for any help!

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.

2 Likes

Thanks for the quick response Cody!

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?

It’s going to require some clever property manipulation:

You’ll need to set up a set of custom properties like so (onInstanceClick will need to write the index and position values):

instance: {
    index: 0,
    position: {
        left: 0px,
        top: 0px
    }
}
mouseDown: false
page: {
    left: 0px
    top: 0px
}
delta: {
    x: 0,
    y: 0
}

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.

3 Likes

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.

Any ideas?

I’ll need to think about that for a bit.

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.

1 Like

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?

Here is an export of my view if that helps

ClickAndDragTest.zip (4.6 KB)

Also this would be fantastic, Here is the ideas post!

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

{custom.original.instanceLeft} + {custom.delta.x}
1 Like

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.

However, here is a working version incase anyone needs it!
PerspectiveClickAndDragComponents.zip (5.0 KB)

com-video-to-gif%20(2)

10 Likes

Hi
Does this work smooth over slow internet connection? All mouse position should be send to server and back to client.
Do you get response movement?

Unfortunately I havent tested it over a slow internet connection so I am not sure

Everything should be there to spin up a project in your own environment and test it out though

1 Like