LoginSignup
3
3

More than 5 years have passed since last update.

【コメント欄】+-の比率でコメントの色・大きさが動的に変わるUIの実装

Last updated at Posted at 2018-07-30

コメント欄にup、downボタンとそれぞれの比率のバーを設置。

そのコメントがどれだけ支持されているかが一目で分かるようなUIを作成したので
何を考えていたのか、どう実装したかを解説。

↓実装した先のサイト
なろう廃人のすすめ

コメントクラス付け替え (1) (1).gif

screenshot-2018-07-28-215743.PNG

何を考えていたのか

1、コメントがどれだけ支持されているかを可視化

up,downの比率により、読者の支持を可視化。
コメントを読むべきか読まなくて良いかが分かるようにして
見る人の脳内コストの削減をしたかった。

up,downの比率によってコメントのクラスを付け替えて
色、大きさが変わるようにしてパッと入ってくるようにしている。

2、画面から反応が返ってくるようにしてサイトを楽しくする

画面から反応が返ってくることによって
参加している感を出して、
【参加したくなるサイト】を目指した。

処理の流れ

1、ユーザがボタンを押す
2、jqueryでカウント数を増やす・ボタンを押せなくする
3、ajaxでrailsのコントローラを呼んでコメントのupカラムを+1する
4、ajaxの処理がsuccessで返ってきたときは、バーのwidthをアニメーションで変更する
5、画面からカウント数の比率を取得して、コメントのクラスを付け替える

実際の処理

html部分

【ポイント】
・up_down_rateを取得、comment-level-1~5のクラス分けをしてコメントの見た目を変更
・バーの部分は灰色の背景、青い前面の2つを用意して、青い前面のwidthをup_down_rateの%により制御

_card.html.haml
.card.my-2.mx-0.border-0
  .text-muted.small.p-2
    名前: #{comment.name}
  -# up,downの比率を取得
  - up_down_rate = ((comment.up.to_f) / (comment.up.to_f + comment.down.to_f)) * 100
  -# 比率によりクラスを分ける
  - if    90 <= up_down_rate
    .p-2.comment.comment-level-5
      #{comment.comment}
  - elsif 70 <= up_down_rate  && up_down_rate < 90
    .p-2.comment.comment-level-4
      #{comment.comment}
  - elsif 50 <= up_down_rate  && up_down_rate < 70
    .p-2.comment.comment-level-3
      #{comment.comment}
  - elsif 30 <= up_down_rate  && up_down_rate < 50
    .p-2.comment.comment-level-2
      #{comment.comment}
  - else
    .p-2.comment.comment-level-1
      #{comment.comment}
  .container.mb-0.mt-3.pr-1
    .row.mx-auto.d-flex.justify-content-end.comment-bottom-content
      %p.up-contents.mb-0
        %a.comment-rating-button.comment-rating-button-up.d-inline-flex.justify-content-center.font-weight-bold{} +
        %br
        %span{class: "comment-count comment-count-up mb-0"}
          - if comment.up != nil
            #{comment.up}
          - else
            0
      -# 0で割れないので、分母が0の時で場合分け
      - if (comment.up.to_f + comment.down.to_f) != 0
        .comment-rating-bar.justify-content-center.m-2.mt-3
          -# up, downの比率で青いバーの長さを決定する
          .comment-rating-bar-up{style: "width: #{( (comment.up.to_f) / (comment.up.to_f + comment.down.to_f) ) * 100}%;"}
      - else
        .comment-rating-bar.justify-content-center.m-2
          -# up, downがどちらも0の時は50%にする
          .comment-rating-bar-up{style: "width: 50%;"}
      %p.down-contents.mb-0
        %a.comment-rating-button.comment-rating-button-down.d-inline-flex.justify-content-center.font-weight-bold{} -
        %br
        %span{class: "comment-count comment-count-down mb-0"}
          - if comment.down != nil
            #{comment.down}
          - else
            0
      .comment-id{style: "display:none"}
        #{comment.id}

1、ユーザがボタンを押す

