react-hotzone
v1.0.7
Published
react+ts实现的热区绘制组件
Downloads
624
Readme
Welcome to react-hotzone 👋
react热区绘制组件
install
npm install react-hotzone
usage
import HotZone from 'react-hotzone'; // 引入组件
const App = () => {
return (
<div>
<HotZone
dashBorder={[10, 5]} // 虚线边框:表示10个像素实线,5个像素空白
width={"30vh"}
src="http://img.netbian.com/file/2024/0920/194034Hwm4C.jpg"
allowOverlap={false}
onOverlap={() => { console.log('触发了重叠操作!!!!') }}
zones={zones}
ref={hotZoneRef}
onZoneChange={(data: RectInfoType[]) => {
console.log(data);
}}
/>
</div>
);
}
props
type WithReadonlyPropsType = {
readonly: true,
scale: [number, number]
}
type WithoutReadonlyPropsType = {
readonly?: false,
}
type HotZonePropsType = {
src: string,//热区要绘制的图片地址
width: string,//热区宽度:支持px rem vw vh 不支持%
height?: string,//热区高度:同width
allowOverlap?: boolean // 是否允许内部的热区重叠,若传入false,请传入onOverlap回调函数,当热区重叠时会触发onOverlap回调
onOverlap?: () => void // 内部矩形框重叠时触发的回调函数:在此可以自定义提示行为
onZoneChange?: (data: RectInfoType[]) => void // 接收绘制的热区信息
zones?: RectInfoType[]// 父组件传递进来的热区数据
// 这部分和热区样式有关
fillColor?: string,// 热区填充的颜色
borderColor?: string,// 热区边线的颜色
borderWidth?: number,//热区边线的宽度
dashBorder?: [number, number],// 热区边线是为虚线
orderColor?: string,//左上角序号的颜色
orderBackgroundColor?: string,// 左上角序号的背景颜色
closeColor?: string,//右上角关闭图标的颜色
closeBackgroundColor?: string,//右上角关闭图标背景色
} & (WithReadonlyPropsType | WithoutReadonlyPropsType) //当 readonly 存在时,scale必须存在
props默认值
const {
allowOverlap = true,
onOverlap = () => { },
src,
width = '500px',
height,
onZoneChange = () => { },
zones = [],
fillColor = 'rgba(255, 200, 200,0.4)',
borderColor = '#ff0000',
borderWidth = 2,
dashBorder,
orderColor = "white",
orderBackgroundColor = '#262626',
closeColor = "white",
closeBackgroundColor = '#262626',
readonly = false,
scale = [1, 1],
} = props
props——readonly与scale
readonly
表示组件内部热区不可操作,只用作展示。
当 readonly
为 true
时,scale
是必传,值为 [widthScale,heightScale]
表示 [水平方向缩放,垂直方向缩放]
。具体为:[widthReadonly / width, heightReadonly / height]
( 后边有更具体的用例 )。
当 readonly
为 false
时,scale
不允许传入。
当尺寸已知时
import HotZone,{RectInfoType} from 'react-hotzone';
const App = () => {
const [zones, setZones] = useState<RectInfoType[]>([]);
const [zoneKey, setZoneKey] = useState(1)
return (
<div>
<HotZone
dashBorder={[10, 5]}
width={600} //已知宽度
height={700} // 已知高度
src="http://img.netbian.com/file/2024/0920/194034Hwm4C.jpg"
allowOverlap={false}
onOverlap={() => { console.log('触发了重叠操作!!!!') }}
zones={zones}
onZoneChange={(data: RectInfoType[]) => {
setZones(data);
setZoneKey(zoneKey+1);
}}
/>
<h1>下边是回显内容:配置了 readonly</h1>
<HotZone
key={zoneKey}
dashBorder={[10, 5]}
width={300} //已知宽度
height={500} // 已知高度
src="http://img.netbian.com/file/2024/0920/194034Hwm4C.jpg"
allowOverlap={false}
zones={zones}
readonly={true}
scale={[300 / 600, 500 / 700]} // 直接计算缩放比例传入
/>
</div>
);
}
当尺寸未知时
即根据宽度高度自动:
import React, { useEffect, useRef, useState } from "react"
import { createRoot } from 'react-dom/client';
import HotZone,{RectInfoType} from 'react-hotzone'; // 引入组件
const App = () => {
const [zones, setZones] = useState<RectInfoType[]>([]);
const [zoneKey, setZoneKey] = useState(1);
const hotZoneRef = useRef<HTMLCanvasElement>(null);
const readonlyHotZoneRef = useRef<HTMLCanvasElement>(null);
const [hotzoneSize, setHotzoneSize] = useState<{
width: number,
height: number,
widthReadonly: number,
heightReadonly: number
}>({
width: 0,
height: 0,
widthReadonly: 0,
heightReadonly: 0
});
return (
<div>
<HotZone
dashBorder={[10, 5]}
width={400} //已知宽度
src="http://img.netbian.com/file/2024/0920/194034Hwm4C.jpg"
allowOverlap={false}
onOverlap={() => { console.log('触发了重叠操作!!!!') }}
zones={zones}
ref={hotZoneRef}
onZoneChange={(data: RectInfoType[]) => {
setZones(data);
setZoneKey(zoneKey + 1);
if (hotZoneRef.current && readonlyHotZoneRef.current) {
const { offsetWidth, offsetHeight } = hotZoneRef.current;
const { offsetWidth: widthReadonly, offsetHeight: heightReadonly } = readonlyHotZoneRef.current;
setHotzoneSize({
width: offsetWidth,
height: offsetHeight,
widthReadonly,
heightReadonly
});
}
}}
/>
<h1>下边是回显内容:配置了 readonly</h1>
<HotZone
key={zoneKey}
dashBorder={[10, 5]}
width={300} //已知宽度
src="http://img.netbian.com/file/2024/0920/194034Hwm4C.jpg"
allowOverlap={false}
zones={zones}
readonly={true}
ref={readonlyHotZoneRef}
scale={[hotzoneSize?.widthReadonly / hotzoneSize?.width, hotzoneSize?.heightReadonly / hotzoneSize?.height]} // 直接计算缩放比例传入
/>
</div>
);
}
const container = document.getElementById('root');
const root = createRoot(container as HTMLElement);
root.render(<App />);