Edited at

CanvasでMaterial Design風ボタン

More than 3 years have passed since last update.

人のソースを見て勉強しようシリーズ第一弾。

CanvasでMaterial Design風ボタン(ボタンを押すと半透明な円が広がるアニメーションのやつ)を実装してる人がいたので、ソースを写経+ちょこっといじってみた。

CanvasでMaterial Design風ボタン

お手本ソース

sample1.gif

以下、解読したソースのまとめ。


HTML

<h1>Material Design Buttons</h1>

<section class="container">
<button class="btn color material-design" data-color="#004740">Button1</button>
<button class="btn btn-round color material-design" data-color="#ffffff">Button2</button>
<button class="btn btn-border color material-design" data-color="#004740">Button3</button>
<button class="btn btn-border btn-round color material-design" data-color="#00897b">Button4</button>
</section>


CSS

* {

box-sizing: border-box;
outline: none;
}

@import url(http://fonts.googleapis.com/css?family=Open+Sans:300);

body {
font-family: 'Open Sans', sans-serif;
font-size: 100%;
font-weight: 300;
line-height: 1.5em;
text-align: center;
backgrorund: #FFF;
}

h1 {
color: #666666;
font-size: 2rem;
line-height: 1.5em;
margin:2em 0 2em 0;
}

$color: #00897b;

.btn {
border: none;
color: white;
overflow: hidden;
margin: 1rem;
padding: 0;
text-transform: uppercase;
width: 150px;
height: 40px;
&.color {
background-color: $color;
}
}

.btn-border {
&.color {
background-color: transparent;
border: 2px solid $color;
color: $color;
}
}

.btn-round {
border-radius: 10em;
}

.material-design {
position: relative;
canvas {
opacity: 0.25;
position: absolute;
top: 0;
left: 0;
}
}

.container {
display: flex; //Flexboxコンテナーを作る
flex-direction: row; //HTMLの書き順で、左から右に配置
flex-wrap: wrap; //折り返しを許可
justify-content: center; //水平方向:中央揃え
align-items: flex-start; //垂直方向の:上揃え
align-content: center; //行:中央揃え
margin: 0 auto;
max-width: 46rem;
}


フォント

GoogleのWebフォントを使用 => Open Sans Light 300

@import url(http://fonts.googleapis.com/css?family=Open+Sans:300);

body {
font-family: 'Open Sans', sans-serif;
}


Flexbox

上下中央配置や、レスポンシブでの調整に便利なやつ。

(=普段IEを無視して書けることがそんなに無いから、毎回書き方を忘れてしまうやつ)

参考:今こそ未来!CSS3のFlexboxを基本から理解して、使い倒そう! | 株式会社LIG


JS

var canvas = {},

centerX = 0, //押されたx座標位置
centerY = 0, //押されたy座標位置
color = '', //描画色
containers = document.getElementsByClassName('material-design'),
context = {},
element = {},
radius = 0,

//requestAnimationFrame()でアニメーションさせる
//未対応のブラウザにはsetTimeout()
requestAnimFrame = function () {
return (
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
} (),

init = function () {
containers = Array.prototype.slice.call(containers); //オブジェクトを配列に変換
for (var i = 0; i < containers.length; i += 1) {
canvas = document.createElement('canvas');
containers[i].appendChild(canvas);
canvas.addEventListener('click', press, false);
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
},
//押されたときの処理
press = function (event) {
color = event.toElement.parentElement.dataset.color; // data-colorの値を取得
element = event.toElement;
context = element.getContext('2d');
radius = 0; //円の大きさを初期値に
centerX = event.offsetX; //押されたx座標位置
centerY = event.offsetY; //押されたy座標位置
context.clearRect(0, 0, element.width, element.height); //矩形をクリア
draw();
},
//描画更新処理
draw = function () {
context.beginPath(); //描画開始
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); //正円の描画
context.fillStyle = color;
context.fill(); //パス図形を描画
radius += 8; //円の描画スピード
if (radius <= element.width) {
requestAnimFrame(draw); //矩形の幅を超えるまで円を描画
} else {
context.clearRect(0, 0, element.width, element.height);
}
};

init();