Rumah  >  Soal Jawab  >  teks badan

Letakkan penanda interaktif pada imej menggunakan React

Tolong bantu. Saya mempunyai imej seperti di bawah yang dipaparkan di halaman utama (imej yang lebih besar). Perhatikan bahawa rumah "FORGE" mempunyai penanda putih dan biru di tengah dengan anak panah hitam.

Begitu juga dengan rumah "sewa".

Setiap penanda ini akan bertindak sebagai butang interaktif. Berikut ialah tingkah laku interaksi yang diharapkan:

Juga mahu ia responsif, jika dan apabila skrin diubah saiz, butang harus kekal dalam kedudukan tertentu tersebut.

Saya cuba menggunakan kedudukan mutlak, koordinat x,y untuk mencuba dan memastikannya berfungsi. Tetapi kerana saya menikmati pengalaman antara muka pengguna jenis ini, saya tidak dapat mencari penyelesaian yang berkesan. Tidak pasti sama ada saya perlu menggunakan kanvas atau sesuatu yang lain.

Sebarang bantuan amat kami hargai.

Kod saya kelihatan seperti ini, tetapi nampaknya saya tidak berada di landasan yang betul:

const ImageComponent = () => {

  const markers = [
    { name: 'Forge', x: 100, y: 200 },
    { name: 'Rentals', x: 300, y: 150 },
    // Add more 
  ];

  const handleMarkerClick = (m) => {
    // do something with marker
  };

  return (
    <div style={{ position: 'relative' }}>
      <img src="path/to/image.jpg" alt="Image with markers" />

      {markers.map((marker, index) => (
        <div
          key={index}
          className="marker"
          style={{ left: marker.x, top: marker.y, position: "absolute" }}
          onClick={() => handleMarkerClick(marker)}
        />
      ))}
    </div>
  );
};

P粉896751037P粉896751037378 hari yang lalu721

