What is the operator asking the screen to do?
The request looks simple from the operator side: grab a button, a label, or an image on a running Vision window and slide it somewhere else. Nothing in the component property sheet does that. Vision has no "undock" or "floating" flag for a component. Position is a design-time property, and at runtime a component sits where the Designer left it unless a script changes its location. So the honest answer to "can I drag this without code?" is no. Every workable pattern below is scripting, and the choice between them comes down to what the drag is supposed to accomplish.
The use case that drives most of these requests is a magnifier: a transparent box or magnifying-glass image the operator slides across a plant overview, with a detail region (a conveyor with a dozen bottles, the order data for that stretch of line) refreshing wherever the box sits. The only information that view needs is the box location. That framing matters, because it means you do not actually need to move the original component at all; you need a moving hotspot that reports where it is.
Which approaches can move something on a Vision window at runtime?
Three patterns cover the ground. Each one works; they differ in how much the operator can break, how the window behaves under load, and how much scripting you own afterward.
| Approach | Where the logic lives | What the operator sees | Cost and pitfalls |
|---|---|---|---|
Scripted component move (moveComponent style library on mouse events) |
Mouse event scripts on the component itself, inside the parent window | The actual button/label/image relocates within the window | Component is clipped by its container; overlaps other components; z-order and layout constraints fight the move; hardest to keep tidy |
| Borderless mouseover popup window (pattern used by the Demo project webcam example) | A small separate window, opened without decorations, positioned by script from the pointer or hotspot location | A floating pane that follows the pointer or the dragged hotspot and shows detail for that area | Lightweight; original overview untouched; a few short scripts; the detail content is a normal window with normal bindings |
| Oversized pan/zoom container (a 10000x10000 container holding the full plant overview inside an ~800x600 window) | Zoom/pan logic on the container; pointer drags translate the container | Google-Maps style pan and scan across the whole plant, responsive, effectively unlimited virtual resolution | Every component and binding in the giant container is live whether visible or not; scales the tag-dispatch load, not the drag |
The first approach is the literal reading of the question and the wrong tool for a magnifier. Moving the magnifying-glass image around is not the goal; knowing where it is and rendering detail there is. The second approach delivers exactly that with the least coupling. The third approach is a different feature: it is not a floating component at all but a navigable canvas, and it is worth keeping in the toolbox because it is the one that will eventually hit the performance ceiling described below.
Why is a borderless popup the right pattern for a draggable magnifier?
Two reasons, one architectural and one operational.
Architecturally, a popup window is its own container. Its components, bindings, and layout are independent of the overview underneath. You can size it once, bind its detail image and order-data table to whatever tag or dataset the current hotspot location selects, and never touch the overview's component tree at runtime. A scripted in-window move, by contrast, has to fight the parent container's bounds and any layout constraints applied to sibling components, and the moved component drags its bindings with it while overlapping whatever it lands on.
Operationally, the popup's content only has to represent one region at a time. The overview shows the coarse picture; the popup shows a dozen bottles and their order data for the region under the pointer. That is a handful of bindings that change only when the hotspot crosses into a new region, which is exactly the shape of load Vision handles cheaply. The giant-canvas approach inverts this: it keeps every region's detail live simultaneously so that panning is instantaneous, and it pays for that with continuous tag-change dispatch across the whole plant.
If you already have a working pan/zoom canvas and it feels responsive, keep it for navigation and add the popup on top for detail. They are complementary, not competing.
How do you build the mouseover magnifier?
- Decide the hotspot. Either use the pointer position directly (pure mouseover, as the webcam example does) or place a transparent rectangle or magnifying-glass image on the overview and let the operator drag it. For the dragged variant, put the position update in the component's mouse-drag event script and keep it to arithmetic on the drag delta; that is the only place the
moveComponent-style library belongs. - Map location to region. Convert the hotspot's x/y on the overview into a region identifier (conveyor segment, machine number, or a grid cell). Do this in the same script; it is a lookup or a division, not a tag write.
- Write the region identifier and the screen coordinates to client-scoped tags or window parameters. Client tags keep the selection local to that operator station and cost the Gateway nothing.
- Open the detail window without border decorations, positioned relative to the hotspot. Open it once on the first hover or drag and reposition it on subsequent events; do not open and close it on every pixel of movement.
- Bind the detail window's image and order-data components to the region identifier. Those bindings fire only when the region changes, not while the pointer wanders inside one region.
- Close the detail window when the hotspot leaves the overview or the operator releases and exits, so the popup does not persist over other windows.
# Pattern outline for the dragged hotspot (mouse event scripts on the hotspot component)
# mousePressed : store pointer offset inside the hotspot
# mouseDragged : new x/y = hotspot origin + drag delta (clamped to overview bounds)
# region = lookup(new x, new y)
# write region + x/y to client tags
# if popup not open: open borderless detail window
# else: reposition detail window beside the hotspot
# mouseReleased/mouseExited : optionally close detail window
Keep the hotspot itself binding-free. Its job is to report location; the popup does the rendering.
How many tags and components can one window carry before it drags?
This is the question the giant-canvas approach forces, and the answer is not a hard limit. A Vision window does not fail at some component count. It consumes progressively more of the client machine's resources until tag dispatch backs up.
The mechanism: the client polls the Gateway for tag changes on a fixed scan interval. When a batch of changes arrives, the client dispatches each changed value to every component binding that references it. If dispatching a batch takes longer than the scan interval, the next scan is held up. If the scan stays held up long enough, the client's picture of the tag database is stale enough that the Gateway can no longer send it a diff of changed values and must send a full batch of every subscribed tag. That full batch is larger than any diff, takes longer to dispatch, holds up the following scan further, and the loop compounds. That compounding is the point at which the screen effectively "breaks": it is still running, but the values on it lag reality and the lag grows.
Two variables set where that happens:
| Variable | Effect | Practical reading |
|---|---|---|
| Client machine capability | Sets how many binding updates fit inside one scan interval | Windows with more than 400 tag subscriptions and more than 600 components have run fine; benchmarks did not go higher, so treat that as a known-good floor, not a ceiling |
| Tag change rate | Bindings consume resources only when the bound tag actually changes | 1000 subscribed tags of which 100 change per second is a light window; 1000 tags all changing every second is a heavy one at the same component count |
So "500 tags and 200 objects" or "1000" cannot be answered from the counts alone. A 10000x10000 canvas full of slow-moving status bits costs almost nothing after the initial load; the same canvas full of live analog values updating every scan is where you will find the compounding behavior first. Initial load time is a separate matter, driven mostly by image decoding, and does not feed the dispatch backlog.
Where does the load land: client or Gateway?
Dispatching tag changes to component bindings is client work. The scan, the diff application, and the binding updates all execute in the client JVM on the operator station, so the machine that slows down first is the one the operator is sitting at. The Gateway's share is computing and serving diffs to each subscribed client; that share is small while diffs are small.
The crossover comes with the compounding step. When a client falls far enough behind that the Gateway has to resend full tag batches, the Gateway is now serializing and sending the entire subscription set for that client instead of a handful of changes, and it does so repeatedly while the client stays behind. One overloaded client therefore raises Gateway load as well, and several overloaded clients running the same heavy window raise it together. Fix the client-side backlog and the Gateway-side cost disappears with it.
How do you measure whether the window is keeping up?
The screen will tell you when it is behind, but not until values are visibly stale. Read the number directly instead.
- Confirm the client poll rate. It is an expert-level project property in the Designer; the default is
250 ms. Compute the ideal scan rate as1000 / poll_rate_ms, which is4 scans/secat the default. - Open the heavy window on a representative operator station, not the Designer's development PC.
- Open the client Diagnostics window and read the SQLTags throughput figure, reported in scans per second.
- Compare to the ideal. At the default poll rate, a reading at or near 4 scans/sec means dispatch is finishing inside each interval and the window is healthy. A reading that sits noticeably below the ideal means each scan is waiting on the previous dispatch; the further below, the longer the client is spending on tag changes.
- Drive the process to its busiest realistic state (all lines running, all analogs live) and read again. The idle-plant number is not the one that matters.
- If throughput sags, reduce the number of bindings that fire per scan: bind to slower-changing tags, drop live detail out of the overview and into the popup, or split the canvas. Re-read the Diagnostics window after each change.
For the magnifier build specifically, take the throughput reading with the popup open and the hotspot being dragged across a busy area of the overview. If the scans-per-second figure holds at the poll-rate ideal while the detail image and order data follow the hotspot, the configuration is done.
FAQ
What happens if I put too many tag bindings on one Ignition Vision window?
Nothing fails outright; the client spends longer dispatching each batch of tag changes until dispatch exceeds the scan interval, scans are delayed, and the Gateway eventually resends full tag batches instead of diffs, which compounds the lag. Windows with over 400 tag subscriptions and over 600 components have run fine, so the practical limit depends on the client PC and how many tags actually change per second.
What happens if I use moveComponent to make a magnifier the operator drags around?
The image moves, but you still have to translate its position into a region and render detail somewhere, so you end up rebuilding the popup pattern anyway while fighting container bounds and overlap. Use a transparent hotspot that reports its location and open a borderless detail window beside it instead.
What happens if the SQLTags throughput in the Diagnostics window reads well below 4 scans per second?
At the default 250 ms client poll rate, 4 scans/sec is the ideal; a lower figure means each scan is waiting on the previous dispatch and the window is falling behind. Reduce the bindings that fire per scan or move live detail into a popup, then re-read the figure under full process load.
What happens if I put my whole plant overview in a 10000x10000 container with pan and zoom?
Panning stays responsive because it is just a translation of the container, but every component and binding in the canvas is live whether it is on screen or not, so the tag-change dispatch load equals the whole plant's change rate. It works for slow-changing status views; keep fast-changing analog detail in a mouseover popup and verify with the Diagnostics throughput reading.