LoginSignup
0
0

シロイルカの画像を触ったように見せる方法

Last updated at Posted at 2023-01-07

シロイルカ(ベルーガ)を触っているように見えるようにしてみました。
実行する際はローカルホストで行ってください。
画像を連続して歪ませてアニメーションにすることで、
ポインタを中心にふにふに触っているように見せることができます。
写真だけでなくイラストにも使うことができます。

シロイルカ.gif

サンプルのURL(PC専用、スマホ不可)
https://beluga-can-touch.momijiworks.net/

プログラムの流れ

CreateJSでtickイベントというイベントを細かい時間で発生させて、
ポインタが触りたい部分の領域に入ったら、
glfs.jsで画像を歪ませるという流れになります。
また、CreateJSによって画像の輪郭の範囲に入った場合だけ、
画像を歪ませる処理を行うようにしています。

GitHub

メインとなるJavaScript

{
  ("use strict");

  // マウスの座標を取得する。
  let mouseX = 0, //マウスのX座標
    mouseY = 0; //マウスのY座標

  $(document).on("mousemove", function (e) {
    mouseX = e.pageX;
    mouseY = e.pageY;
  });

  window.addEventListener("load", init);

  function init() {
    ////// Beluga CanTouch
    // Stageオブジェクトの作成。表示リストのルートになる。
    let stageCanTouchBeluga = new createjs.Stage("CanTouchBeluga");

    // マウスオーバーを有効にする。
    stageCanTouchBeluga.enableMouseOver();

    // 触れるベルーガの画像を表示する。
    let CanTouchBelugaBitmap = new createjs.Bitmap("./images/canTouch/CanTouchBeluga.png");
    stageCanTouchBeluga.addChild(CanTouchBelugaBitmap);

    CanTouchBelugaBitmap.x = 0;
    CanTouchBelugaBitmap.y = 0;

    stageCanTouchBeluga.update();

    let CanTouchBelugaShape = new createjs.Shape();
    CanTouchBelugaShape.alpha = 0.01;
    ////// 輪郭確認用
    // CanTouchBelugaShape.alpha = 1;
    CanTouchBelugaShape.graphics.beginFill("#ffffff");

    CanTouchBelugaShape.graphics.moveTo(122.00, 90.00);
    CanTouchBelugaShape.graphics.lineTo(88.00, 101.00);
    CanTouchBelugaShape.graphics.lineTo(72.00, 118.00);
    CanTouchBelugaShape.graphics.lineTo(67.00, 135.00);
    CanTouchBelugaShape.graphics.lineTo(69.00, 159.00);
    CanTouchBelugaShape.graphics.lineTo(74.00, 187.00);
    CanTouchBelugaShape.graphics.lineTo(80.00, 215.00);
    CanTouchBelugaShape.graphics.lineTo(87.00, 253.00);
    CanTouchBelugaShape.graphics.lineTo(90.00, 295.00);
    CanTouchBelugaShape.graphics.lineTo(92.00, 344.00);
    CanTouchBelugaShape.graphics.lineTo(97.00, 384.00);
    CanTouchBelugaShape.graphics.lineTo(113.00, 447.00);
    CanTouchBelugaShape.graphics.lineTo(127.00, 505.00);
    CanTouchBelugaShape.graphics.lineTo(129.00, 520.00);
    CanTouchBelugaShape.graphics.lineTo(129.00, 553.00);
    CanTouchBelugaShape.graphics.lineTo(116.00, 605.00);
    CanTouchBelugaShape.graphics.lineTo(100.00, 663.00);
    CanTouchBelugaShape.graphics.lineTo(82.00, 713.00);
    CanTouchBelugaShape.graphics.lineTo(47.00, 798.00);
    CanTouchBelugaShape.graphics.lineTo(674.00, 799.00);
    CanTouchBelugaShape.graphics.lineTo(636.00, 711.00);
    CanTouchBelugaShape.graphics.lineTo(612.00, 662.00);
    CanTouchBelugaShape.graphics.lineTo(592.00, 621.00);
    CanTouchBelugaShape.graphics.lineTo(570.00, 584.00);
    CanTouchBelugaShape.graphics.lineTo(549.00, 548.00);
    CanTouchBelugaShape.graphics.lineTo(529.00, 517.00);
    CanTouchBelugaShape.graphics.lineTo(508.00, 478.00);
    CanTouchBelugaShape.graphics.lineTo(496.00, 447.00);
    CanTouchBelugaShape.graphics.lineTo(482.00, 418.00);
    CanTouchBelugaShape.graphics.lineTo(466.00, 372.00);
    CanTouchBelugaShape.graphics.lineTo(451.00, 334.00);
    CanTouchBelugaShape.graphics.lineTo(434.00, 290.00);
    CanTouchBelugaShape.graphics.lineTo(406.00, 240.00);
    CanTouchBelugaShape.graphics.lineTo(366.00, 167.00);
    CanTouchBelugaShape.graphics.lineTo(337.00, 124.00);
    CanTouchBelugaShape.graphics.lineTo(305.00, 88.00);
    CanTouchBelugaShape.graphics.lineTo(275.00, 65.00);
    CanTouchBelugaShape.graphics.lineTo(247.00, 52.00);
    CanTouchBelugaShape.graphics.lineTo(214.00, 46.00);
    CanTouchBelugaShape.graphics.lineTo(185.00, 49.00);
    CanTouchBelugaShape.graphics.lineTo(158.00, 63.00);
    CanTouchBelugaShape.graphics.lineTo(122.00, 90.00);

    stageCanTouchBeluga.addChild(CanTouchBelugaShape);

    // フレームレート。
    createjs.Ticker.framerate = 30;

    createjs.Ticker.addEventListener("tick", handleTick);

    function handleTick() {
      // 触れるベルーガから見た相対座標に変換する。
      let pointCanTouchBeluga = CanTouchBelugaShape.globalToLocal(stageCanTouchBeluga.mouseX, stageCanTouchBeluga.mouseY);

      // 触れるベルーガとカーソルが当たっているかを調べる
      let isHitCanTouchBeluga = CanTouchBelugaShape.hitTest(pointCanTouchBeluga.x, pointCanTouchBeluga.y);

      // 当たっていれば
      if (isHitCanTouchBeluga === true) {
        setCanvas_and_ReproTouchCanTouchBeluga();
      }

      if (isHitCanTouchBeluga === true) {
        document.body.style.cursor = "grab";
      } else {
        document.body.style.cursor = "pointer";
      }

      // Stageの描画を更新する。
      stageCanTouchBeluga.update();
    }
    // Stageの描画を更新する。
    stageCanTouchBeluga.update();
  }

  function setCanvas_and_ReproTouchCanTouchBeluga() {
    console.log("touch CanTouchBeluga");

    try {
      var canvas_CanTouchBeluga = fx.canvas();
      canvas_CanTouchBeluga.classList.add("CanTouchBelugaImageClass");
    } catch (err) {
      alert(err);
      return;
    }

    let Image_CanTouchBeluga = document.getElementById("CanTouchBelugaImage");

    let texture_CanTouchBeluga = canvas_CanTouchBeluga.texture(Image_CanTouchBeluga);

    canvas_CanTouchBeluga
      .draw(texture_CanTouchBeluga)
      .bulgePinch(mouseX - 0, mouseY - 0, 70, 0.28)
      .update();

    Image_CanTouchBeluga.parentNode.insertBefore(canvas_CanTouchBeluga, Image_CanTouchBeluga);

    $(".CanTouchBelugaImageClass:not(:last)").remove();

    return false;
  }
}