コード前半部分 jqueryでcss弄る部分

・up,downボタンのクラスをpushedに付け替えて、動かないようにする
・upのcountを+1する。

application.js
  $(".comment-rating-button-up").click(function(){
    //upを押された時に、upとdownどちらも動かないようにクラスを付け替える  TODO セレクターがダサいから直す。
    $(this).removeClass("comment-rating-button-up").addClass("comment-rating-button-up-pushed");
    var down_button = $(this).parent().next().next().children(".comment-rating-button-down");
    down_button.removeClass("comment-rating-button-down").addClass("comment-rating-button-down-pushed");

    var old_up_count = parseInt($(this).siblings(".comment-count-up").text());
    $(this).siblings(".comment-count-up").text(old_up_count + 1);

コード中盤 ajax送信部分

コメントのidをhiddenでhtmlに埋め込んであるので、
それをjqueryで取得してajaxで送る。

application.js
    $.ajax({
        url: "comment_count_up",
        data: { id : parseInt($(this).parent().siblings(".comment-id").text()) },
        dataType: "html",
controller.rb
  def comment_count_up
      @comment = Comment.find_by(id: params[:id])
      if @comment.up == nil
        @comment.update(up: 1)
      else
        @comment.update(up: @comment.up + 1)
      end
  end
routes.rb
  #resourcesの上に書く
  get "novels/comment_count_up"

コード後半 コメントのクラス付け替え、バーの長さ変更

・up_down_rateを最初に取得
・rateに応じてcomment-levelを決定
・元のcomment-levelのクラスを削除して、上で定義したcomment-levelをつける

application.js

        success: (data) => {
          var up_count   = parseInt($(this).parents(".comment-bottom-content").children(".up-contents").children(".comment-count-up").text());
          var down_count = parseInt($(this).parents(".comment-bottom-content").children(".down-contents").children(".comment-count-down").text());
          var sum_count = up_count + down_count
          var up_down_rate = ((up_count/sum_count)*100)
          // 青いバーのwidthをanimeteを使って変更
          $(this).parent().next().children(".comment-rating-bar-up").animate({width:up_down_rate + "%"},200);

          // rateに応じてcomment_levelを定義
          switch(true) {
              case 90 <= up_down_rate:
                  var comment_level = "comment-level-5";
                  break;
              case 70 <= up_down_rate && up_down_rate < 90 :
                  var comment_level = "comment-level-4";
                  break;
              case 50 <= up_down_rate && up_down_rate < 70 :
                  var comment_level = "comment-level-3";
                  break;
              case 30 <= up_down_rate && up_down_rate < 50 :
                  var comment_level = "comment-level-2";
                  break;
              case up_down_rate < 30 :
                  var comment_level = "comment-level-1";
                  break;
              default:
                  alert("0より小さいです");
          }
          //前方一致でクラスを削除  参考:jQueryの.removeClass()で「特定の文字列で始まるclass」をすべて削除する
          //comment_levelのクラスを付け加える
          $(this).parents(".card").children(".comment").removeClass(function(index, className) {
              return (className.match(/\bcomment-level-\S+/g) || []).join(' ');
          }).addClass(comment_level);

          console.log("正常にup完了")
        },

javascriptコード全体(upボタンを押された場合)

application.js
//upボタン押された時
$(document).on('turbolinks:load',function(){
  $(".comment-rating-button-up").click(function(){
    //upを押された時に、upとdownどちらも動かないようにクラスを付け替える  TODO セレクターがダサいから直す。
    $(this).removeClass("comment-rating-button-up").addClass("comment-rating-button-up-pushed");
    var down_button = $(this).parent().next().next().children(".comment-rating-button-down");
    down_button.removeClass("comment-rating-button-down").addClass("comment-rating-button-down-pushed");

    var old_up_count = parseInt($(this).siblings(".comment-count-up").text());
    $(this).siblings(".comment-count-up").text(old_up_count + 1);
    $.ajax({
        url: "comment_count_up",
        data: { id : parseInt($(this).parent().siblings(".comment-id").text()) },
        dataType: "html",
        success: (data) => {
          //TODO function get_up_down_rateに切り出ししたい
          var up_count   = parseInt($(this).parents(".comment-bottom-content").children(".up-contents").children(".comment-count-up").text());
          var down_count = parseInt($(this).parents(".comment-bottom-content").children(".down-contents").children(".comment-count-down").text());
          var sum_count = up_count + down_count
          var up_down_rate = ((up_count/sum_count)*100)
          $(this).parent().next().children(".comment-rating-bar-up").animate({width:up_down_rate + "%"},200);

          switch(true) {
              case 90 <= up_down_rate:
                  var comment_level = "comment-level-5";
                  break;
              case 70 <= up_down_rate && up_down_rate < 90 :
                  var comment_level = "comment-level-4";
                  break;
              case 50 <= up_down_rate && up_down_rate < 70 :
                  var comment_level = "comment-level-3";
                  break;
              case 30 <= up_down_rate && up_down_rate < 50 :
                  var comment_level = "comment-level-2";
                  break;
              case up_down_rate < 30 :
                  var comment_level = "comment-level-1";
                  break;
              default:
                  alert("0より小さいです");
          }
          //前方一致でクラスを削除  参考:jQueryの.removeClass()で「特定の文字列で始まるclass」をすべて削除する
          $(this).parents(".card").children(".comment").removeClass(function(index, className) {
              return (className.match(/\bcomment-level-\S+/g) || []).join(' ');
          }).addClass(comment_level);

          console.log("正常にup完了")
        },
        error: function(data) {
          console.log('upをつけるのに失敗しています');
        }
    });
  });
});

CSS

ポイント
・押した後のボタンはpointer-events: none;を入れて押せなくする。

novels.scss

.comment-rating-button {
  display: block;
  width: 30px;
  height: 30px;
  border-radius: 15px;
  font-size: 25px;
  padding-top: 5px;
  margin-bottom: 1px;
  // ユーザーがボタンのテキストをハイライトできないようにする
  -webkit-user-select:none;
  -moz-user-select:none;
  -ms-user-select:none;
  user-select:none;
}
.comment-rating-button-up{
  background: #73DCFF;
  box-shadow: 0 2px 0 #2a82a3;
  color: white !important;
  &:hover{
    background-color: #2a82a3 !important;
  }
}
.comment-rating-button-up-pushed{
  background-color: #2a82a3 !important;
  box-shadow: 0 2px 0 #2a82a3;
  color: white !important;
  pointer-events: none;
  &:hover{
    background-color: #2a82a3 !important;
  }
}



.comment-rating-button-down{
  background: #BDBDAE;
  box-shadow: 0 3px 0 #79796A;
  color: white !important;
  &:hover{
    background-color: #79796A !important;
  }
}
.comment-rating-button-down-pushed{
  background-color: #79796A !important;
  box-shadow: 0 3px 0 #79796A;
  color: white !important;
  pointer-events: none;
  &:hover{
    background-color: #79796A !important;
  }
}

.comment-rating-bar{
  border-radius: 20px;
  background-color: #DFDFD0;
  height: 15px;
  width: 150px;
  .comment-rating-bar-up{
    border-radius: 20px;
    background-color: #73DCFF;
    height: 15px;
    width: 100px;
  }
}

.comment-count{
  font-size: 12px;
  margin-left: 8px;
}
.comment-count-up{
  color: #5DB2CD !important;
}
.comment-count-down{
  color: #99998C !important;
}

comments.scss
// up_down_rate = 90%~
.comment-level-5{
  font-size: 150%;
  font-weight: bold;
  color: red;
}
// up_down_rate = 70~90%
.comment-level-4{
  font-size: 130%;
  font-weight: bold;
}
// up_down_rate = 50~70%
.comment-level-3{
  font-weight: bold;
}
// up_down_rate = 30=50%
.comment-level-2{
}
// up_down_rate = ~ 30%
.comment-level-1{
  color: #777;
}
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3