Skip to navigation

Dial

The ruler that levels a tilted photo, up to 45° each way, like the one in iOS Photos.

Open
Download
0.0

Anatomy

Put DialTicks inside Dial. Dial and DialValue go anywhere inside Root:

<Cropper.DialValue />
<Cropper.Dial aria-label="Straighten">
  <Cropper.DialTicks />
</Cropper.Dial>

The stylesheet makes Dial 40 px tall and clips its ticks at the sides only, so the zero dot above them stays in view, and fades them out over 48 px at each side. It draws the ticks and the centre line. DialValue ships bare.

The demo above shows the angle to one decimal with a degree sign and uses the styles from the zriz site.

Drag and flick the ruler

The first 10 px of a drag only pick up the ruler. After that, every 4 px turns 1°. A quick flick keeps it gliding after you let go, and past the limit it stretches and springs back. On touch, a vertical swipe scrolls the page instead.

The ruler reads like a ruler, with positive angles to the right of 0°. Drag it left, or press the right arrow, and the angle grows past the centre line.

A drag catches at 0°. Within 1° of it the angle holds at exactly 0°, and past that it carries on from 0° without a jump, so a level horizon takes no fiddling. A flick that comes to rest within 1° lands on 0°. Keys, the wheel and setRotation keep the exact angle.

The photo zooms in as the angle grows. One gesture back to 0° restores the zoom. Separate gestures keep it, as in iOS Photos, until Reset or Zoom takes it back.

Set the ruler width

Dial fills its parent's width. Ticks sit 9 px apart, one every 2.25°, so 361 px fits all 41 ticks:

<Cropper.Dial aria-label="Straighten" style={{ maxWidth: 361 }}>
  <Cropper.DialTicks />
</Cropper.Dial>

The demo above is 360 px wide, as on the zriz site, so its outermost ticks fall on the edges.

Add a degree sign

format on DialValue gets the angle in degrees and returns the text to show:

<Cropper.DialValue
  format={(angle) =>
    `${Math.sign(angle) * Math.round(Math.abs(angle))}°`
  }
/>

Make the major ticks taller

Ticks carry no data-zriz-item. Select them through DialTicks:

[data-zriz-item="dial-ticks"] > [data-major] {
  height: 14px;
}

Change the drag colour

The centre line takes the accent colour while you drag. --zriz-accent sets it, and styling lists its default:

[data-zriz-item="dial"] {
  --zriz-accent: #0a84ff;
}

Keyboard

These keys work while Dial has focus:

KeyWhat it does
leftorrightLower or raise the angle by 1°
upordownRaise or lower the angle by 1°
shift+arrow keysThe same by 10°
page uporpage downRaise or lower the angle by 10°
homeorendGo to the lowest or the highest angle, −45° or 45° at most
0Straighten to 0°

On a right-to-left page or with dir="rtl" on Root, left and right swap. Up and down stay the same. The ticks read the direction when they draw, so after a page flips its dir they follow at the next draw. A new dir on Root redraws them at once.

Escape during a drag cancels it and puts the angle back.

API

Dial

Renders a <div role="slider"> anywhere inside Root. Every part also takes className, render and the props of its element, see composition. className and render get { dragging }.

Prop
aria-label string
Names the slider for screen readers. Development builds warn without it
format Intl.NumberFormatOptions
How screen readers hear the angle, merged over the default "5 degrees". An aria-valuetext of yours wins over it
AttributeWhen
data-draggingWhile a pointer drags any Dial of this cropper, so a second copy lights up too
data-snappedWhile the angle rests at exactly 0°, from the start too. The zero dot hides then. A drag through 0° leaves it as it was until you let go
VariableWhat it sets
--zriz-linePaints the centre line, the zero dot and the major ticks. Styling lists its light and dark values
--zriz-accentPaints the centre line while you drag. Styling lists its default

DialTicks

Renders an aria-hidden <div> of <span> ticks inside Dial. className and render get { count }.

Prop
count number = 41
How many ticks to draw, 2.25° apart. 41 spans 45° each way. Use an odd count so one tick sits at 0°
AttributeWhen
data-majorEvery tenth tick from the centre: 0°, 22.5° and 45° each way
data-zeroThe centre tick, at 0°
data-fade"0", "1" or "2" on the last three ticks at each end, outermost "0"
VariableWhat it sets
--zriz-tickPaints the minor ticks. Styling lists its light and dark values
--zriz-tick-indexOn each tick, its index from the left, from 0 to count minus 1

DialValue

Renders an aria-hidden <span> anywhere inside Root. zriz writes its text, so it takes no children, and neither does a render element.

Prop
format (angle: number) => string
Turns the angle into the text shown. The default rounds it and adds no unit