Skip to content
html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <form id="form">
    Edges:
    <select id="sidesSelect">
      <option value="4">4</option>
      <option value="5">5</option>
      <option value="6">6</option>
    </select>
    <br>
    Stroke Style:
    <select id="strokeStyleSelect">
      <option value="#5470c6">#5470c6</option>
      <option value="#91cc75">#91cc75</option>
      <option value="#fac858">#fac858</option>
      <option value="#ee6666">#ee6666</option>
      <option value="#73c0de">#73c0de</option>
      <option value="#3ba272">#3ba272</option>
      <option value="#fc8452">#fc8452</option>
      <option value="#9a60b4">#9a60b4</option>
      <option value="#ea7ccc">#ea7ccc</option>
    </select>
    <br>
    <input type="checkbox" id="fillCheckbox">
    Fill Checkbox
    <br>
    <input type="checkbox" id="editCheckbox">
    Edit Checkbox
  </form>
  <canvas id="canvas"></canvas>

  <script src="../lib/plain-canvas.min.js"></script>
  <script>
    const canvas = document.getElementById('canvas')
    const context = canvas.getContext('2d')
    const c = new Canvas(canvas, {
      lineWidth: 1,
      fillStyle: strokeStyleSelect.value,
      strokeStyle: strokeStyleSelect.value
    })

    canvas.width = 600
    canvas.height = 600
    canvas.style.background = '#ddd'

    context.strokeStyle = context.fillStyle = strokeStyleSelect.value

    // 选择颜色
    strokeStyleSelect.addEventListener('change', e => {
      context.strokeStyle = context.fillStyle = e.target.value
    })

    let dragging = false
    let filling = false
    let editing = false
    let edges = 4
    let drawingSurface = null
    let draggingOffsetX = null
    let draggingOffsetY = null
    let draggingPolygon = null
    const polygons = []
    let point = {
      x: null,
      y: null
    }

    sidesSelect.addEventListener('change', e => {
      edges = e.target.value
    })

    fillCheckbox.addEventListener('change', e => {
      filling = e.target.checked
    })

    editCheckbox.addEventListener('change', e => {
      editing = e.target.checked
    })

    // 保存绘图表面
    const saveDrawingSurface = () => {
      const { width, height } = canvas
      drawingSurface = context.getImageData(0, 0, width, height)
    }

    // 恢复绘图表面
    const restoreDrawingSurface = () => {
      context.putImageData(drawingSurface, 0, 0)
    }

    const drawPolygons = () => {
      polygons.forEach((polygon) => {
        polygon.createPath()

        polygon.stroke(polygon.strokeStyle)
      })
    }

    canvas.addEventListener('mousedown', e => {
      const { clientX, clientY } = e
      point = c.windowToCanvas(clientX, clientY)
      
      if (editing) {
        for (let i = 0, l = polygons.length; i < l; i++) {
          const polygon = polygons[i]
          // 绘制路径
          polygon.createPath()
          // 绘制完成后通过 isPointInPath 判断鼠标按下时是否在路径内
          if (context.isPointInPath(point.x, point.y)) {
            // 记录被拖拽的多边形
            draggingPolygon = polygon
            // 鼠标一定在多边形内部,鼠标释放时需要保持鼠标和多边形的相对位置一致
            draggingOffsetX = point.x - polygon.x
            draggingOffsetY = point.y - polygon.y
            break
          }
        }
      } else {
        // 保存绘图表面,在 mousemove 中恢复绘图表面,这样鼠标每次移动就会擦除上一次的线段。
        saveDrawingSurface()
      }
      dragging = true
    })

    let polygon = null
    canvas.addEventListener('mousemove', e => {
      if (!dragging) {
        return
      }

      const { x, y } = c.windowToCanvas(e.clientX, e.clientY)

      if (editing) {
        if (draggingPolygon) {
          // 拖动时确定多边形新的位置
          draggingPolygon.x = x - draggingOffsetX
          draggingPolygon.y = y - draggingOffsetY

          // 重新绘制
          context.clearRect(0, 0, canvas.width, canvas.height)
          drawPolygons()
        }
      } else {
        restoreDrawingSurface()
        const { x: _x, y: _y } = point
        
        const radius = Math.sqrt(Math.pow((x - _x), 2) + Math.pow((y - _y), 2))

        polygon = c.polygon(_x, _y, radius, edges)

        if (filling) {
          polygon.fill()
        }
      }
    })

    canvas.addEventListener('mouseup', e => {
      dragging = false
      point.x = point.y = null
      draggingPolygon = null
      
      if (!editing) {
        polygons.push(polygon)
      }

      polygon = null
    })
  </script>
</body>

</html>