(149) 非矩形領域をホバー時に反応させたい。

投稿者: | 2023年12月29日

154 views

1. やりたいこと

画面上の非矩形な領域をマウスホバーした時に、何らかの反応をさせたい。

2. やってみる

方法1 : ベクタ画像データを使う

下記コードの実装例はこちら。
https://www.dogrow.net/hp/sample/00149/01/

(1) index.html

<!DOCTYPE html>
<html>
<head>
  <title>Blog No.148-1</title>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>
<body>
  <div class="imgArea">
    <img id="imgBg" src="./bg_snow_jutaku.jpg" alt="" />
    <object id="item1" class="fimg" type="image/svg+xml" data="./myimg_1.svg" data-pup="pup1"></object>
    <div id="pup1" class="pup">パックマン?</div>
    <object id="item2" class="fimg" type="image/svg+xml" data="./myimg_2.svg" data-pup="pup2"></object>
    <div id="pup2" class="pup">セキセイインコたち</div>
  </div>
</body>
</html>

(2) script.js

document.addEventListener("DOMContentLoaded", function() {
  var elem_fimgs = document.querySelectorAll('object.fimg');

  elem_fimgs.forEach(function(elem) {

    elem.addEventListener('load', function() {
      const svgDoc  = this.contentDocument;
      const svgElem = svgDoc.querySelector('polygon');
      const pup_id  = elem.getAttribute('data-pup');
      const pupElem = document.getElementById(pup_id);
      if(svgElem && pupElem){

        svgElem.addEventListener('mouseover', function(ev) {
          svgElem.style.cursor = 'pointer';
          elem.classList.add('anim_blink');
        });

        svgElem.addEventListener('mouseout', function(ev) {
          svgElem.style.cursor = '';
          elem.classList.remove('anim_blink');
          pupElem.style.display = 'none';
        });

        svgElem.addEventListener('click', function(ev) {
          pupElem.style.display = 'inline-block';
        });
      }
    });
  });
});

(3) SVG画像

Adobe Illustratorで編集、出力した SVG画像をそのまま使った。

<?xml version="1.0" encoding="UTF-8"?>
<svg id="_レイヤー_2" data-name="レイヤー 2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 167.23 201.14">
  <defs>
    <style>
      .cls-1 {
        fill: #3072b9;
        stroke-width: 0px;
      }
    </style>
  </defs>
  <g id="_レイヤー_1-2" data-name="レイヤー 1">
    <image width="720" height="866" transform="scale(.23)" xlink:href="myimg_1.png"/>
    <polygon class="cls-1" style="opacity:0" points="48.7 0 0 63.24 0 149.4 67.57 201.14 167.23 147.48 76.48 106.41 158.27 42.97 48.7 0"/>
  </g>
</svg>

(4) style.css

*{
  margin:  0;
  padding: 0;
  box-sizing: border-box;
}
div.imgArea{
  position: relative;
  margin: 1rem;
  border: 3px #000 solid;
  line-height: 0;
}
img#imgBg{
  width: 100%;
}
.anim_blink {
  animation: kf_blink 1s infinite;
}
@keyframes kf_blink {
  0%  { opacity: 1;   }
  50% { opacity: 0.1; }
  100%{ opacity: 1;   }
}
div.pup{
  position: absolute;
  background-color: #fffff8;
  box-shadow: 2px 2px 4px rgba(0,0,0,0.5);
  border-radius: 0.5rem;
  padding: 1rem;
  display: none;
}
#item1{
  position: absolute;
  top: 10%;
  left: 20%;
  width: 10%;
}
#pup1{
  top:  12%;
  left: 30%;
}
#item2{
  position: absolute;
  top: 70%;
  left: 60%;
  width: 15%;
}
#pup2{
  top:   72%;
  left:  75%;
}

方法2 : ラスタ画像データを使う

背景透過の PNG画像を使用する。
ポイントした座標の画素値を参照し、αチャネルの値が0であれば背景であると判断する。
ポイントした座標の画素値を参照し、αチャネルの値が非0であれば画像上と判断する。→ 反応させる。

 ↓↓↓
実際に実装して動かしてみたが…
・コード量が多く複雑になる。
・画素値参照による処理負荷が大きい。

よって…
今回は上述の「ベクタ画像データを使う」を採用することにした。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)