イントロダクション
記事「HTMLとJavaScriptで単純なアニメーション付きの横向き棒グラフを作成する-アニメーションパターン:増加量固定」では、Webページ上に単純な横向きの棒グラフを JavaScript を使って作成し、全てのグラフの増加量固定でアニメーションする方法を紹介しました。今回は、その時のコードを修正して、横向きの棒グラフがぐーん!と伸びるようなアニメーションをするようにしてみます。
コード
以下のコードをグラフを表示させたい<body>内の任意の位置に貼り付けてください。(なお、<script type="text/javascript"></script>の部分は<head>内に設置することもできます。)
<form> <input type="button" value="アニメーション実行" onclick="startAnimation()" /> </form> <div id="graph-object"></div> <script type="text/javascript"> <!-- // 系列名と値 function CGraphValue(name, value) { this.name = name; // 系列名 this.value = value; // 値 } // グラフのデータ var graphValues = []; graphValues.push(new CGraphValue("系列1", 100)); graphValues.push(new CGraphValue("系列2", 200)); graphValues.push(new CGraphValue("系列3", 215)); graphValues.push(new CGraphValue("系列4", 105)); graphValues.push(new CGraphValue("系列5", 118)); // グラフの生成パラメータ function CGraphGenerateParam(pixel_per_value, graph_border_style, graph_border_width, graph_border_color, graph_background_color, graph_height) { this.pixel_per_value = pixel_per_value; // 棒グラフの単位値(1)に対応する長さ (ピクセル) // グラフの値が 1 の場合の、グラフの長さです。 // グラフの値 * pixel_per_value がグラフの長さになります this.graph_border_style = graph_border_style; // 棒グラフの棒のボーダーのスタイル this.graph_border_width = graph_border_width; // 棒グラフの棒のボーダーの幅 this.graph_border_color = graph_border_color; // 棒グラフの棒のボーダーの色 this.graph_background_color = graph_background_color; // 棒グラフの棒の背景色 this.graph_height = graph_height; // 棒グラフの高さ } // グラフのアニメーション用パラメータ function CGraphAnimationParam(interval, add_base_value, pow_factor) { this.interval = interval; // 更新間隔 (ミリ秒) this.add_base_value = add_base_value; // 1フレームあたり、グラフに加算する基本値 this.pow_factor = pow_factor; // 増加量 = add_base_value * (フレーム数 の pow_factor 乗) } /* 数値の有効桁数を取得する str : 10進の数値を保持したテキスト */ function getSignificantFigures(str) { // 不要な文字を消す(符号) str = str.replace(/[+-]/g, ""); // 数値の終わりの 0 の列を消す // 1000 の場合 000 を消す // 1.000 の場合 000 は消さない if (!(/^\d*\./.test(str))) { str = str.replace(/0+$/g, ""); } // 小数点を消す str = str.replace(/\./g, ""); // 数値の先頭の 0 の列を消す str = str.replace(/^0+/g, ""); // 指数形式の指数部を消す str = str.replace(/[eE]\d+/g, ""); return str.length; } /* 数値の指数部を取得する */ function getExponent(value) { var value_exponential_str = value.toExponential(); // 数値を指数形式の文字列へ変換 var exponent_str = value_exponential_str.replace(/^.*[eE]/, ""); // 実数部からeの部分までを削除 return Number(exponent_str); } /* アニメーションするグラフを作成する id_graph : グラフを設定する要素の id graphValues : グラフの系列データの配列 (CGraphValueのArray) valuesName : データの名前 (CGraphValue) graphGenParam : グラフの生成パラメータ (CGraphGenerateParam) graphAnimationParam : グラフのアニメーション用パラメータ */ function createAnimationGraph(id_graph, graphValues, valuesName, graphGenParam, graphAnimationParam) { // アニメーション用のグラフデータ作成 var temp_graphValues = []; for (var i = 0; i < graphValues.length; i++) { temp_graphValues.push(new CGraphValue(graphValues[i].name, 0)); } // アニメーションを実行 var animationCount = 0; // アニメーションカウンタ function runAnimation() { createGraph(id_graph, temp_graphValues, valuesName, graphGenParam); // 次のフレーム用のデータを作成 var updateFlag = false; // 情報が更新されたかどうか for (var i = 0; i < graphValues.length; i++) { if (graphValues[i].value > temp_graphValues[i].value) { temp_graphValues[i].value += graphAnimationParam.add_base_value * Math.pow(animationCount, graphAnimationParam.pow_factor); // アニメーションと表示のための有効桁数にフォーマットした値を取得 temp_graphValues[i].value = getAnimationAndViewFormatValue( graphValues[i].value, temp_graphValues[i].value, graphAnimationParam.add_base_value * Math.pow(1, graphAnimationParam.pow_factor)); if (temp_graphValues[i].value > graphValues[i].value) { // 上限を超え他場合は最大値を設定 temp_graphValues[i].value = graphValues[i].value; } updateFlag = true; } } // データの更新が確認されたら、次のフレームをタイマにセット if (updateFlag) { animationCount++; setTimeout(runAnimation, graphAnimationParam.interval); } } runAnimation(); } /* アニメーションと表示のための有効桁数にフォーマットした値を取得 org_value : 元の値 value : アニメーションにより変化中の値 add_min_rate : 最小加算値 */ function getAnimationAndViewFormatValue(org_value, value, add_min_value) { // --- 表示のための有効桁数を計算 ---------------------------------------- // 元々の数値の有効桁数を基本的に使用するが、 // 元々の数値の有効桁数がアニメーションを行うために十分でなければ、 // アニメーション用の有効桁数を数値の表示用に設定する var org_value_str = org_value.toString(); if (/[^.]/.test(org_value_str)) { // 整数の場合、すべての桁を有効桁にするため、最後に . を追加 org_value_str += "."; } // 元々の数値の有効桁数を取得 var org_significantFigures = getSignificantFigures(org_value_str); // 増加割合の指数部を取得 var add_rate_exponent = getExponent(add_min_value); var view_significantFigures; // 表示に使用する有効桁数 // 元々の数値の有効桁数が、アニメーションに必要な有効桁数 // (有効桁数は (-1 * 増加割合の指数部) + 1 以上なければ増加を反映させられない) を割っていたら、 // アニメーションに必要な有効桁数を表示に使用する有効桁数に設定する if (org_significantFigures < -add_rate_exponent + 1) { view_significantFigures = -add_rate_exponent + 1; } else { view_significantFigures = org_significantFigures; } return Number(value.toPrecision(view_significantFigures)); } /* グラフを作成する id_graph : グラフを設定する要素の id graphValues : グラフの系列データの配列 (CGraphValueのArray) valuesName : データの名前 (CGraphValue) graphGenParam : グラフの生成パラメータ (CGraphGenerateParam) */ function createGraph(id_graph, graphValues, valuesName, graphGenParam) { // グラフ 出力 var obj_graph = document.getElementById(id_graph); var graph_html = "<table>"; graph_html += "<tr><td>" + valuesName.name + "</td><td>" + valuesName.value + "</td></tr>"; for (var i = 0; i < graphValues.length; i++) { var width = graphGenParam.pixel_per_value * graphValues[i].value; var graph_div = ""; if (graphValues[i].value > 0) { graph_div = "<div style=\"border-style:" + graphGenParam.graph_border_style + ";border-width:" + graphGenParam.graph_border_width + ";border-color:" + graphGenParam.graph_border_color + ";background-color:" + graphGenParam.graph_background_color + ";width:" + width + "px;height:" + graphGenParam.graph_height + ";\"></div>"; } graph_html += "<tr><td>" + graphValues[i].name + "</td><td><table><tr><td>" + graph_div + "</td><td>" + graphValues[i].value + "</td></tr></table></td></tr>"; } graph_html += "</table>"; obj_graph.innerHTML = graph_html; } // グラフのアニメーションを開始 function startAnimation() { // 最大のカウントを取得する var max_value = 0; for (var i = 0; i < graphValues.length; i++) { if (graphValues[i].value > max_value) { max_value = graphValues[i].value; } } // グラフの単位値あたりの長さを計算 var max_width = 300; // グラフの最大の長さ var pixel_per_value = max_width / max_value; // グラフの単位値あたりの長さ // アニメーショングラフの作成 createAnimationGraph( "graph-object", graphValues, new CGraphValue("系列名", "値"), new CGraphGenerateParam(pixel_per_value, "solid", "1px", "#999999", "#cccccc", "14px"), new CGraphAnimationParam(1000 / 60, 0.01, 1.8) ); } //--> </script>
以下の部分が棒グラフのデータです。
// グラフのデータ
var graphValues = [];
graphValues.push(new CGraphValue("系列1", 100));
graphValues.push(new CGraphValue("系列2", 200));
graphValues.push(new CGraphValue("系列3", 215));
graphValues.push(new CGraphValue("系列4", 105));
graphValues.push(new CGraphValue("系列5", 118));
任意の値を設定してください。
以下の部分で、アニメーションするグラフの生成処理を呼び出しています。
// アニメーショングラフの作成
createAnimationGraph(
"graph-object",
graphValues,
new CGraphValue("系列名", "値"),
new CGraphGenerateParam(pixel_per_value, "solid", "1px", "#999999", "#cccccc", "14px"),
new CGraphAnimationParam(1000 / 60, 0.01, 1.8)
);
第1引数はグラフを挿入する要素の id です。
各自の環境に応じて、適切な id を設定してください。
(ここでは、<div id="graph-object"></div> 内に棒グラフが挿入されます。)
第2引数はグラフのデータです。
第3引数はグラフの各値のタイトルです。
任意の値を設定してください。
第4引数はグラフの書式設定です。
任意の値を設定してください。
第5引数はアニメーションの設定です。
任意の値を設定してください。
CGraphAnimationParam の 第2引数と、第3引数を調整することで、棒グラフがぐーんと伸びるときの動作を調整できます。
結果
以下のように、全てのグラフが増加量固定でぐーん!と伸びるアニメーションをする横向きの棒グラフが作成できます。「アニメーション実行」ボタンをクリックすると、アニメーションを開始できます。
なお、CGraphAnimationParam の add_base_value と pow_factor をテキストボックスから入力して設定できるようにしましたので、いろいろな値でアニメーションの変化を試してみてください。
なお、今回はアニメーションの実行開始のトリガーをボタンクリック時としましたが、ページ読み込み完了時や要素が画面内に表示されたときなど、いろいろなトリガーが考えられます。
最適なトリガーを検討してみてください。
コメントを投稿 (ここをクリックしてコメント投稿フォームを表示)
コメント投稿機能について