[英]How to map an array of arrays into a JSX element in a react component, with each inner array having it's own clipPath
array_groups is an array of arrays. array_groups 是一个 arrays 的数组。 The objects in the inner arrays are coordinates of regular circles, which are all proximal and the idea is that these inner arrays of circles should all be clipPath-ed together.
内部 arrays 中的对象是规则圆的坐标,它们都是近端的,想法是这些内部 arrays 的圆应该都被clipPath-ed在一起。 The idea is that when I move my mouse over each area of proximal circles, the rect only shows in that area.
这个想法是,当我将鼠标移到近端圆圈的每个区域上时,矩形仅显示在该区域中。
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>
)}
The CSS looks like this.. 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;
}
Oh, yeah, I have seen that one.哦,是的,我见过那个。 You just need to enclose all those adjacent tags (
clipPath
and rect
) in a single node for the mapping return.您只需将所有这些相邻标签(
clipPath
和rect
)包含在单个节点中即可进行映射返回。 React Fragment
comes in handy for this. React
Fragment
就派上用场了。
Fragment - keyed Fragments片段-键控片段
Fragments declared with the explicit
<React.Fragment>
syntax may have keys.使用显式
<React.Fragment>
语法声明的片段可能有键。 A use case for this is mapping a collection to an array of fragments一个用例是将集合映射到片段数组
{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>
))}
I can't save the edits I made to your codepen, but I can copy the contents of the component here.我无法保存对您的 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>
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.