🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

2363閲覧

canvasに複数の画像を表示させる

truemind2002

総合スコア16

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/09/08 12:25

編集2019/09/10 00:35

下記のサイトを参考に、落ち葉を降らせるアニメーションを製作中です。

Canvasで桜を降らせてみました | 株式会社オーツー|スタッフブログ

やりたいこと

このサイトの例に習って、落ち葉を動かすことはできたのですが、
更に、いくつかの別々の葉っぱの画像をランダムに表示させたいと思っています。

例)leaf1.svg,leaf2.svg,leaf3.svg
(サイトの例では、1つの画像を仕様)

現状のコードは以下のとおりです。

・参考サイトにある「雲の動き」などは使わないので省いてあります
・キャンバスサイズの指定など少し修正しています。

javascript

1var canvas = document.getElementById("canvas"); 2var container = document.getElementById('canvas_wrap'); 3var ctx = canvas.getContext("2d"); 4sizing(); 5var imgCnt = 15; 6var aryImg = []; 7var aryCloud = []; 8var cvsw = $(window).width(); 9var cvsh = $(window).height(); 10var imgBaseSizeW = 15; 11var imgBaseSizeH = 20; 12var aspectMax = 2; 13var aspectMin = 1; 14var speedMax = 4; 15var speedMin = 2; 16var angleAdd = 100; 17var wind = 200; 18var newWind = 20; 19var windMax = 10; 20var windMin = 5; 21var img = new Image(); 22img.src = "resource/images/common/leaf.svg"; 23img.onload = flow_start; 24 25function sizing() { 26 canvas.height = container.offsetHeight; 27 canvas.width = container.offsetWidth; 28 } 29 30 31function setImagas(){ 32 var aspect = 0; 33 for(var i = 0;i < imgCnt;i++){ 34 aspect = Math.random()*(aspectMax-aspectMin)+aspectMin; 35 aryImg.push({ 36 "posx": Math.random()*cvsw, 37 "posy": Math.random()*cvsh, 38 "sizew": imgBaseSizeW*aspect, 39 "sizeh": imgBaseSizeH*aspect, 40 "speedy": Math.random()*(speedMax-speedMin)+speedMin, 41 "angle": Math.random()*360, 42 }); 43 } 44} 45 46var idx = 0; 47var idxc = 0; 48var cos = 0; 49var sin = 0; 50var rad = Math.PI / 180; 51 52function flow(){ 53 ctx.clearRect(0,0,cvsw,cvsh); 54 for(idx = 0;idx < imgCnt;idx++){ 55 aryImg[idx].posx += wind/aryImg[idx].sizew; 56 aryImg[idx].posy += aryImg[idx].speedy; 57 (idx%2) ? aryImg[idx].angle += 1 : aryImg[idx].angle -= 1; 58 cos = Math.cos(aryImg[idx].angle * rad); 59 sin = Math.sin(aryImg[idx].angle * rad); 60 ctx.setTransform(cos, sin, sin, cos, aryImg[idx].posx, aryImg[idx].posy); 61 ctx.drawImage(img, 0, 0 , aryImg[idx].sizew , aryImg[idx].sizeh); 62 ctx.setTransform(1, 0, 0, 1, 0, 0); 63 if(aryImg[idx].posy >= cvsh){ 64 aryImg[idx].posy = -aryImg[idx].sizeh; 65 if(imgCnt < idx){ 66 aryImg.splice(idx, 1); 67 } 68 } 69 if(aryImg[idx].posx >= cvsw){ 70 aryImg[idx].posx = -aryImg[idx].sizew; 71 if(imgCnt < idx){ 72 aryImg.splice(idx, 1); 73 } 74 } 75 } 76} 77 78function windowChange(){ 79 newWind = Math.random()*(windMax-windMin)+windMin; 80 setInterval(function(){ 81 if(newWind != wind){ 82 (newWind > wind) ? wind += 0 : wind -= 0; 83 } 84 },100); 85} 86 87function flow_start(){ 88 setImagas(); 89 setInterval(flow,10); 90}

調べたりやってみたこと

画像の指定部分は

javascript

1img.src = "resource/images/common/leaf.svg";

canvasで画像の描画部分は、

javascript

1ctx.drawImage(img, 0, 0 , aryImg[idx].sizew , aryImg[idx].sizeh);

だと思うので、ここの変数imgを配列を使ったり、Math.randomとかで何かするのかなぁと思ったのですが、うまくいきません。
どうしたら実現できるのかお教えください。よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まったくランダムではないけど・・・
作戦としては、

  1. 画像を3つ読み込む
  2. 3画像すべての読込完了を検知(Promise使う)してflow_startを流す
  3. ctx.drawImageで指定するimgを、idxに合わせて3画像のどれかをチョイスするようにする

って感じ。

そのために関数を2つ追加するのとimg用の変数を3つにしてやってみると。

javascript

1// ここを入れ替えて・・・ 2//var img = new Image(); 3//img.src = "resource/images/common/leaf.svg"; 4//img.onload = flow_start; 5 6 7/** 画像読込完了を検知するための関数 */ 8function loadImg(img, src) { 9 return new Promise((res, _) => { 10 img.src = src; 11 img.onload = () => res(); 12 }) 13} 14 15/** 3画像のどれかをチョイスする関数 */ 16function choiseImg(idx) { 17 switch(idx % 3) { 18 case 0: 19 return img1; 20 break; 21 case 1: 22 return img2; 23 break; 24 case 2: 25 return img3; 26 break; 27 } 28} 29 30var img1 = new Image(); 31var img2 = new Image(); 32var img3 = new Image(); 33 34// 作戦1部分 35const ps = [ 36 loadImg(img1, "resource/images/common/leaf1.svg"), 37 loadImg(img2, "resource/images/common/leaf2.svg"), 38 loadImg(img3, "resource/images/common/leaf3.svg") 39]; 40// 作戦2部分、Promise.allで先の3画像のロードが終わったらthen内を実行ってやってる 41Promise.all(ps).then(() => flow_start()) 42 43// ~~中略~~ 44 45// ctx.drawImage(img, 0, 0 , aryImg[idx].sizew , aryImg[idx].sizeh);をいれかえ、作戦3部分 46 ctx.drawImage(choiseImg(idx), 0, 0 , aryImg[idx].sizew , aryImg[idx].sizeh); 47

Promise分からないかもだけど説明がめんどい・・・非同期できるやつです。「javascript promise 優しい解説」とかでググったら出てこないかな・・・

投稿2019/09/12 09:17

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

truemind2002

2019/09/12 14:29

ご回答ありがとうございます!希望の動きが再現できました! javascriptはまだ勉強が足りないですが、Promiseについても調べて学習しようと思います。 助かりました。
退会済みユーザー

退会済みユーザー

2019/09/13 00:17

よかったです。勉強がんばって!俺も頑張んなきゃ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問