membalas semua(1)saya akan balas

  • P粉412533525

    P粉4125335252023-09-09 17:37:18

    Anda harus meletakkan kawalan pada kedudukan mutlak bekas imej. Pelaksanaan bergantung kepada pelbagai faktor, seperti tempat imej diletakkan, sama ada skrin penuh, sama ada terdapat kandungan sebelum atau selepas imej, dsb. Tetapi kod ini harus menunjukkan kepada anda prinsip utama.

    Jika imej diubah saiz apabila tetingkap diubah saiznya, anda harus mencipta bekas yang sama dengan imej. Anda kemudiannya boleh menetapkan kedudukan kawalan berbanding bekas itu dan menambatnya ke titik masing-masing.

    .container {
      width: 60vw; /* set 100vw to fit image window width*/
      position: relative;
    }
    .container img { width: 100%; display: block;}
    .container .control {
      position: absolute;
      width: 7.5%;  /* size in percents to resize controls with image */
      height: 7%;
      border-radius: 200px;
      background: red;
      transition: all 0.2s ease-in-out;
    }
    
    .container .control:hover {
      width: 20%;
    }
    
    #c1 { left: 50.4%; top: 26%; } /* position in percents, not in pixels */
    #c2 { left: 58.5%; top: 76.3%; }
    <div class="container">
      <img src="https://i.stack.imgur.com/BVaY9.jpg"/>
      <div class="control" id="c1"></div>
      <div class="control" id="c2"></div>
    </div>

    Gunakan kod anda dan ia akan kelihatan seperti ini (tetapi saya syorkan alihkan gaya anda dalam fail gaya untuk belajar cara menggunakan gaya modul dalam bertindak balas):

    const ImageComponent = () => {
    
      const markers = [
        { name: 'Forge', x: 50.4, y: 26 },
        { name: 'Rentals', x: 58.5, y: 76.3 },
        // Add more 
      ];
    
      const handleMarkerClick = (m) => {
        // do something with marker
      };
    
      return (
        <div style={{ position: 'relative', width: '100vw' }}>
          <img style={{ width: '100%', display: 'block'}} src="path/to/image.jpg" alt="Image with markers" />
    
          {markers.map((marker, index) => (
            <div
              key={index}
              className="marker"
              style={{ left: `${marker.x}%`, top: `${marker.y}%`, position: "absolute" }}
              onClick={() => handleMarkerClick(marker)}
            />
          ))}
        </div>
      );
    };
    

    Hanya betulkan kedudukan dan tambahkan paparan kawalan biasa.

    Untuk kawalan anda hendaklah membuat komponen berasingan. Berikut ialah contoh cara untuk mencapai tingkah laku yang anda inginkan:

    .control {
      background: #08f;
      padding: 10px;
      width: 60px;
      box-sizing: border-box;
      border-radius: 200px;
      transition: all 0.2s ease-in-out;
      display: flex;
      align-items: center;
      overflow: hidden;
      cursor: pointer;
    }
    
    .control:hover {
      width: 200px;
    }
    
    .text {
      color: white;
      font: 30px Arial;
      margin-left: 16px;
      opacity: 0;
      transition: opacity 0.2s ease-in-out;
    }
    
    .control:hover .text {
      opacity: 1;
    }
    
    .icon {
      width: 40px;
      min-width: 40px;
      height: 40px;
      border-radius: 50%;
      box-shadow: 2px 2px 7px #0005;
      background-color: white;
      background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIGZpbGw9IiMwMDAwMDAiIGhlaWdodD0iODAwcHgiIHdpZHRoPSI4MDBweCIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiAKCSB2aWV3Qm94PSIwIDAgMjk3IDI5NyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnPgoJPHBhdGggZD0iTTI5NC4wNzcsMjUxLjE5OWwtNTkuMTA1LTU5LjEwN2w0Mi4xNjctMjQuMzU2YzMuMjk1LTEuOTAzLDUuMjEyLTUuNTIsNC45MzgtOS4zMTVjLTAuMjc0LTMuNzk2LTIuNjkyLTcuMTAxLTYuMjI2LTguNTEKCQlMODcuODIsNzQuOTA1Yy0zLjY4Ni0xLjQ3Mi03Ljg5NS0wLjYwNS0xMC43MDIsMi4yMDFjLTIuODA3LDIuODA4LTMuNjc0LDcuMDE2LTIuMjAzLDEwLjcwMmw3NC45OTQsMTg4LjA1MwoJCWMxLjQxLDMuNTM0LDQuNzE1LDUuOTUzLDguNTExLDYuMjI3YzMuNzk2LDAuMjc2LDcuNDE0LTEuNjQyLDkuMzE2LTQuOTM4bDI0LjM1NC00Mi4xNjdsNTkuMTAxLDU5LjEwNwoJCWMxLjg2MiwxLjg2Myw0LjM5LDIuOTEsNy4wMjMsMi45MWMyLjYzNSwwLDUuMTYxLTEuMDQ3LDcuMDIzLTIuOTFsMjguODQxLTI4Ljg0NUMyOTcuOTU2LDI2MS4zNjYsMjk3Ljk1NiwyNTUuMDc4LDI5NC4wNzcsMjUxLjE5OQoJCXoiLz4KCTxwYXRoIGQ9Ik00My42MSwyOS41NTJjLTMuODc5LTMuODc2LTEwLjE2Ni0zLjg3Ny0xNC4wNDcsMGMtMy44NzgsMy44NzktMy44NzgsMTAuMTY4LDAsMTQuMDQ3bDIyLjA2OSwyMi4wNjkKCQljMS45MzksMS45MzksNC40OCwyLjkwOSw3LjAyMywyLjkwOWMyLjU0MSwwLDUuMDgzLTAuOTcsNy4wMjItMi45MDljMy44NzktMy44NzksMy44NzktMTAuMTY3LDAtMTQuMDQ2TDQzLjYxLDI5LjU1MnoiLz4KCTxwYXRoIGQ9Ik01MS4wODksOTguMjE1YzAtNS40ODQtNC40NDctOS45MzItOS45MzMtOS45MzJIOS45NDZjLTUuNDg1LDAtOS45MzMsNC40NDctOS45MzMsOS45MzJjMCw1LjQ4NSw0LjQ0Nyw5LjkzMyw5LjkzMyw5LjkzMwoJCWgzMS4yMUM0Ni42NDIsMTA4LjE0Nyw1MS4wODksMTAzLjcsNTEuMDg5LDk4LjIxNXoiLz4KCTxwYXRoIGQ9Ik00Ny4wNjMsMTI4Ljg2OWwtMjIuMDcyLDIyLjA3MWMtMy44NzgsMy44NzktMy44NzgsMTAuMTY4LDAsMTQuMDQ2YzEuOTQsMS45MzksNC40ODIsMi45MDksNy4wMjMsMi45MDkKCQljMi41NDEsMCw1LjA4NC0wLjk3LDcuMDIzLTIuOTA5bDIyLjA3MS0yMi4wN2MzLjg3OS0zLjg3OSwzLjg3OS0xMC4xNjgsMC0xNC4wNDdDNTcuMjMsMTI0Ljk5Myw1MC45NDQsMTI0Ljk5Miw0Ny4wNjMsMTI4Ljg2OXoiLz4KCTxwYXRoIGQ9Ik05OC4yMjIsNTEuMDc4YzUuNDg1LDAsOS45MzMtNC40NDcsOS45MzMtOS45MzNWOS45MzJjMC01LjQ4NS00LjQ0Ny05LjkzMi05LjkzMy05LjkzMmMtNS40ODQsMC05LjkzMiw0LjQ0Ni05LjkzMiw5LjkzMgoJCXYzMS4yMTRDODguMjksNDYuNjMxLDkyLjczNyw1MS4wNzgsOTguMjIyLDUxLjA3OHoiLz4KCTxwYXRoIGQ9Ik0xMzUuODk0LDY0LjAwNmMyLjU0MywwLDUuMDg0LTAuOTcsNy4wMjMtMi45MDlsMjIuMDY4LTIyLjA2OWMzLjg3OS0zLjg3OSwzLjg3OS0xMC4xNjgsMC0xNC4wNDcKCQljLTMuODc5LTMuODc3LTEwLjE2OC0zLjg3Ny0xNC4wNDYsMGwtMjIuMDY4LDIyLjA3Yy0zLjg3OSwzLjg3OS0zLjg3OSwxMC4xNjgsMCwxNC4wNDYKCQlDMTMwLjgxMSw2My4wMzYsMTMzLjM1Miw2NC4wMDYsMTM1Ljg5NCw2NC4wMDZ6Ii8+CjwvZz4KPC9zdmc+');
      background-size: 60%;
      background-repeat: no-repeat;
      background-position: center;
    }
    <div class="control">
      <div class="icon"></div>
      <div class="text">Home</div>
    </div>

    balas
    0
  • Batalbalas