基于d3的鼠标动态绘制矩形和圆

安装d3依赖 npm i d3

效果
绘制圆
img
绘制矩形
img
react实现版

import * as d3 from 'd3'
import React, {useRef, useEffect, useState} from 'react'

const DrawRect = () => {
  // CRICLE 圆 RECT 矩形
  const type = 'CRICLE'
  const svgBase = useRef()
  const carrierSvg = useRef()
  const isDraw = useRef(true)
  const currentId = useRef(0)
  const [allId, setAllId] = useState([0])
  // [x0,y0,x1,y1]
  const [rectCoor, setRectCoor] = useState([0, 0, 0, 0])
  const [, setIsDraw] = useState(true)
  const [, setCarrierSvg] = useState(null)

  useEffect(() => {
    const svg = d3.select(svgBase.current)
      .append('svg')
      .attr('width', '100vw')
      .attr('height', '100vh')
    carrierSvg.current = svg
    setCarrierSvg(svg)
  }, [])

  const drawRect = (endX, endY, id) => {
    const delEl = document.getElementById(id)
    if (delEl) {
      delEl.remove()
    }

    carrierSvg.current.append('rect')
      .attr('id', id)
      .attr('width', Math.abs(endX - rectCoor[0]))
      .attr('height', Math.abs(endY - rectCoor[1]))
      .attr('x', rectCoor[0] > endX ? endX : rectCoor[0])
      .attr('y', rectCoor[1] > endY ? endY : rectCoor[1])
      .attr('fill', 'rgba(255,10,10,0.4)')
      .attr('stroke', 'rgba(255,10,10,1)')
  }

  const drawCircle = (endX, endY, id) => {
    const delEl = document.getElementById(id)
    if (delEl) {
      delEl.remove()
    }
    const xr = Math.abs(endX - rectCoor[0])
    const yr = Math.abs(endY - rectCoor[1])
    const r = Math.sqrt(xr * xr + yr * yr) / 2
    carrierSvg.current.append('circle')
      .attr('id', id)
      .attr('r', r)
      .attr('cx', xr / 2 + endX > rectCoor[0] ? rectCoor[0] : endX)
      .attr('cy', yr / 2 + endY > rectCoor[1] ? rectCoor[1] : endY)
      .attr('fill', 'rgba(10,255,10,0.4)')
      .attr('stroke', 'rgba(10,255,10,1)')
  }

  useEffect(() => {
    // 鼠标按下
    svgBase.current.onmousedown = e => {
      const x0 = e.offsetX
      const y0 = e.offsetY
      rectCoor[0] = x0
      rectCoor[1] = y0
      setRectCoor(rectCoor)
      setIsDraw(false)
      isDraw.current = false
    }
    // 鼠标移动
    svgBase.current.onmousemove = e => {
      const x1 = e.offsetX
      const y1 = e.offsetY
      if (!isDraw.current) {
        if (type === 'RECT') {
          drawRect(x1, y1, currentId.current)
        }
        if (type === 'CRICLE') {
          drawCircle(x1, y1, currentId.current)
        }
      }
    }
    svgBase.current.onmouseup = e => {
      const x1 = e.offsetX
      const y1 = e.offsetY
      rectCoor[2] = x1
      rectCoor[3] = y1
      setRectCoor(rectCoor)
      if (type === 'RECT') {
        drawRect(x1, y1, currentId.current)
      }
      if (type === 'CRICLE') {
        drawCircle(x1, y1, currentId.current)
      }
      setIsDraw(true)
      isDraw.current = true
      currentId.current += 1
      setAllId(allId.push(currentId.current))
    }
  }, [])

  return <div ref={svgBase} style={{zIndex: 10, position: 'absolute', background: '#fff'}} />
}

export default DrawRect

posted @ 2022-07-01 14:42  VictoriaC~  阅读(319)  评论(0编辑  收藏  举报