canvas-txt 5 interactive

by Geon George

HTML

<canvas id="c" width="800" height="500"></canvas>

CSS

body {
  background: #fafaf7;
  margin: 20px;
}
canvas {
  background: #fff;
  border: 1px solid #ddd;
}

JavaScript

import { layoutText, drawTextLayout  } from 'https://unpkg.com/[email protected]/dist/index.js'

const canvas = document.getElementById('c')
const ctx = canvas.getContext('2d')

const box = { x: 240, y: 140, w: 320, h: 220 }
const MIN = 60      // minimum box size while resizing
const GRAB = 8      // hit radius around a handle, in px

const text =
  'Drag me around, or grab a handle to resize — canvas-txt re-lays the text out on every change.'

function handles() {
  const { x, y, w, h } = box
  return [
    { id: 'nw', x, y },
    { id: 'n', x: x + w / 2, y },
    { id: 'ne', x: x + w, y },
    { id: 'w', x, y: y + h / 2 },
    { id: 'e', x: x + w, y: y + h / 2 },
    { id: 'sw', x, y: y + h },
    { id: 's', x: x + w / 2, y: y + h },
    { id: 'se', x: x + w, y: y + h },
  ]
}

function render() {
  ctx.clearRect(0, 0, canvas.width, canvas.height)

  // the library's job: turn the rectangle into laid-out text
  ctx.fillStyle = '#17191c'
  const layout = layoutText(ctx, text, {
    width: box.w,
    height: box.h,
    fontSize: 22,
    overflow: 'ellipsis',
  })
  drawTextLayout(ctx, layout, { x: box.x, y: box.y })

  // your app's job: the selection chrome
  ctx.strokeStyle = '#0c8ce9'
  ctx.lineWidth = 1
  ctx.strokeRect(box.x + 0.5, box.y + 0.5, box.w, box.h)
  ctx.fillStyle = '#fff'
  for (const p of handles()) {
    ctx.fillRect(p.x - 3, p.y - 3, 6, 6)
    ctx.strokeRect(p.x - 2.5, p.y - 2.5, 5, 5)
  }
}

// ------- pointer handling: hit-test, drag, resize -------

function pick(mx, my) {
  for (const p of handles()) {
    if (Math.abs(mx - p.x) <= GRAB && Math.abs(my - p.y) <= GRAB) return p.id
  }
  const { x, y, w, h } = box
  if (mx >= x && mx <= x + w && my >= y && my <= y + h) return 'move'
  return null
}

const CURSORS = {
  nw: 'nwse-resize', se: 'nwse-resize',
  ne: 'nesw-resize', sw: 'nesw-resize',
  n: 'ns-resize', s: 'ns-resize',
  w: 'ew-resize', e: 'ew-resize',
  move:...