如何解决如何将数组数组映射到 React 组件中的 JSX 元素,每个内部数组都有自己的剪辑路径
array_groups 是一个数组数组。内部数组中的对象是规则圆的坐标,它们都是近端的,想法是这些内部的圆数组都应该一起剪辑路径。这个想法是,当我将鼠标移到近端圆的每个区域上时,矩形仅显示在该区域中。
function Hoverpicture() {
const [image,setimage] = useState("");
const [mousepos,setmousepos] = useState({ x: 0,y: 0 });
const [radius,setradius] = useState(20)
const [label,setlabel] = useState("");
const [region,setregion] = useState([]);
const [input,setinput] = useState("");
const [mode,setmode] = useState(1);
const [mousemove,setmousemove] = useState(()=>onmousemove);
function onlabelclick(e) {
setlabel("clicked label")
}
function onmouseclick(e) {
let newregion = region.concat({ x: e.nativeEvent.offsetX,y: e.nativeEvent.offsetY,r: radius,label: input});
setregion(newregion);
}
function checkregion(pos) {
for (let reg of region) {
let xs = pos.x - reg.x;
let ys = pos.y - reg.y;
xs*=xs;
ys*=ys;
console.log(reg);
if (reg.r-Math.sqrt( xs + ys ) > 0) {
return reg.label;
}
}
return false;
}
function onmousemove(e) {
setmousepos({ x: e.nativeEvent.offsetX,y: e.nativeEvent.offsetY });
let displaylabel = checkregion({x: e.nativeEvent.offsetX,y: e.nativeEvent.offsetY});
if (displaylabel) {
setlabel(displaylabel);
} else {
setlabel("");
}
}
function handleinput(e) {
setinput(e.target.value);
}
function myreducer(accum,next) {
accum[next.label] = accum[next.label] || [];
accum[next.label].push(next);
return accum;
}
var grouped_region = region.reduce(function (accum,next) {
accum[next.label] = accum[next.label] || [];
accum[next.label].push(next);
return accum;
},{});
var array_groups = [];
for (let area in grouped_region) {
array_groups.push(grouped_region[area]);
}
if (mode===1)
{
return (
<div>
<div className="img-overlay-wrap">
<img src={image} alt="table with coffee"/>
<svg onMouseMove={onmousemove} viewBox="0 0 auto auto">
<circle cx={mousepos.x} cy={mousepos.y} r={radius} fill-opacity="0"/>
{array_groups.map((ar,i) =>(
<clipPath id="shape">
{ar.map(reg =>(<circle onClick={onlabelclick} cx={reg.x} cy={reg.y} r={reg.r} fill="orange"/>))}
</clipPath>
<rect x={0} y={0} width="100%" height="100%" clipPath="url(#shape)" class="label" fill-opacity="0"/>
))}
</svg>
</div>
<div>
<h1>{ label }</h1>
<button onClick={()=>{setmode(1)}}>✏</button>
</div>
</div>
)}
CSS 看起来像这样..
.img-overlay-wrap {
position: relative;
display: inline-block; /* <= shrinks container to image size */
transition: transform 150ms ease-in-out;
}
.img-overlay-wrap img { /* <= optional,for responsiveness */
display: block;
max-width: 100%;
height: auto;
}
.img-overlay-wrap svg {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
.label:hover {
fill-opacity:.5;
fill:red;
}
解决方法
哦,是的,我见过那个。您只需要将所有这些相邻的标签(clipPath
和 rect
)包含在一个节点中,以便映射返回。 React Fragment
可以派上用场。
使用显式 <React.Fragment>
语法声明的片段可能具有
键。一个用例是将一个集合映射到一个数组
片段
{array_groups.map((ar,i) => (
<Fragment key={i}>
<clipPath id="shape">
{ar.map((reg) => (
<circle
onClick={onlabelclick}
cx={reg.x}
cy={reg.y}
r={reg.r}
fill="orange"
/>
))}
</clipPath>
<rect
x={0}
y={0}
width="100%"
height="100%"
clipPath="url(#shape)"
class="label"
fill-opacity="0"
/>
</Fragment>
))}
我无法保存对您的 codepen 所做的编辑,但我可以在此处复制组件的内容。
function Hoverpicture() {
const [image,setimage] = useState("");
const [mousepos,setmousepos] = useState({ x: 0,y: 0 });
const [radius,setradius] = useState(20);
const [label,setlabel] = useState("");
const [region,setregion] = useState([]);
const [input,setinput] = useState("");
const [mode,setmode] = useState(1);
function getimage() {
storage
.child("peterRabbit.png")
.getDownloadURL()
.then((url) => {
let image = url;
setimage(image);
})
.catch((error) => {
// Handle any errors
});
}
function getlabels() {
let doc = ref.doc("01xfB3duoKI2Uoq4gtYZ");
doc.get().then((d) => {
console.log(d.data());
});
}
getlabels();
getimage();
function onlabelclick(e) {
setlabel("clicked label");
}
function onmouseclick(e) {
let newregion = region.concat({
x: e.nativeEvent.offsetX,y: e.nativeEvent.offsetY,r: radius,label: input
});
setregion(newregion);
}
function getcoords() {}
function checkregion(pos) {
for (let reg of region) {
let xs = pos.x - reg.x;
let ys = pos.y - reg.y;
xs *= xs;
ys *= ys;
console.log(reg);
if (reg.r - Math.sqrt(xs + ys) > 0) {
return reg.label;
}
}
return false;
}
function onmousemove(e) {
setmousepos({ x: e.nativeEvent.offsetX,y: e.nativeEvent.offsetY });
let displaylabel = checkregion({
x: e.nativeEvent.offsetX,y: e.nativeEvent.offsetY
});
if (displaylabel) {
setlabel(displaylabel);
} else {
setlabel("");
}
}
function handleinput(e) {
setinput(e.target.value);
}
function myreducer(accum,next) {
accum[next.label] = accum[next.label] || [];
accum[next.label].push(next);
return accum;
}
const [mousemove,setmousemove] = useState(() => onmousemove);
var grouped_region = region.reduce(function (accum,next) {
accum[next.label] = accum[next.label] || [];
accum[next.label].push(next);
return accum;
},{});
console.log(grouped_region);
var array_groups = [];
for (let area in grouped_region) {
array_groups.push(grouped_region[area]);
}
if (mode === 0) {
return (
<div>
<div className="img-overlay-wrap">
<img src={image} alt="table with coffee" />
<svg onMouseMove={onmousemove} viewBox="0 0 auto auto">
<circle
cx={mousepos.x}
cy={mousepos.y}
r={radius}
fill-opacity="0"
/>
{array_groups.map((ar,i) => (
<>
<clipPath id="shape">
{ar.map((reg) => (
<circle
onClick={onlabelclick}
cx={reg.x}
cy={reg.y}
r={reg.r}
fill="orange"
/>
))}
</clipPath>
<rect
x={0}
y={0}
width="100%"
height="100%"
clipPath="url(#shape)"
class="label"
fill-opacity="0"
/>
</>
))}
</svg>
</div>
<div>
<h1>{label}</h1>
<button
onClick={() => {
setmode(1);
}}
>
✏
</button>
</div>
</div>
);
} else if (mode === 1) {
return (
<div>
<div className="img-overlay-wrap">
<img src={image} alt="table with coffee" />
<svg
onMouseMove={onmousemove}
onClick={onmouseclick}
viewBox="0 0 auto auto"
>
<circle
cx={mousepos.x}
cy={mousepos.y}
r={radius}
fill="rebeccapurple"
/>
{region.map((reg) => (
<circle
onClick={onlabelclick}
class="label"
cx={reg.x}
cy={reg.y}
r={reg.r}
fill="orange"
/>
))}
</svg>
</div>
<div>
<h1>
{mousepos.x} {mousepos.y}
</h1>
<h1>{label}</h1>
<input
placeholder="label"
value={input}
onChange={handleinput}
></input>
<button
onClick={() => {
setmode(0);
}}
>
✅
</button>
</div>
</div>
);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。