The original atlas has a 400-millisecond loop with a 200-millisecond B frame. B draws two blue columns at destination x one, leaving transparent edges. The manual inspector computes frame boundaries and draws the original color-block atlas with Canvas when available; a textual row explains the same layout.

Work through the example
Enter 100 milliseconds and Inspect frame: B is selected, not A. At 299 it is still B; 300 selects green C and 400 loops to red A. Each draw clears all four logical columns before drawing the selected crop, preventing red edges from the earlier full-width frame. Blank, negative or nonfinite time clears the accepted output.
Check the half-open boundaries directly, especially 100 and 300 milliseconds. B must last twice as long as either neighbor. Source crop and destination offset belong to different coordinate systems. Verify the transparent outer columns with native alpha readback before treating the drawing as tested; the enlarged checkerboard and textual row explain the intention but do not replace that observation.
Prepare the atlas and logical-frame contract
Use these atlas rectangles and durations:
| Frame | Source rectangle (x,y,w,h) | Source color | Destination rectangle (x,y,w,h) | Duration |
|---|---|---|---|---|
| A | (0,0,4,4) | Opaque red | (0,0,4,4) | 100 ms |
| B | (4,0,2,4) | Opaque blue | (1,0,2,4) | 200 ms |
| C | (0,4,4,4) | Opaque green | (0,0,4,4) | 100 ms |
The logical frame is always 4 × 4. B stores only the middle two columns of that logical frame; its destination x = 1 restores their intended placement. Do not stretch B's two columns into four or choose a new anchor because its crop is narrow.
Source rectangles use atlas coordinates. Destination rectangles use logical-output coordinates. Treating source x = 4 as the destination position would put B outside the intended frame.
MDN documents the nine-argument drawImage form with separate source and destination rectangles. Its source-size note also distinguishes intrinsic image dimensions from an element's display dimensions. MDN's drawImage reference.
Use cumulative half-open time intervals
The total loop duration is:
100 + 200 + 100 = 400 ms.
For finite nonnegative elapsed time, calculate the loop-local time as elapsed modulo 400. Then select:
| Frame | Loop-local interval |
|---|---|
| A | 0 ≤ t < 100 |
| B | 100 ≤ t < 300 |
| C | 300 ≤ t < 400 |
The interval includes its start and excludes its end. At exactly 100 ms, select B; at exactly 300 ms, select C. At 400 ms, the next loop starts at A.
Keep these authored acceptance points:
| Elapsed time | Expected frame |
|---|---|
| 99 ms | A |
| 100 ms | B |
| 299 ms | B |
| 300 ms | C |
| 399 ms | C |
| 400 ms | A |
The equal-duration expression floor(elapsed/100) modulo 3 is wrong for this manifest. It would select C during part of B's intended interval and loop too soon.
This timeline is an original scheduling contract. It does not establish an actual browser frame rate or prove that every scheduled moment is physically displayed.
Clear the logical area before drawing B
For each frame:
- Validate the current atlas and frame metadata.
- Select the current frame from the accepted elapsed time.
- Clear the complete logical 4 × 4 output.
- Draw the selected crop at its declared destination.
- Update the frame ID, local time, and rectangle readout.
MDN describes clearRect as making the selected area transparent. Clearing only B's destination crop would leave A's earlier pixels outside it. MDN's clearRect behavior.
Recreate this example
Build one self-contained responsive HTML example titled “Canvas sprite animation: keep trim and time” for readers completing the stated task. Return the complete HTML with embedded CSS and JavaScript. Use no remote fonts, libraries, images, requests, account connections, or saved-state claims.
Create an 8 × 8 Canvas atlas: opaque red A at rectangle (0,0,4,4), blue B at (4,0,2,4), green C at (0,4,4,4); the rest is transparent. Logical output is 4 × 4. Destination rectangles and durations: A (0,0,4,4), 100 ms; B (1,0,2,4), 200 ms; C (0,0,4,4), 100 ms. Elapsed input starts at 0. Provide Inspect frame, 100 ms, 300 ms and Reset buttons. Modulo 400 selects half-open intervals A [0,100), B [100,300), C [300,400). Clear the full logical canvas before drawing without scaling. Magnify with crisp pixels. B’s text row is transparent, blue, blue, transparent. Input edits clear the canvas and row/rectangle readouts and request inspection. Reject invalid time and clear output. No autoplay.
Use a pixel frame inspector with enlarged native Canvas, timeline readout and textual alpha-row alternative design with a compact header. Keep the actual sample data, controls, and useful default result visible early on a 360px-wide screen. Use readable text at least 16px, generous paragraph spacing, strong contrast, semantic labels, visible keyboard focus, and wrapping source blocks. Stack records on narrow screens rather than forcing a wide table.
Wire each action to an explicit type=button click handler using element selectors; the host permits scripts but blocks form submission. Update the visible result when the described action occurs. Show specific error feedback for invalid or missing input and clear stale feedback after dependent inputs change. Use plain text when displaying user values.
Manual frame inspection does not establish animation timing, browser pixel readback or playback performance. Keep the source fixture and worked teacher or developer example distinct from actual user records. Include the domain-specific explanation and next check beside the result. Provide no fake download, send, deployment, approval, or persistence button. Everything operates locally for the current page session.
Review the prepared copy in NOS
Review B’s time interval and destination offset together before adding playback. NOS can render an HTML frame explanation and support visual revisions to eligible static notes. Preserve the native atlas, manifest and actual alpha/time checks when integrating the sprite into an animation.