プログラミング雑記

【 JavaScript 】アイコン用の画像をアップロードしてもらいサイズや位置も調整する

楠 剛毅(goke)

個人開発から世界を変えるようなプロダクトづくりを目指しています

はじめに

ユーザー登録の時なんかにアイコン用の画像をアップロードしてもらうことがよくあります。すごく雑なやり方でよければ、アップされた画像の中心部分から半径50pxで円をかいたような形でアイコンにして仕舞えばいいのですが、ユーザーによってはアップした画像を拡大したり、少し位置をずらしたりしたいはずです。
アプリではよくこのような体験に出会うのでどう実装するのがいいのか、実装例を探してみたのですがなかなか見つからないので、こんな感じかなと実装してみました。

実装方法

やりたいことは次の通りです。

1. 画像をアップしてもらう
2. アップした画像の中から、アイコンに使いたい部分だけを選択してもらう
3. 選択した部分をアイコンに設定する

上記の中でも今回は2について、スマホからでもPCからでもうまくいくような方法を検討しようと思います。

スマホからでもうまく実装するためには画像をピンチインしたり移動させたりするUXが必要になりそうです。
とするとフルスクラッチは厳しいので、下記のライブラリを利用しようと思います。

https://github.com/anvaka/panzoom

上記に加えて、jQueryも利用します。
それでは実際にコードを書いていきます。

<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <script src="https://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
    <style>
     body{
       text-align:center;
     }
     .container{
       width:300px;
       height:300px;
       display:inline-block;
       margin:20px;
     }
     .outer{
       width:300px;
       height:300px;
       overflow:hidden;
       border-radius:300px;
     }
     #preview{
       width:300px;
       height:300px;
       background-image:url('1.jpg');
       background-size:100%;
       background-repeat:no-repeat;
       border-radius:600px;
       display:inline-block;
     }
     #panzoom{
       position:relative;
       align-items:center;
       justify-content:center;
       width:100%;
       height:100%
     }
     #panzoom img{
       width:auto;
       height:auto;
       vertical-align:bottom
     }
    </style>
  </head>

  <body>
    <!-- ユーザーが触る部分 -->
    <div class="container">
      <div class="outer">
	    <div id="panzoom">
	      <img src="test.jpeg" id="target_img">
	    </div>
      </div>
    </div>
    <!-- うまくいっているか確認する部分 -->
    <div id="preview" style="background-image:url('test.jpeg')">
    </div>

    <script src="https://unpkg.com/panzoom@9.4.3/dist/panzoom.min.js"></script>
    <script>
     /* scale or move image*/
     const panzoomEl = document.getElementById('panzoom');
     const instance = panzoom(panzoomEl, {
       bounds: true,
       boundsPadding: 0.05
     });
     instance.on('transform', function(e) {
       var scale = instance.getTransform().scale;
       var x = instance.getTransform().x;
       var y = instance.getTransform().y;
       if($("#target_img").width() > $("#target_img").height()){
	 //landscape
	 height_scale = 100 * $("#target_img").width() / $("#target_img").height() * scale;
	 width_scale = 100 * scale;
	 $("#target_img").css("height","100%");
       }else{
	 //portrait
	 height_scale = 100 * scale;
	 width_scale = 100 * $("#target_img").height() / $("#target_img").width() * scale;
	 $("#target_img").css("width","100%");
       }
       //parameters
       $("#preview").css("background-position-x", x + "px");
       $("#preview").css("background-position-y", y + "px");
       $("#preview").css("background-size", height_scale + "%" + "," + width_scale + "%" );
     });
    </script>
  </body>
</html>

test.jpegというファイルは適当な画像ファイルにしていただければと思いますが、上記のコードを表示すると下のようになります。

2つ円がありますが、上の円は画像を取り込んできた部分で、ユーザーがマウスやピンチイン/アウトなどで移動したり拡大縮小したりすることができます。
そして、その結果をパラメータとして取り込んだのが下の円です。
コードで言うと「parameters」と言うコメントがある部分でユーザーが調整した結果のパラメータを取得、反映しています。

想定するステップとしては、ユーザーがアップロードした画像をそのままアイコンとして表示し、表示するときには指定されたパラメータによって表示箇所を調整する、というやり方です。

もっとうまいやり方もある気がしているので気になる点があればぜひ教えてください。

最後に

gokeでは上記のようなプログラムを駆使して新しいサービスを制作しています。気になることなどがあればコメントまたはTwitterでご連絡ください。

  • この記事を書いた人

楠 剛毅(goke)

個人開発から世界を変えるようなプロダクトづくりを目指しています

-プログラミング雑記