Files
css-matrix-calc/.mimocode/plans/1782265108554-gentle-rocket.md
T

4.4 KiB

Plan: Background Image Upload for CSS Matrix Calculator

Overview

Add ability to load a background image onto the main #field element for visual reference when positioning corners. The image is stored as a data URL in memory (no server). Three upload methods: Ctrl+V paste, file picker, drag & drop onto the field. Adjustable via object-fit options.

Files to Modify

1. js/state.js — Add background state

  • Add bgImage: null (data URL string) and objectFit: 'contain' to defaultState and state
  • Reset these in resetState()

2. index.html — New "Background" panel + hidden file input

Add a new panel in right-col (between Field and Widget panels, after line 78):

<div class="panel">
  <h2>Background</h2>
  <div class="bg-controls">
    <input type="file" id="bgFileInput" accept="image/*" hidden />
    <button class="btn btn-edit-field" id="btnBgLoad">Load Image</button>
    <button class="btn btn-cancel-field" id="btnBgRemove" style="display:none">Remove</button>
    <select id="bgObjectFit">
      <option value="contain">contain</option>
      <option value="cover">cover</option>
      <option value="fill">fill</option>
      <option value="none">none</option>
      <option value="scale-down">scale-down</option>
    </select>
  </div>
</div>

Add drag & drop hint overlay on #fieldContainer (drop zone indicator).

3. style.css — New styles

  • .bg-controls — flex row layout for controls
  • #bgObjectFit — styled select matching existing dark theme
  • #fieldContainer.drag-over — dashed border highlight for drop feedback
  • #field — add background-size, background-position, background-repeat properties
  • .bg-hint — overlay text on field when no image loaded ("Drop image or Ctrl+V")

4. js/ui.js — Event handlers

  • btnBgLoad click → trigger hidden file input
  • bgFileInput change → read file as data URL via FileReaderstate.bgImage = dataUrl
  • document paste event → detect image in clipboardData.files → read as data URL
  • #fieldContainer dragover/drop → read dropped file as data URL
  • btnBgRemove click → clear state.bgImage
  • bgObjectFit change → state.objectFit = value
  • Toggle remove button visibility based on whether image is loaded
  • On state change: call updateAll()

5. js/preview.js — Apply background to field

  • If state.bgImage: set field.style.backgroundImage = url(...), field.style.backgroundSize, field.style.backgroundPosition, field.style.backgroundRepeat based on objectFit
  • If no image: clear background properties

6. js/svg-renderer.js — Show background in SVG editor

  • If state.bgImage: add an <image> element as first child of SVG (behind grid) with href, width, height, and preserveAspectRatio matching the objectFit mapping

7. js/main.js — No changes needed (updateAll already propagates)

Implementation Details

Image loading flow

  1. User triggers upload (paste/file/drop) → get File object
  2. FileReader.readAsDataURL(file) → get data URL string
  3. Store in state.bgImage
  4. Call updateAll() to propagate

object-fit mapping to SVG preserveAspectRatio

objectFit SVG preserveAspectRatio
contain xMidYMid meet
cover xMidYMid slice
fill none
none xMinYMin meet
scale-down xMidYMid meet

Keyboard shortcut

  • Ctrl+V paste listener on document — check for image in clipboard items
  • Only active when no input/textarea is focused (to avoid conflicts)

Drag & drop

  • Listen on #fieldContainer for dragover (prevent default, show visual hint) and drop (read file)

Verification

  1. Open index.html in browser
  2. File picker: Click "Load Image" → select image → verify it appears as background on the field in both edit (SVG) and preview modes
  3. Ctrl+V: Copy an image to clipboard → press Ctrl+V → verify it loads
  4. Drag & drop: Drag an image file onto the field area → verify it loads
  5. object-fit: Change dropdown → verify background resizes correctly (contain fits, cover fills, etc.)
  6. Remove: Click "Remove" → verify background clears
  7. Reset: Click "Reset" → verify background clears along with other state
  8. Corner drag: Load background → drag corners → verify background stays in place, corners move independently