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.
<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:
html
<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>Interaction modifiers:
| Key | Behavior |
|---|---|
Shift | Lock aspect ratio during resize |
Ctrl / Meta | Resize from center |
css
ef-transform-handles::part(handle) { background: #e94560; }
ef-transform-handles::part(handle-se) { background: #22c55e; }Attributes
8 of 8
canvas-scale
- React prop
canvasScale- Type
number- Default
1- Description
- Current canvas zoom scale, used to keep handle hit areas a consistent screen size.
corners-only
- React prop
cornersOnly- Type
boolean- Default
false- Description
- Only shows corner resize handles, hiding edge handles.
enable-drag
- React prop
enableDrag- Type
boolean- Default
true- Description
- Allows dragging the selection by its body.
enable-resize
- React prop
enableResize- Type
boolean- Default
true- Description
- Shows resize handles.
enable-rotation
- React prop
enableRotation- Type
boolean- Default
false- Description
- Shows a rotation handle.
lock-aspect-ratio
- React prop
lockAspectRatio- Type
boolean- Default
false- Description
- Constrains resizing to the original aspect ratio.
min-size
- React prop
minSize- Type
number- Default
- —
- Description
- Minimum width/height in pixels during resize.
rotation-step
- React prop
rotationStep- Type
number- Default
- —
- Description
- Snap increment in degrees while rotating.
CSS Parts
| Part | Description |
|---|---|
drag-area | This part is an invisible drag surface that covers the overlay. It appears only when enable-drag is true. |
handle | This part matches every resize handle. There are eight handles by default, or four when corners-only is true. |
handle-e | This part is the resize handle on the east edge. |
handle-n | This part is the resize handle on the north edge. |
handle-ne | This part is the resize handle in the northeast corner. |
handle-nw | This part is the resize handle in the northwest corner. |
handle-s | This part is the resize handle on the south edge. |
handle-se | This part is the resize handle in the southeast corner. |
handle-sw | This part is the resize handle in the southwest corner. |
handle-w | This part is the resize handle on the west edge. |
overlay | This part is the outer bounding box that sits over the selected element. |
rotate-handle | This part is the hit area of the rotation handle. It appears only when enable-rotation is true. |
rotate-handle-circle | This part is the visible circular knob inside the rotation handle. |
CSS Custom Properties
| 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. |
Events
| Event | Detail | Description |
|---|---|---|
bounds-change | { bounds: {
x: number;
y: number;
width: number;
height: number;
rotation?: number;
} } | This event fires on every pointer move during a drag or a resize action. |
rotation-change | { rotation: number } | This event fires during a rotation drag. |