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

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

ただいまの
回答率

88.80%

jQueryの非同期処理について。順番に実行させるには。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 710

aoies

score 196

やりたいこと

jQuery, javascript初心者です。趣味でサイトを作っています。

Aボタン(.buttonA)をホバーした時に、png画像(A.png)をクロマキー処理して、class="xx"の<img>のところに表示する、
という仕組みを作りたいと思っています。

クロマキー処理にはalphaimageというjQueryのプラグインを使っています。

(クロマキー処理とは、単色の背景を透過させることです。)
(ちなみに、他のボタンがホバーされた時は他の画像を代わりに表示させるつもりです。そのためあらかじめイメージをAlphaimageで処理しておくとのではなく、ホバーの際にクロマキー処理をさせたいと考えました。)

発生している問題・エラーメッセージ

ホバーした時、処理後の画像が出るより先にクロマキー処理前の画像が一瞬表示されてしまいます。javaScriptの非同期処理が原因かと考え、whenとdoneを使ってみたのですが、改善しませんでした。

以下は、jQueryのコードになります。

該当のソースコード

$(function(){
    $('.buttonA').hover(function(){
      $.when(
        $('.c-img2').attr('src','../A.png'),
        $('.c-img2').alphaimage({colour:"#00FF00"})
      ).done(
        $('.c-img2').css('display','inline')
      );
    },function(){
      $('.c-img2').css('display','none');
    });
});

補足情報(FW/ツールのバージョンなど)

確認はGooglechromeで行っています。
alphaimageプラグインは↓のものです。
http://sly777.github.io/Jquery-Alpha-Image/

おそらくプラグインというよりは、javaScriptの動作を理解できていないのかなと思います。
javaScriptとjQueryについてはかなり初心者なので、お手柔らかに教えてくだされば嬉しいです。

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

こんにちは

以下にて、多少は改善されるのではと思われる修正をサンプルにて回答します。

改善前のものとして、以下のようなHTMLを作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Q188894</title>
    <script src="js/jquery-3.4.1.min.js"></script>
    <script src="js/jquery.alphaimage.js"></script>
    <script>
      $(document).ready(function() {

        $('.buttonA').hover(
          function() {
            $('img')
              .attr('src', 'img/Octocat.png')
              .alphaimage({
                colour: "#f4cab1"
              });
          },
          function() {
            $('img').removeAttr('src');
          }
        );

      });
    </script>
    <style>
        .buttonA {
            width: 800px;
            height: 665px;
            border: solid 1px #444;
        }
    </style>
</head>
<body>
    <div class="buttonA">
        <img />
    </div>
</body>
</html>
  • 上記で使用している画像ファイルOctocat.pngはGitHubのキャラクターのOctocatの画像で、Alpha-Imageのサイト でもサンプルで使用されているものです。GitHub Logos and Usage の Download Octocat のリンクからダウンロードできます。

  • 画像は img/, JQuery と alphaimage は、js/ フォルダの中に置いています。

上記のHTMLを表示すると、初期表示では <div> の中は何も表示されませんが、<div> の中にマウスカーソルを移動させると、Octocat の画像から顔の肌色を抜いた画像が表示され、マウスが <div> から外れると画像表示が消えます。

ですが、このままだとご質問の状況と同じように、マウスが <div> に入ったときに一瞬、肌色が抜ける前の画像が見えるときがあります。

これを改善したものが、以下です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Q188894</title>
    <script src="js/jquery-3.4.1.min.js"></script>
    <script src="js/jquery.alphaimage.js"></script>
    <script>
      $(document).ready(function() {

        const img = $('img');

        img.on('load', function() {
          if (img.attr('src') !== 'img/Octocat.png') return;
          img.alphaimage({
            colour: "#f4cab1",
            onlyData: true,
            onComplete: function(result) {
              img.attr('src', result.imageSrc).removeClass('hidden');
            }
          });
        });

        $('.buttonA').hover(
          function() {
            img.attr('src', 'img/Octocat.png');
          },
          function() {
            img.removeAttr('src').addClass('hidden');
          }
        );

      });
    </script>
    <style>
        .buttonA {
            width: 800px;
            height: 665px;
            border: solid 1px #444;
        }
        .hidden { visibility: hidden; }
    </style>
</head>
<body>
    <div class="buttonA">
        <img class="hidden"/>
    </div>
</body>
</html>

上記で意図しているのは、マウスカーソルが div に入ったときに、以下の (1)〜(4)が順に行われることです。

(1)<img> の src属性に img/Octocat.png を設定する。
(2) <img>要素が、img/Octocat.png を読み込む。
(3) 読み込みが完了したら、 .alphaimage() で透過処理を実行
(4) 透過処理が完了したら、透過処理によって生成された画像のURLをsrc属性に設定し、かつ .hiddenを削除します。この「透過処理が完了したら、」というのを実現するための .alphaimage() に対するオプションが、 以下の2点です。(Alpha-Imageのサイト から引用)

onlyData: When completed, plugin returns result that has Image and Image Data. (default : false)
onComplete: If you change onlyData option to true, it works when image processing completed.

改良版の方で動作確認しましたが、私の手元では、マウスが乗ったときに、一瞬肌色が見えることはなくなりました。

以上参考になれば幸いです。

補足

CSSクラス.hidden を追加しているのは、<img> の src属性が無い状態のときに、ブラウザのデフォルトの動作で、何らかの無効な画像を示す×印のようなものが表示されないようにすることを意図したもので、この回答の本筋にはあまり関係のない、補助的なものです。

この回答で、最も重要な主旨は、

  • onlyData を true にしたうえで、onComplete オプションを上手く使いましょう。

という点になるかと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/12 22:34

    なるほど!プラグイン側でそのための仕組みが作られていたんですね。全く理解できていませんでした。大変丁寧な回答ありがとうございます。とてもわかりやすかったです。

    キャンセル

  • 2019/05/12 22:55

    どういたしまして。
    解決のヒントになったようで、よかったです 👌

    キャンセル

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

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

関連した質問

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