質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.63%

html要素にオンマウスしても背景色が変更できない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,429

aaaaaaaa

score 479

html要素にオンマウスするとアニメーションつきで背景色を変更する処理、について質問です。
下記のソースは、オンマウスした要素のbackground-colorを取得し、配列color内のfromと一致すれば、
同じく配列colorのtoに変更するという処理です。このオンマウスし取得したときの色が透明(transparent)だと、
初回のみ色を変更してくれるのですが、再度オンマウスすると全く色が変更されないのです。
コンソールで再度オンマウスしたときに何色を取得しているのか見てみると、何故か変更後の色(to)であるrgb(0,102,51)を取得していたのです。しかし要素の背景色は、rgb(0,102,51)ではなく透明です。
色が変更されないのは、再度オンマウスすると透明時のみ"変更後"の色が取得されてしまい、
from内に一致する色がないからだと思うのです。なぜ、透明にすると"変更後"色が取得されてしまうのでしょうか。

var animation_el = [
        '#gnavi li a',
        '#language li a',
        '.gnavi_contents p a',
        '#katugyoArea p'//問題の透明部分
    ];
        var colors = [
        {from: 'rgb(0, 153, 51)', to: 'rgb(0, 133, 44)'},
        {from: 'rgb(230, 230, 230)', to: 'rgb(191, 191, 191)'},
        //▼何故か、再度オンマウスすると色が変更してくれない。最初にオンマウスした際に取得した色は、透明(transparent)なのだが、何故か再度取得すると変更後の色(to)であるrgb0,102,51が取得できてしまうのだ。
        {from: 'transparent', to: 'rgb(0, 102, 51)'}//fromが透明、toが濃い緑(#006633)。
    ];
    var baseColor;
    $.each(animation_el, function(index,value) {        
        $(value).on({
            'mouseenter':function() {
                baseColor = $(this).css('background-color');
                console.log('初期背景色',baseColor);
                                for(var i = 0; i<colors.length; i++) {
                                        if(colors[i].from == baseColor) {  
                        $(this).animate({'background-color': colors[i].to}, 400);
                        console.log('colors',colors[i].to)
                        break;
                    }
                }    
            },
            'mouseleave':function() {
                $(this).animate({'background-color': baseColor}, 400);//#006622 #093より濃い緑
            }
        });//on
    });
<section id="katugyoArea">
<h1>題名</h1>
<img src="./image/.png" alt="円形の画像">
<p><span>ここに文字列</span></p>

</section>
#katugyoArea p {
    height: 64px;
    width: 420px;
    font-weight: bold;
    border: solid 5px #fff;
    margin: 0 auto;
    background: url(../image/yazirusi.png) no-repeat right;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • rossi46hiro

    2016/02/03 21:57

    コンソールで確認したというのは2回目の`console.log('初期背景色',baseColor);`でしょうか?
    であれば、2回目に`baseColor = $(this).css('background-color');`が入れられる前のbaseColorの値は何になっているのでしょうか?

    キャンセル

  • aaaaaaaa

    2016/02/04 19:39

    http://up2.cache.kouploader.jp/koups16160.png
    情報不足で申し訳ありません。
    一度目のオンマウスがtransparent、二度目がrgba(0,102,51,0)です。
    二度目以降は、rgba(0,102,51,0)のままですね。

    キャンセル

  • think49

    2016/02/09 21:41

    素朴な疑問ですが、なぜ些細な文言の微修正だけして回答には何の返答もしないのでしょうか。もし、[アクティブ] で上の方に持っていくのが目的なら回答に返答を返した方がいいと思いますよ。
    https://teratail.com/questions/history-questions/26359

    キャンセル

回答 2

checkベストアンサー

+2

いくつか複合的な問題があったように思います。

まず、jQuery の animate() ですが、API リファレンス にもあるように、background-color のように単純なスカラー量でない要素には対応していません。もし、background-color のアニメーションをしたい場合は、同じリファレンスページに書いてあるように、JQuery.Color プラグインを利用するとよいようです。
CDN を使うなら、次のようになりますね。

<script src="http://code.jquery.com/color/jquery.color-2.1.2.min.js"></script>

で、お望みの動きになるようなコードとして、次のようなものを書いてみました。