作り方

1. 画像のサイズを変更する。

GIMPを使って、画像の幅(または高さ)の長い方を800pxまで縮小します。
大きすぎる画像だとアニメーションがカクカクしてしまうため、データのサイズを減らします。

2. 画像を透過する。

GIMPを使って、触りたい部分以外の背景を透過します。
触りたい部分が複数ある場合は、それぞれをトリミングして背景を透過します。
周囲に余白ができるよう50pxほど大きめにトリミングすると良いでしょう。
余白を作る理由は、触っていない場合に画像を歪ませる処理をしないためです。
このリポジトリの例で触りたいのはベルーガ一匹なので、トリミングはしていません。
CanTouchBeluga.png

3. 画像のパスを取得する。

GIMPを使って、触れる部分のパス(ファイルやURLの意味のパスではなく、画像の輪郭などイラストで使われる意味のパス)を
取得してエクスポートします。

    CanTouchBelugaShape.graphics.moveTo(122.00, 90.00);
    CanTouchBelugaShape.graphics.lineTo(88.00, 101.00);
    CanTouchBelugaShape.graphics.lineTo(72.00, 118.00);
    CanTouchBelugaShape.graphics.lineTo(67.00, 135.00);
    CanTouchBelugaShape.graphics.lineTo(69.00, 159.00);
    CanTouchBelugaShape.graphics.lineTo(74.00, 187.00);
    CanTouchBelugaShape.graphics.lineTo(80.00, 215.00);
    CanTouchBelugaShape.graphics.lineTo(87.00, 253.00);
    CanTouchBelugaShape.graphics.lineTo(90.00, 295.00);
    CanTouchBelugaShape.graphics.lineTo(92.00, 344.00);
    CanTouchBelugaShape.graphics.lineTo(97.00, 384.00);
    CanTouchBelugaShape.graphics.lineTo(113.00, 447.00);
    CanTouchBelugaShape.graphics.lineTo(127.00, 505.00);
    CanTouchBelugaShape.graphics.lineTo(129.00, 520.00);
    CanTouchBelugaShape.graphics.lineTo(129.00, 553.00);
    CanTouchBelugaShape.graphics.lineTo(116.00, 605.00);
    CanTouchBelugaShape.graphics.lineTo(100.00, 663.00);
    CanTouchBelugaShape.graphics.lineTo(82.00, 713.00);
    CanTouchBelugaShape.graphics.lineTo(47.00, 798.00);
    CanTouchBelugaShape.graphics.lineTo(674.00, 799.00);
    CanTouchBelugaShape.graphics.lineTo(636.00, 711.00);
    CanTouchBelugaShape.graphics.lineTo(612.00, 662.00);
    CanTouchBelugaShape.graphics.lineTo(592.00, 621.00);
    CanTouchBelugaShape.graphics.lineTo(570.00, 584.00);
    CanTouchBelugaShape.graphics.lineTo(549.00, 548.00);
    CanTouchBelugaShape.graphics.lineTo(529.00, 517.00);
    CanTouchBelugaShape.graphics.lineTo(508.00, 478.00);
    CanTouchBelugaShape.graphics.lineTo(496.00, 447.00);
    CanTouchBelugaShape.graphics.lineTo(482.00, 418.00);
    CanTouchBelugaShape.graphics.lineTo(466.00, 372.00);
    CanTouchBelugaShape.graphics.lineTo(451.00, 334.00);
    CanTouchBelugaShape.graphics.lineTo(434.00, 290.00);
    CanTouchBelugaShape.graphics.lineTo(406.00, 240.00);
    CanTouchBelugaShape.graphics.lineTo(366.00, 167.00);
    CanTouchBelugaShape.graphics.lineTo(337.00, 124.00);
    CanTouchBelugaShape.graphics.lineTo(305.00, 88.00);
    CanTouchBelugaShape.graphics.lineTo(275.00, 65.00);
    CanTouchBelugaShape.graphics.lineTo(247.00, 52.00);
    CanTouchBelugaShape.graphics.lineTo(214.00, 46.00);
    CanTouchBelugaShape.graphics.lineTo(185.00, 49.00);
    CanTouchBelugaShape.graphics.lineTo(158.00, 63.00);
    CanTouchBelugaShape.graphics.lineTo(122.00, 90.00);

4. index.phpを編集する。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="description" content="シロイルカ(ベルーガ)を触っているように見えるようにしてみました。">
  <meta charset="utf-8">
  <link rel="stylesheet" href="./css/style.css?ver<?php echo date('Ymd-His'); ?>">

  <title>Animal_Touch</title>
</head>

<body>
  <div id="container">

    <div class="wrapper">
      <img id="background" src="./images/background/Beluga.png" />
      
      <canvas id ="CanTouchBeluga" width="694" height="800"></canvas>
      <img id="CanTouchBelugaImage" src="./images/canTouch/CanTouchBeluga.png" alt="">
    </div>
  </div>

  <script src="./js/glfx.js"></script>
  <script src="./js/jquery.js"></script>
  <script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
  <script src="./js/main.js?<?php echo date('Ymd-His'); ?>"></script>
</html>

画像のパス(ファイルのパスの意味です)を入力し、canvasのwidthとheightを指定します。
widthとheightはMacならプレビュー.appから取得すると良いでしょう。

読み込むJavaScriptは全部で4つです。

<script src="./js/glfx.js"></script>
<script src="./js/jquery.js"></script>
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
<script src="./js/main.js?<?php echo date('Ymd-His'); ?>"></script>

コードを編集した時にすぐにブラウザで反映されるよう、クエリ(?)を用いています。 (このクエリを利用するためにphpを使用しました。)
glfx.jsは画像を歪ませる処理をしてくれるライブラリです。
jqueryは歪ませた画像を表示した後、最後に表示した画像以外の過去の歪ませた画像を削除するときに便利なため 使うことにしました。
createJSは画像の当たり判定を処理しています。エクスポートしたパスはこの当たり判定のために作りました。
main.jsは画像を歪ませる処理とカーソルと画像の当たり判定を処理するJavaScriptです。

