jQueryでマテリアルデザイン風味なウェーブ(リップル)ボタン

うちのブログやmodellaxでマテリアルデザインを行うときに作ったなんちゃってウェーブボタン(リップルボタンとも言う)のコード。

前々から公開する公開するといいつつ、おざなりになっていたので、自分の腹の中に置いておいても腐るだけなので、さっさと公開してしまおうと思う。

 

動作は自分のブログを見てもらえばわかると思うが、ボタンを押下したときにGoogle Chromeよろしく、押下地点からウェーブが広がるという動作。

 

↓こんなやつ。

 

ボタン

 

作成当時はWeb系でのマテリアルデザインを採用しているサイトはあまりなかった(今も少ないけど)。

少ない中でも多かったのがCSSフレームワーク全体で動かしているサイト。

CSSフレームワークでの制作はほぼほぼどこでもやっているものであるが、CSSフレームワークを余り使わない派の自分にとってはコレはちょっと不都合。というか、CSSフレームワークを組み込まなくても、どうせライブラリに頼るとしても極々最小限で単独で動かせるようなものが欲しい。

 

自分と同じようにこのボタン動作を作っている変態さんもいたが、PCとスマホまたぐと好みの動きをしてなかったり、組み込み方の形式もなんか俺の考えてるのとはちょっと違う。

 

ぶっちゃけ、ありものを使い回せればそれに越したことはないと思っていたんだけどね。

そんな甘いお話は当然ないわけだ。めんどくさすぎて絶望した。魔法使いのライダーさんは俺の絶望を希望に変えには来てくれなかった。

 

じゃあ自分で作るか!ということでGoogle Chromeのその他ブックマークフォルダを連打して、その動作をずっと見ること15分。

正直、このときの自分はハタから見たら気が触れたように見えたと思う。

だって、アレだぜ?クリックゲーでも無いのにひたすらのブラウザのボタン連打。・・・正直、自分でもドン引きした。

 

まぁそんなこんなで、それっぽいものを作ってみた。

jQueryのスクリプトとCSS3利用のスタイルね。

 

スクリプトコード

以下をripple.jsとでもしておく。

この記事の下の方に関連ファイルをまとめてDLできるようにしてあるけど。

/* Script Ripple Button from CattleMute */
 
(function($){
 
  $.fn.ripple = function(options){
    var option = {
    };
    var static = {
      canvas: 'ripple-canvas',
      wave: 'ripple-wave'
    };
    var config = $.extend(option, options);
    var inc = $(this), time = null;
    var ua = window.navigator.userAgent.toLowerCase();
 
    var ripple = (function(){
      return{
        init: function(){
          this.clip();
        },
        calc: function(e, target){
          var plate = {
            rideX: e.pageX - target.offset().left,
            rideY: e.pageY - target.offset().top,
            sizeX: target.outerWidth(),
            sizeY: target.outerHeight(),
            shapeX: 0,
            shapeY: 0
          };
 
          plate.shapeX = plate.rideX - (plate.sizeX / 2);
          plate.shapeX = (plate.shapeX < 0) ? plate.shapeX * -1 : plate.shapeX;
          plate.shapeX = (plate.sizeX + plate.shapeX) * 1.414;
 
          plate.shapeY = plate.rideY - (plate.sizeY / 2);
          plate.shapeY = (plate.shapeY < 0) ? plate.shapeY * -1 : plate.shapeY;
          plate.shapeY = (plate.sizeY + plate.shapeY) * 1.414;
 
          return plate;
        },
        draw: function(e, target){
          var plate = this.calc(e, target);
          var size = (plate.shapeX <= plate.shapeY) ? plate.shapeY :  plate.shapeX;
          var margin = size / 2 * -1;
          target.children('.' + static.canvas).remove();
          target.append('');
          target.children('.' + static.canvas).append('');
          clearTimeout(time);
          time = setTimeout(function(){
            target.children('.' + static.canvas).children('.' + static.wave).css({
              'transform': 'scale(1, 1)'
            });
          }, 1 / 1000);
        },
        hidden: function(target){
          time = setTimeout(function(){
            target.children('.' + static.canvas).children('.' + static.wave).css({
              'opacity': 0
            });
            clearTimeout(time);
          }, 1 / 1000);
        },
        dcase: function(){
          if(ua.indexOf('windows') > -1 || ua.indexOf('macintosh') > -1){
            return true;
          }else{
            return false;
          }
        },
        clip: function(){
          inc.bind({
            mouseout: function(){
              if(ripple.dcase()){
                ripple.hidden($(this));
              }
            },
            mousedown: function(e){
              if(ripple.dcase()){
                if(e.which === 1){
                  ripple.draw(e, $(this));
                }
              }
            },
            mouseup: function(e){
              if(ripple.dcase()){
                if(e.which === 1){
                  ripple.hidden($(this));
                }
              }
            },
            touchstart: function(e){
              if(!ripple.dcase()){
                ripple.draw(e.originalEvent.touches[0], $(this));
              }
            },
            touchend: function(e){
              if(!ripple.dcase()){
                ripple.hidden($(this));
              }
            }
          });
        }
      };
    })();
 
    ripple.init();
 
    return(this);
  };
 
})(jQuery);

 

スタイル

以下をripple.cssとでもしておく。

この記事の下の方に関連ファイルをまとめてDLでk(ry

/* Style Ripple Button from CattleMute */
 
.ripple{
  -webkit-tap-highlight-color:rgba(0,0,0,0);
  overflow:hidden;
  position:relative;
  z-index:10;
  display:inline-block;
}
.ripple::after{
  content:"";
  display:block;
  position:absolute;
  width:102%;
  height:102%;
  top:-1%;
  left:-1%;
  right:-1%;
  bottom:-1%;
  z-index:20;
}
 
.ripple-canvas{
  display:block;
  position:absolute;
  width:100%;
  height:100%;
  top:0;
  left:0;
  right:0;
  bottom:0;
  z-index:10;
  overflow:hidden;
}
.ripple-wave{
  display:block;
  position:absolute;
  margin-top:0;
  margin-left:0;
  width:0;
  height:0;
  top:0;
  left:0;
  z-index:10;
  border-radius:50%;
  transition-duration:1.5s;
  transition-timing-function:cubic-bezier(0.215,0.61,0.355,1);
  transform:scale(0,0);
}
.ripple-wave{
  background-color:#000000;
  opacity:0.25;
}

 

HTML

上記を外部ファイルにして、HTML側では以下のようにファイルを読み込み。

この記j(ry

<!-- jQuery -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js" type="text/javascript"></script>
 
<!-- ripple.js -->
<script src="ripple.js" type="text/javascript"></script>
 
<!-- ripple.css -->
<link href="ripple.css" type="text/css" rel="stylesheet" />
 
<!-- Start script -->
<script type="text/javascript">
$(document).ready(function(){
  $('.ripple').ripple();
});
</script>

 

後は、aタグなどにclass=”ripple”を付与したらマテリアルデザイン風味なウェーブ(リップル)ボタンのアクションが得られると思う。

 

上記の単独HTMLでの動作サンプルはここからどーぞ。

 

・・・まぁ、いらない人にいらないでしょう。でも、一応、ダウンロードできるようにしておきます。

こんなつたないコードでよければ、ダウンロードはここからどうぞ。

 

PS:

つーか、以前にも似たような記事書いてたけど、あっちのコードは実用に耐えない習作だったような気もする。

あとから見たらスマホ関係の動作がとてつもなく不安定だったわ。

・・・というわけで以上!

 

カテゴリ

この記事のコメント

コメントはないです。

コメントを残す

メールアドレスが公開されることはありません。