口コミサイトなどでよく見かける星形レーティング。
RateYo!というプラグインは、動きが軽快で使える関数もなかなかあり満足な動作をしてくれます(ただし、IE9以上)。他のプラグインではあまりない機能として小数点2桁までつけることもできます。
しかしスマホは一応の動作はしてくれるもののあまり満足の行く動作ではありません。指でスライドして点数がつけられないので、細かい点数をつけずらい、という難点があります。せっかく小数点2桁までつけられるのにもったいない!!と思いました。
そこで、スマホで指でスライドさせて点数をつける動作に対応してみました。やり方は下で書いています。
http://prrashi.github.io/rateYo/の右上にあるGitHubのリンクからダウンロードして以下の指定で基本の動きが出来ます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ・・・ <link rel="stylesheet" type="text/css" media="all" href="/sample/rateyo/jquery.rateyo.min.css"> <script type="text/javascript" src="/sample/rateyo/jquery.rateyo.js"></script> <script type="text/javascript"> (function ($) { 'use strict'; $("#rateYo").rateYo(); })(jQuery); </script> ・・・ <div id="rateYo"></div> ・・・ |
オプションの種類や書き方も丁寧に書かれています。英語が読めなくても実行例を付けてくれているのでなんとなく分かると思います。
●例1:「初期値を★2.5にして、0.5区切りでしか点数をつけさせない」。
1 2 3 4 5 6 7 8 9 10 | ・・・ $("#rateYo02").rateYo({ rateing: 2.5, halfStar: true }); ・・・ <div id="rateYo"></div> ・・・ |
●例2:「最高★7つで、★のサイズが40pxで、小数点2桁対応で、★の数に応じて色が変わる」。(※製作者のGitHubのexampleにある「color.js」を利用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <script type="text/javascript" src="/sample/rateyo/color.js"></script> ・・・ (function ($) { 'use strict'; var getColor = function (options, rating) { var minValue = options.minValue, maxValue = options.maxValue, halfValue = (options.maxValue - options.minValue)/2, startColor = "#c0392b", endColor = "#f1c40f"; var perentageCovered = ((rating - minValue)/maxValue)*100; var newColor = window.coolColor.pickColor(startColor,endColor, perentageCovered); return newColor; }; var changeRating = function (rating) { var options = $(this).rateYo("option"); var newColor = getColor(options, rating); $(this).rateYo("option", "ratedFill", newColor); }; var args = { starWidth: "40px", numStars: 7, maxValue: 7, minValue: 0, precision: 2, onChange: function (rating, rateYoInstance) { var pos = (-13) + rating * 40; $(this).next().text(rating).css({left : pos}); } }; // start var $rateYo = $("#rateYo03").rateYo(args).on("rateyo.change", function (e, data) { changeRating.apply(this, [data.rating]); }).on("rateyo.set", function (e, data) { changeRating.apply(this, [data.rating]); var rate = parseFloat(data.rating); $(this).parents('.rating-box').find('.rating-input').val(data.rating); }); })(jQuery); |
いよいよ本題のスマホ対応の話です。
コードを修正しやすいように、プラグインをダウンロードするときに、jquery.rateyo.min.jsではなく、jquery.rateyo.jsをダウンロードします。
1.スマホ用の計算関数を作成
スマホで、指を付けた瞬間から指を離すまでの動きは、PCでオンマウスした時の動きと同じで良いので、「onMouseEnter」関数をコピーして「onTouchMove」関数という新たな関数を作ります。
指を離した瞬間の動きは、PCでクリックした動きと同じで良いので、「onMouseClick」関数をコピーして「onTouchEnd」関数という新たな関数を作ります。
同じで良いとは言っても、PCとスマホで少し処理が違うところがあるので、そこを修正します。
実際に追加するのは以下のコードでOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | (追加) ・・・ function calculateRatingTouch (e) { var position = $normalGroup.offset(), nodeStartX = position.left, nodeEndX = nodeStartX + $normalGroup.width(); var maxValue = options.maxValue; var pageX = e.originalEvent.changedTouches[0].pageX; var calculatedRating = 0; if(pageX < nodeStartX) { calculatedRating = minValue; }else if (pageX > nodeEndX) { calculatedRating = maxValue; }else { var calcPrcnt = ((pageX - nodeStartX)/(nodeEndX - nodeStartX)); if (spacing > 0) { calcPrcnt *= 100; var remPrcnt = calcPrcnt; while (remPrcnt > 0) { if (remPrcnt > percentOfStar) { calculatedRating += step; remPrcnt -= (percentOfStar + percentOfSpacing); } else { calculatedRating += remPrcnt/percentOfStar*step; remPrcnt = 0; } } } else { calculatedRating = calcPrcnt * (options.maxValue); } calculatedRating = round(calculatedRating); } return calculatedRating; } function onTouchMove (e) { event.preventDefault(); event.stopPropagation(); var rating = calculateRatingTouch(e).toFixed(options.precision); var maxValue = options.maxValue; rating = checkPrecision(parseFloat(rating), minValue, maxValue); showRating(rating); $node.trigger("rateyo.change", {rating: rating}); } function onTouchEnd (e) { event.preventDefault(); event.stopPropagation(); var resultantRating = calculateRatingTouch(e).toFixed(options.precision); resultantRating = parseFloat(resultantRating); that.rating(resultantRating); } ・・・ |
2.タッチイベントをバインド
「bindEvents」関数と「unbindEvents」関数にタッチイベントをバインドしてやります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | (修正後) ・・・ function bindEvents () { $node .on("mousemove", onMouseEnter) .on("mouseenter", onMouseEnter) .on("mouseleave", onMouseLeave) .on("click", onMouseClick) .on("touchstart", onTouchMove) .on("touchmove", onTouchMove) .on("touchend", onTouchEnd) .on("rateyo.change", onChange) .on("rateyo.set", onSet); } function unbindEvents () { $node .off("mousemove", onMouseEnter) .off("mouseenter", onMouseEnter) .off("mouseleave", onMouseLeave) .off("click", onMouseClick) .off("touchstart", onTouchMove) .off("touchmove", onTouchMove) .off("touchend", onTouchEnd) .off("rateyo.change", onChange) .off("rateyo.set", onSet); } ・・・ |
これでOKです。
南本貴之