5. CSSの座標などを調整する。

CSSはこのベルーガの例では

.CanTouchBelugaImageClass {
position: absolute;
left: 0px;
top: 0px;
z-index: 1;
}

となっています。 このCanTouchBelugaImageClassは歪ませた画像に付随しているクラスとなっています。
これはmain.jsのsetCanvas_and_ReproTouchCanTouchBeluga()関数でクラスを付加しています。

z-index: 1;

は背景よりも前に表示するための処理です。

left: 0px;
top: 0px;

は触りたい画像で触りたい画像の位置を調整してください。
画像の大きさはGIMPであらかじめ処理しているためさらに処理を加える必要はないはずです。

6. JSを編集する。

main.jsの27行目、28行目のx座標、y座標は触りたい画像の位置です。
このベルーガの例では共に0としていますが、
5.の

left: 0px;
top: 0px;

と同じ値にすることで画像の位置を調整することができます。

33行目で

CanTouchBelugaShape.alpha = 0.01;

としているのは、完全な透明だと当たり判定の処理をしなくなってしまうためです。

38行目〜79行目でGIMPでエクスポートしたパス(3.)を入力しています。
このパスが当たり判定の範囲となります。

84行目でフレームレートを指定しています。
カクカクしないようご自身で調整してください。

参考リンク: https://ics.media/tutorial-createjs/ticker/

7. 歪ませた後の画像をどこに表示するかを調整する。

setCanvas_and_ReproTouchCanTouchBeluga()関数で歪ませた後の画像をどこに表示するかを調整する。
main.jsのsetCanvas_and_ReproTouchCanTouchBeluga()関数の
130行目で歪ませた後の画像を表示する座標を指定します。
ここでは共に0としていますが、表示させたい画像の場所を調整することができます。
70は歪ませる範囲の半径、0.28はどのぐらい強く歪ませるかの値です。

参考リンク: https://evanw.github.io/glfx.js/docs/

これで終了です。

補足1 (glfx.js)

try {
      var canvas_CanTouchBeluga = fx.canvas();
      canvas_CanTouchBeluga.classList.add("CanTouchBelugaImageClass");
    } catch (err) {
      alert(err);
      return;
    }

    let Image_CanTouchBeluga = document.getElementById("CanTouchBelugaImage");

    let texture_CanTouchBeluga = canvas_CanTouchBeluga.texture(Image_CanTouchBeluga);

    canvas_CanTouchBeluga
      .draw(texture_CanTouchBeluga)
      .bulgePinch(mouseX - 0, mouseY - 0, 70, 0.28)
      .update();

    Image_CanTouchBeluga.parentNode.insertBefore(canvas_CanTouchBeluga, Image_CanTouchBeluga);

    $(".CanTouchBelugaImageClass:not(:last)").remove();

    return false;

このコードはglfx.jsの公式サイトのコードを応用したものです。

補足2 (CreateJS)

init関数の中には見慣れないオブジェクトやメソッドなどが多数あるかと思いますが、
これらはCreateJS特有のものです。
(Shape、enableMouseOver()など)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0