Canvas には、drawImage() (w3c) と呼ばれる非常に強力な API があります。
その主な機能は、写真、ビデオ、さらには他のキャンバスを描画することです。
質問:彼は感心してここに来たが、的を外して頭を下げたとき、地面に大きな穴があった。
内容はこんな感じです。w3c の概要と非常に説得力のある教育的なデモを読んだ後、本当の知識を得るために実践してみようという考えに基づいて試してみることにしました。試してみてください〜
組立ライン プロジェクトに従って、次の基本的なタスクを配置しました。
1.キャンバスタグ+ID
<canvas id=canvas1></canvas>
2. キャンバスを取得 + 幅と高さを設定
var cav1 = document.getElementById('canvas1')、wWidth = 800、wHeight = 600;3. getContext('2d') はキャンバスを準備します
var ctx1 = cav1.getContext('2d');4. 新しい Image() オブジェクトを作成し、それに好きな写真の属性を与えます... (あまり考えすぎないでください)
var bgImg = new Image();bgImg.src = 'images/background.jpg';
5. いよいよ描画です。私は興奮して次のコードを書きました。
ctx1.drawImage(bgImg,0,0,wWidth,wHeight);
慌ててブラウザの F5 キーを押しました。
それから、死んだような沈黙がありました...
コードの書き方が間違っているのではないかと思い、戻ってよく確認してみたら、間違っていませんでした。
w3c のキー属性名とメソッドをコピーして、確かに正しいことを再度確認します。
写真をプリントアウトすると、こんな写真(人物)も!
後で W3C の事例を観察したところ、私のコードとの違いは、画像が HTML であることです。
それからHTMLに画像を挿入する方法を学びました。
<img src=./images/background.jpg id=imgs style=display:none></img>
getElementById を使用してこの要素を取得します。
var bgImg = document.getElementById('imgs')再度描画を実行するとうまくいきました。
彼は実際にそれができるのです!
悲しいことに、それは物理的なものである必要があるのでしょうか? Canvasタグの前に置くだけではないでしょうか? js の読み込みにもエンティティがあり、私は今でも new を使用していますが、実際の人間とはまったく異なります。
そうなんです、ただ前に置いてあるだけじゃないですか?これには順序の問題が関係します。
確かにjsで読み込んだ画像は描画の前に配置されますが、画像の読み込みに時間がかかります。画像のバッファリングには時間を与える必要があります。画像が正常にロードされるまで待ってから、画像を描画します。画像がロードされる前に使用される場合、drawImage メソッドは呼び出されません。描画は失敗します。なるほど!
img タグ内の画像は読み込みに時間がかからないと主張する人もいますか?この時点ではdrawImageは制限されていないのでしょうか? !ただし、jsの先頭にあるwindow.onloadを無視しないでください。画像の読み込みが遅くても、画像タグの順序がcanvasタグの後であっても、window.onloadがそれをカバーしている場合でも、画像をロードすることはできません。ロードされているので、drawImage がロードされる可能性はありません。
おおよその順序は次のとおりです。
<img src=>window.onload = function(){drawImage}画像が HTML 構造に挿入されていなかったら、この制限は私の不注意によって回避されていたでしょう。
画像がリソースとしてリクエストされ、js で読み込まれると、当然、画像の読み込み時間が発生します。
ただし、制限がないため、ほとんどの場合、画像が読み込まれていないときにdrawImageが呼び出され、このメソッドは機能しません。
解決する:画像の読み込みシーケンスが原因でdrawImageの描画が失敗する問題を解決する良い方法はあるでしょうか?
以下の3つの方法をまとめました。
1.タグ+ウィンドウ.オンロード <img src=>window.onload = function(){ context.drawImage()}このアプローチの中心となるソリューションは onload です。これは、イメージとdrawImage を別々にロードします。これにより、ロードが完了した後に描画が確実に使用されるようになります。
1-2.後でタグを挿入しますか?実現可能ですか1 つの状況は、スクリーンショット関数を使用するときに、drawImage も使用できることです。スクリーンショットは、独自の既存の画像のスクリーンショットを取得するのではなく、画像のアドレスをパラメータとして使用します。
この種のことは、jsでimgを作成し、それにアドレスを割り当てる必要があると思います。その後、画像を生成してスクリーンショットを撮ります。
var myImg = document.createElement('img');myImg.src = '///';document.body.appendChild(myImg);ctx1.drawImage(myImg,0,0,wWidth,wHeight);余分なタグを追加したくないですか?新しい画像オブジェクトを作成するには、以下に示すように js を使用する必要がありますか?
var bgImg = new Image();bgImg.src = 'images/background.jpg';
前述したように、new Image() を使用して作成されたこの種の画像は、画像をバッファリングするのに時間がかかります。画像が正常にロードされるまで待ってから、画像を描画します。
画像オブジェクトの準備は完了しましたが、画像が実際にロードされたことをどうやって知ることができるでしょうか。別の方法があります。
js タスクの実行中、私が実行時間に近づきすぎていると思われますか? 私を一人で取り出して再度キューに入れて、後でもう一度実行してもらえますか?
2. タイマー非同期実装 setTimeout(function(){ ctx1.drawImage(bgImg,0,0,wWidth,wHeight);},10)よくある 1000 または 0 ではなく、ここで 10 を書くのが遅いのはなぜですか?
なぜなら、私の特定の Wi-Fi 環境と特定のデスクトップ コンピューターのテストでは、表示されない 0 とは異なり、10 はイメージのロード後に表示されるだけであり、1000 のように半日待つ必要はありません。
しかし、画像をより大きな画像に変更した場合、この 10 は依然として適用されるでしょうか? Wi-Fiを2Gに変更してもこの10は適用されますか?
したがって、タイマーの欠点は、ネットワークが高速でない場合、時間が経過しても画像がロードされるという保証がないことです。
3.img.onloadwindow.onload を使用すると、読み込みの完了を直接監視できないでしょうか。
img の読み込みイベントを使用して、画像の読み込みが成功したことを監視し、キャンバスの描画効果を実行します。この方法はより信頼性が高くなります。
bgImg.onload = function(){ console.log('画像が正常にロードされました'); ctx1.drawImage(bgImg,0,0,wWidth,wHeight);実際、これら 3 つのメソッドはすべて、最初にイメージをロードするという同じコアを持っています。つまり、画像のプリロードです。ただし、キャッシュされた画像の場合、画像のプリロードでは、ページが更新されていないときにキャッシュされた画像を監視するという問題も解決する必要があります。
別の問題が見つかりました。 。 。 。まず、背景の塗装が完了すると、次のようになります。
そして、ようやく背景の絵が出てきて、楽しく続けました。
そこで、見えなくなるのを避けるために、すぐに赤い線を引きました。幅も 20 に増やしました。
bgImg.onload = function(){ ctx1.drawImage(bgImg,0,0,wWidth,wHeight); /* 次のように赤い線を描画します。 */ ctx1.beginPath(10,wHeight); ctx1.lineTo (10,wHeight-100); ctx1.lineWidth = 20; ctx1.ストロークスタイル = '赤' ctx1.closePath();しかし、F5を押しても変化はなく、赤い線も見えません。
長い間検索した後、背景画像をオフにするまで見つかりませんでした。
ああ、彼は背景画像で覆われていたことがわかりました。
しかし、なぜ?
2つの可能性があると考えています
1. 階層の問題
2. 順序の問題
1に関してはCSSのz-indexのような感じで、背景画像が赤線を覆っているところです。背景画像のレベルが赤線よりも高いということでしょうか?
この仮説を検証する方法がなかったので、2 番目の可能性のある暴露を諦めました。
しかし、なぜ背景画像が上部にあるのでしょうか?背景画像は後から描くからでしょうか?
これは、console.log() を出力して実行シーケンスを観察することで最も簡単に観察できます。
原因は onload コールバックであることが判明しました。タイマーと同様に、これは非同期タスクです。当然、同期タスクよりも順位が下になります(下に線を引いています)。
したがって、onload は良い解決策のように見えますが、ここではその欠点も明らかになります。
とても良いですね。約束の学習計画をできるだけ早くスケジュールに組み込む必要があるようです。ははは
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。