suzy1031 / everyday-study-app

0 stars 0 forks source link

Recordの画面で目標時間(goals.target_time)を取得しプログレスバーを作成する #31

Closed suzy1031 closed 3 years ago

suzy1031 commented 3 years ago

'/record'で取得しているデータ

今週の達成度をプログレスバーで表示する為にgoal.target_timeを取得する => 最初SQL(ActiveRecord)でstudyテーブルとgoalテーブルをjoinして取得しようと試みた => 生SQLとActiveRecordを組み合わせて使う方法は?

'/api/v1/goal'にリクエスト投げればユーザーのgoal.target_timeを取得できるのでは?

<template>
+{{ this.goals.target_time }}
=> 15
</template>

<script>
# Record.vue
created() {
+this.$http.secured.get('/api/v1/goals')
+.then(response => {
+this.goals = response.data
# getするデータが無かった場合は0を代入
+if (this.goals.length == 0) {
+this.goals = []
+this.goals.target_time = 0
+} else {
+this.goals = response.data[0]
+}
+}
</script>

'/api/v1/studies'へのリクエストの後に'/api/v1/goals'へリクエストを投げる 取得したデータを使ってプログレスバーを作っていく

suzy1031 commented 3 years ago

参考 vue.jsを使って円のプログレスバーを作る

suzy1031 commented 3 years ago

上記の記事を参考に円プログレスバーを作成する

まず、学習時間(h)=> 達成率(%)への計算

現在の達成度 = 今週の学習時間 / 目標学習時間 * 100

次に、学習時間による角度の計算

現在の角度 = 360 * 現在の達成度 / 100

この2の計算結果を使いプログレスバーの現在の角度を求めていく

HTMLの構造は参考記事を参照

<template>
<div class="circle-position">
<!-- 右側の180度分の領域 -->
<div :style="rightAngle"></div> <= ここに計算式の結果をstyleに適用させる
<!-- 円中心のテキストの領域 -->
<!-- 左側の180度分の領域 -->
<div :style="leftAngle"></div> <= ここに計算式の結果をstyleに適用させる
</div>
</template>
# 学習時間から達成率への計算
+percentAchivement() {
# NaNが描画されてしまうので制御する
+if(this.goals.target_time == undefined) {
+return Const.INT_ZERO
+}
# 学習時間(h)を計算するメソッド「calcThisWeekTotal」を呼び出す
# Mathメソッドを使って目標学習時間÷学習時間×100で%を求める
+var percent = Math.floor(this.calcThisWeekTotal / this.goals.target_time * 100);
# 追記
# Math.floorで小数点以下を切り捨ててしまうと、1%未満が0%になってしまう為修正
-var percent = Math.floor(this.calcThisWeekTotal / this.goals.target_time * 100);
+var percent = this.calcThisWeekTotal / this.goals.target_time * 100;
-return percent
+return percent.toFixed(1)
+}

参考 javascriptで小数点以下の桁数を指定して表示する

# 1周360度なので、現在の角度がどの位置にあるのか計算する
# 360度×学習時間(%)÷100
+currentAngle() {
+return Math.floor(360 * this.percentAchivement / 100);
+}
# 右側半分への角度の適用
+rightAngle() {
# 引数に渡されたもののうち最小の値を返す
# currentAngleが180以上になった場合は180を返すので180度以上の角度にはならない
# Math.min => 270 > 180 なので180が渡される
+var angle = Math.min(this.currentAngle, 180);
+return {
+"transform": "rotate(" + angle + "deg)",
+}
+}
# 左側半分への角度の適用
+leftAngle() {
# Math.maxで引数に渡されたもののうち最大の値を返す
# currentAngleが180度を超える角度になっている場合は、その値を引数に渡す
# Math.minで引数に渡されたもののうち最小の値を返す
# Math.max => 270 - 180 = 90 90 > 0 なので90が渡される
# Math.min => 90 < 180 なので90が渡される値
+var angle = Math.min(Math.max(this.currentAngle-180, Const.INT_ZERO), 180);
+return {
+"transform": "rotate(" + angle +"deg)",
+}
+}

結果 rightAngle()の戻り値=180 leftAgle()の戻り値=90 180 + 90 = 270度