$.normalizeColor = function(colorSpec) {
  var to = false ? $.Color(colorSpec).toRgbaString() : $.Color(colorSpec).toHexString(true);
  //console.log('@@@' + colorSpec + '==>' + to);
  return to;
};
var animation_el = [
        '#gnavi li a',
        '#language li a',
        '.gnavi_contents p a',
        '#katugyoArea p'//問題の透明部分
    ];
        var colors = (function(colors, ret) {
          colors.forEach(function(spec) {
            ret.push({ from: $.normalizeColor(spec.from), to: $.normalizeColor(spec.to) })
          });
          return ret;
        })([
        {from: 'rgb(0, 153, 51)', to: 'rgb(0, 133, 44)'},
        {from: 'rgb(230, 230, 230)', to: 'rgb(191, 191, 191)'},
        {from: 'transparent', to: 'rgb(0, 102, 51)'}
      ], []);
    $.each(animation_el, function(index,value) {
        $(value).on({
            'mouseenter':function() {
                var $elem = $(this);
                var baseColor = $.normalizeColor($elem.css('background-color'));
                $elem.data('baseColor', baseColor);
                console.log('初期背景色',baseColor);
                for(var i = 0; i<colors.length; i++) {
                    if(colors[i].from == baseColor) {
                        $elem.animate({'background-color': colors[i].to }, 400,
                          function() { 1; }
                        );
                        console.log('colors',colors[i].to)
                        break;
                    }
                }
            },
            'mouseleave':function() {
                var $elem = $(this);
                console.log('back to ' + $elem.data('baseColor'));
                $elem.animate({'background-color': $elem.data('baseColor')}, 400, function() {
                    if ($elem.data('baseColor') == '#00000000') {
                      $elem.css('background-color', 'transparent');
                    }
                    $elem.removeData('baseColor');
                });
            }
        });//on
    });

潜在的な問題として、background-color 属性をそのまま JavaScript の == 演算子で比較しているのが怪しいと思いました。特に、いちばん最初、HTML で background-color を明示的に指定していないときの値はブラウザ依存ではないかと思いますので、transparent になると考えるのは危険かと。
なので、背景色を比較するときには正規化して比較するようにしてみました。$.normalizeColor() 関数がそれになります。(なんとなく jQuery のユーティリティ関数にしてしまいましたが、その必要はないですね。)

次に、baseColor 変数のスコープが怪しいな、と思いました。なので、jQuery の data() 関数を利用して、対象の要素に元の背景色を格納するようにしました。

で、ここまでやったらちゃんと動くだろう、と思っていたら、やはりうまく動きませんでした。ある意味では JQuery.Color プラグインのバグと言ってもいいんじゃないかと思いますが、animate({background-color: '#00000000' }) と最終的に透明になるように指定すると、最終的な background-style の値は rgb(0, 0, 0) になるようです。すなわち、今回の場合で言えば、アニメーション終了後の p 要素が

<p style="background-color: rgb(0, 0, 0);">


となってしまいます。
ということで、work around として、mouseleave ハンドラの中の animate() のアニメーション終了後に呼ばれるコールバックで、戻すべき色が #00000000 だった場合には明示的に background-color を transparent にするようにしてみました(background-color を無指定にするのもいいのかもしれません)。 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/02/10 20:03

    ご回答有難うございます。
    未熟者でしてソースを理解するのや初見のjquery.colorを解析するのに時間が掛ってしまいお礼とお返事が遅れてしまいました。申し訳ないです。

    >>jQuery の animate() ですが、API リファレンス にもあるように、background-color のように単純なスカラー量でない要素には対応していません。
    申し訳ないです。書き損じておりましたが、一応、jquery-ui.jsを導入しております。
    なのでbackground-colorも使用可能です。

    >>値はブラウザ依存
    これは全く知りませんでした。勉強になります。

    記述されたソースやjquery.colorの動きやソースを理解したいので少々時間はかかると思うのですが、頂いた案を自分の環境でも試してみたいと思います。
    ご回答有難うございました。

    キャンセル

+1

jQueryを使わず、CSSのtransitionプロパティを利用するとシンプルに書けます。
本題とはずれているかもしれませんが、参考までに。

#katugyoArea p {
    height: 64px;
    width: 420px;
    font-weight: bold;
    border: solid 5px #fff;
    margin: 0 auto;
    background: url(../image/yazirusi.png) no-repeat right;
    transition:background-color 0.4s;
}

#katugyoArea p:hover {
  background-color: rgb(0, 102, 51);
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る