简体   繁体   English

如何将 map 数组 arrays 转换为反应组件中的 JSX 元素,每个内部数组都有自己的 clipPath

[英]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.您只需将所有这些相邻标签( clipPathrect )包含在单个节点中即可进行映射返回。 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.

相关问题 如何为数组中的每个项目呈现 JSX 组件 - How to render a JSX component for each item in array React/MaterialUI - 如何在我的 object 中将每个 JSON 数组 map 放到它自己的单独表中? - React/MaterialUI - How can I map each JSON array in my object to it's own separate table? 如何在反应中使用.map 渲染 JSX 数组 - how to render an array of JSX using .map in react Javascript:按每个内部数组中的第二个元素对数组排序 - Javascript: Sort array of arrays by second element in each inner array 如何在 array.map 中除 React JSX 中的最后一个元素之外的每个元素之后添加逗号 - How to add a comma in array.map after every element except last element in React JSX 如何 map arrays 的 arrays 数组与反应中的对象 - How to map an array of arrays of arrays with objects in react Map Javascript中arrays的数组的每个数组的第一个元素 - Map the first element of each array of an array of arrays in Javascript 如何过滤 arrays 的数组并只返回每个内部数组的一部分? - How to filter an array of arrays and just return part of each inner array? 如何在 JSX 中只链接 .map 数组的一个元素 - How to href Link only one element of a .map array inside JSX 如何将 map 索引传递给由 jsx 元素组成的数组项? - How to pass map indexes to array items compose of jsx element?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM