SVGの雪を降らせる
どうもGW前に風邪を何とか治して安堵しているfujiharaです。
SVGを調べていたら雪降らせたいって事で、JavaScript で降らせてみました。
(後から考えればSVGである必要はないのですが・・・)
背景
SVGについて調べていたら、丸い背景を作った段階で、季節関係なく雪を降らせたいと思いこの記事にいたりました。
HTML
まずはHTMLです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>snow</title>
<!--load library-->
<style type="text/css">
♯wrapper,
♯wrapper svg {
width:900px;
height:900px;
background-color:black;
display:block;
}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="/js/snow.js"></script>
</head>
<div id="wrapper">
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
</svg>
</div>
<body>
</body>
</html>
ここでは#wrapper と SVGの側だけ用意し、表示はJavaScriptで実行します。
JavaScript
次にJavaScriptです。
$(document).ready(function() {
/* 初期設定・表示 */
var svgWidth = $('svg').width(); //svg幅
var svgHeight = $('svg').height(); //svg高さ
var snowLength = 60; //雪の数
var yStart = -30; //動作開始位置(y)
var xInterval = parseInt(svgWidth/snowLength); //雪の間隔(x)
var snowR = parseInt(svgWidth/(3*snowLength)); //雪の半径
for (i=0;i<snowLength;i++) { //----②
var $circle = $('<circle>', {
'cx':xInterval + i*xInterval, // x
'cy':yStart, // y
'r':snowR, // 半径
'stroke':'gray', // 側の色
'stroke-width':2, // 側の幅
'fill':'white' // 内側の色
});
$circle.appendTo($('svg')); //SVGに代入
}
$("#wrapper").html($("#wrapper").html()); //-----③
var $circles = $('circle');
/* 雪を動かす */
$circles.each(function(i) {
var $target = $(this);
// ランダムパラメータ
var random = Math.ceil(i%10+i*Math.random()+Math.random()*7);
// 下に落ちる距離
var fallHeight = parseFloat(1.4/random);
// Opacity減少値
var reduceOpacity = parseFloat(0.0002/snowLength);
// 雪ごとに1ms単位でSVGを動かす
setInterval(function(random) {
// 下へ移動
$target.attr('cy', parseFloat($target.attr('cy'))+fallHeight);
// 徐々に透過させていく
$target.css('opacity', parseFloat($target.css('opacity')-reduceOpacity));
// SVGの下に30px以上言ったら、top位置に
if (svgHeight +30 < $target.attr('cy')) {
$target.attr('cy', yStart);
}
// Opacity を一定間隔でリセット
if ($target.css('opacity') < -0.03) {
$target.css('opacity',1);
}
},1);
});
});
初期設定で雪の数や、雪の半径、スタートポジション(高さ)を設定してあげています。
そして決定した値で SVG の 円を作成し、SVGに追加していきいます。
※ここで注意ですが、③のようにDOMを更新しないとSVGが表示されませんでした。
最後に各雪ごとに落ちる動作と透過度を変更してあげます。
改善の余地が多々ある部分です。
サンプルを前回作成したHeroku環境にアップしましたので是非見てください。
デザイン的なセンスがないので、いくらでも改良が可能だと思います。
まとめ
デザインやJavaScriptコードについては改良点が多々あるとは思います。
寒い季節ではないですが今年のウィンターシーズンに使用されてみてはいかがでしょうか?