イントロダクション
記事「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_rate) {
this.interval = interval; // 更新間隔 (ミリ秒)
this.add_rate = add_rate; // 1フレームあたり、グラフが増加する割合(0~1.0)
}
/*
数値の有効桁数を取得する
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 = animationCount * graphValues[i].value * graphAnimationParam.add_rate;
// --- 表示のための有効桁数を計算 ----------------------------------------
// 元々の数値の有効桁数を基本的に使用するが、
// 元々の数値の有効桁数がアニメーションを行うために十分でなければ、
// アニメーション用の有効桁数を数値の表示用に設定する
var org_value_str = graphValues[i].value.toString();
if (/[^.]/.test(org_value_str)) { // 整数の場合、すべての桁を有効桁にするため、最後に . を追加
org_value_str += ".";
}
// 元々の数値の有効桁数を取得
var org_significantFigures = getSignificantFigures(org_value_str);
// 増加割合の指数部を取得
var add_rate_exponent = getExponent(graphAnimationParam.add_rate);
var view_significantFigures; // 表示に使用する有効桁数
// 元々の数値の有効桁数が、アニメーションに必要な有効桁数
// (有効桁数は (-1 * 増加割合の指数部) + 1 以上なければ増加を反映させられない) を割っていたら、
// アニメーションに必要な有効桁数を表示に使用する有効桁数に設定する
if (org_significantFigures < -add_rate_exponent + 1) {
view_significantFigures = -add_rate_exponent + 1;
} else {
view_significantFigures = org_significantFigures;
}
temp_graphValues[i].value = Number(temp_graphValues[i].value.toPrecision(view_significantFigures));
// 上限を超え他場合は最大値を設定
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();
}
/*
グラフを作成する
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)
);
}
//-->
</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引数はグラフを挿入する要素の id です。
各自の環境に応じて、適切な id を設定してください。
(ここでは、<div id="graph-object"></div> 内に棒グラフが挿入されます。)
第2引数はグラフのデータです。
第3引数はグラフの各値のタイトルです。
任意の値を設定してください。
第4引数はグラフの書式設定です。
任意の値を設定してください。
第5引数はアニメーションの設定です。
任意の値を設定してください。
結果
以下のように、増加割合固定でアニメーションする横向きの棒グラフが作成できます。「アニメーション実行」ボタンをクリックすると、アニメーションを開始できます。
なお、今回はアニメーションの実行開始のトリガーをボタンクリック時としましたが、ページ読み込み完了時や要素が画面内に表示されたときなど、いろいろなトリガーが考えられます。
最適なトリガーを検討してみてください。
コメントを投稿 (ここをクリックしてコメント投稿フォームを表示)
コメント投稿機能について