ef-transform-handles
Resize and drag handles for a selected canvas element.
Renders an outlined bounding box with corner/edge resize handles and an optional rotation handle, positioned at bounds. Fires bounds-change on every drag or resize move. pointer-events: none on the host — only the handles themselves capture input.
Consumes panZoomTransformContext to correctly map pointer coordinates when the canvas is panned or zoomed.
| Attribute | React prop | Type | Default | Description |
|---|---|---|---|---|
canvas-scale | canvasScale | number | 1 | Current canvas zoom scale, used to keep handle hit areas a consistent screen size. |
corners-only | cornersOnly | boolean | false | Only shows corner resize handles, hiding edge handles. |
enable-drag | enableDrag | boolean | true | Allows dragging the selection by its body. |
enable-resize | enableResize | boolean | true | Shows resize handles. |
enable-rotation | enableRotation | boolean | false | Shows a rotation handle. |
lock-aspect-ratio | lockAspectRatio | boolean | false | Constrains resizing to the original aspect ratio. |
min-size | minSize | number | — | Minimum width/height in pixels during resize. |
rotation-step | rotationStep | number | — | Snap increment in degrees while rotating. |
<ef-timegroup id="demo" mode="fixed" duration="5s" class="w-[1920px] h-[1080px] bg-slate-900 flex items-center justify-center">
<style>
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.08); }
}
.demo-text { animation: pulse 2.4s ease-in-out infinite; display: inline-block; }
</style>
<ef-text class="demo-text text-white text-7xl font-bold">Hello</ef-text>
</ef-timegroup>
<ef-controls target="demo">
<div class="th-chrome">
<ef-toggle-play>
<button slot="play" class="th-btn">▶</button>
<button slot="pause" class="th-btn">⏸</button>
</ef-toggle-play>
<span class="th-hint">ef-transform-handles wraps a canvas element to enable resize and drag</span>
</div>
</ef-controls>
<style>
.th-chrome {
display: flex;
align-items: center;
gap: 12px;
padding: 8px 16px;
border-top: 1px solid rgba(255,255,255,0.08);
}
.th-btn { cursor: pointer; padding: 4px 10px; font-size: 13px; }
.th-hint { font-size: 11px; opacity: 0.4; }
</style>Typical usage inside an ef-overlay-layer:
<ef-overlay-layer>
<ef-overlay-item element-id="my-text">
<ef-transform-handles
enable-rotation
enable-resize
canvas-scale="1"
></ef-transform-handles>
</ef-overlay-item>
</ef-overlay-layer>
Events:
| Event | Detail | Description |
|---|---|---|
bounds-change | { bounds: {
x: number;
y: number;
width: number;
height: number;
rotation?: number;
} } | Fires on every pointer move during a drag or resize. |
rotation-change | { rotation: number } | Fires during a rotation drag. |
Interaction modifiers:
| Key | Behavior |
|---|---|
Shift | Lock aspect ratio during resize |
Ctrl / Meta | Resize from center |
CSS Parts
| Part | Description |
|---|---|
drag-area | Invisible drag surface covering the overlay (when `enable-drag`). |
handle | Every resize handle (all 8, or 4 when `corners-only`). |
handle-e | East edge resize handle. |
handle-n | North edge resize handle. |
handle-ne | Northeast corner resize handle. |
handle-nw | Northwest corner resize handle. |
handle-s | South edge resize handle. |
handle-se | Southeast corner resize handle. |
handle-sw | Southwest corner resize handle. |
handle-w | West edge resize handle. |
overlay | Outer bounding box positioned over the selected element. |
rotate-handle | Rotation handle hit area (when `enable-rotation`). |
rotate-handle-circle | Visible circular knob inside the rotation handle. |
ef-transform-handles::part(handle) { background: #e94560; }
ef-transform-handles::part(handle-se) { background: #22c55e; }
CSS Custom Properties
An alternative to ::part() for basic color overrides:
| Property | Default | Description |
|---|---|---|
--ef-transform-handles-border-color | var(--ef-color-primary) | Outline color of the bounding box overlay. |
--ef-transform-handles-dragging-border-color | var(--ef-color-primary) | Bounding box outline color while dragging. |
--ef-transform-handles-handle-border-color | var(--ef-color-primary) | Resize handle border color. |
--ef-transform-handles-handle-color | var(--ef-color-bg-elevated) | Resize handle fill color. |
--ef-transform-handles-rotate-handle-color | var(--ef-color-success) | Rotation handle color. |