基于d3的鼠标动态绘制矩形和圆
安装d3依赖 npm i d3
效果
绘制圆
绘制矩形
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