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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

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

Q&A

解決済

1回答

1937閲覧

WebAudioApiでのクラス化が上手く出来ません

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

0クリップ

投稿2015/11/25 04:19

javascript

1//Lineクラス 2var Line = function(length){ 3 this.audioContext 4 this.wetGainNode; 5 this.lineNum; 6 7 Line.prototype.init(length); 8} 9 10Line.prototype.init = function(length){ 11 //クラスのブラウザ別振り分け 12 var webAudioAPI = (window.AudioContext || 13 window.webkitAudioContext || 14 window.mozAudioContext || 15 window.oAudioContext || 16 window.msAudioContext); 17 18 /* 外部クラスインスタンス化 */ 19 this.audioContext = new webAudioAPI(); 20 21 /* 各種ノード生成 */ 22 this.wetGainNode = this.audioContext.createGain(); //wetGainNode 23 24 /* wetGain初期化 */ 25 this.wetGainNode.gain.value = 0; 26 27 /* LineContainer ModuleRoot要素の作成 */ 28 Line.prototype.createElem(Line.prototype.setLineNum(length)); 29} 30 31Line.prototype.getWetGain = function(){ 32 return this.wetGainNode.gain.value; 33} 34 35Line.prototype.setWetGain = function(val){ 36 this.wetGainNode.gain.value = val; 37} 38 39Line.prototype.paramView = function(obj){ 40 console.log('wetGain : ' + obj.getWetGain()); 41} 42 43Line.prototype.setLineNum = function(length){ 44 return this.lineNum = length; 45} 46 47Line.prototype.createElem = function(linenum){ 48 //HTML構造生成 49 var pElem = document.querySelector('#lineContext'); //lineContext取得 50 var lineContainer = document.createElement("div"); //lineContainer 51 lineContainer.className = "lineContainer"; 52 lineContainer.setAttribute('data-linenum', linenum); 53 /*-------------------------------wetGain-------------------------------*/ 54 //wetGainContainer 55 var wetGainContainer = document.createElement("div"); 56 wetGainContainer.className = "wetGain"; 57 58 //h3 59 var wetGain__p = document.createElement("p"); 60 wetGain__p.innerHTML = "wetGain"; 61 62 //wetGainView 63 var wetGainView = document.createElement("div"); 64 wetGainView.className = "wetGainView"; 65 wetGainView.innerHTML = "0"; 66 67 //wetGain 68 var wetGainInput = document.createElement("input"); 69 wetGainInput.className = "wetGainInput"; 70 wetGainInput.type = "range"; 71 wetGainInput.value = "0"; 72 wetGainInput.step = "1"; 73 wetGainInput.max = "100"; 74 /*----------------------------------------------------------------------*/ 75 76 77 78 /*----------------------------------------------------------------------*/ 79 80 /*-------------------------------appendChild----------------------------*/ 81 //wetGain - appendChild 82 wetGainContainer.appendChild( wetGain__p ); 83 wetGainContainer.appendChild( wetGainView ); 84 wetGainContainer.appendChild( wetGainInput ); 85 86 //p - appendChild 87 pElem.appendChild( lineContainer ); 88 lineContainer.appendChild( wetGainContainer ); 89 /*----------------------------------------------------------------------*/ 90}

javascript

1//イベントリスナー登録 2document.addEventListener('DOMContentLoaded', function (event) { 3 4 var lines = new Array(); 5 6 //Line作成 7 event.target.querySelector('#createButton').addEventListener('click', function(){ 8 9 //インスタンスpush 10 lines.push(new Line(lines.length)); 11 12 var wetGainInputElem = document.querySelectorAll('.wetGainInput'); 13 var wetGainView = document.querySelectorAll('.wetGainView'); 14 15 for(var i = 0; i < lines.length; i++){ 16 17 //スライドバーリスナー登録 18 wetGainInputElem[i].addEventListener("input", function(event){ 19 var input = event.target; 20 var view = input.previousElementSibling; 21 var lineElem = input.parentNode.parentNode; //class="lineContainer" 22 var lineNum = lineElem.getAttribute('data-linenum'); 23 24 var volume = this.value; //gain値の変更 25 view.innerHTML = volume; //表示の変更 26 lines[lineNum].setWetGain(volume); //イベントがあったインスタンスのメンバ変数にアクセスしてセット 27 }, false); 28 } 29 }, false); 30 31 //Lineの状態参照 32 event.target.querySelector('#checkSource').addEventListener('click', function(){ 33 if(lines.length > 0){ 34 for(var i=0; i < lines.length; i++){ 35 lines[i].paramView(lines[i]); 36 } 37 } 38 }, false); 39 40}, false);

html

1<!doctype html> 2<html lang="ja"> 3<head> 4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5<meta http-equiv="Content-Script-Type" content="text/javascript" /> 6<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"> 7<link rel="stylesheet" type="text/css" href="./css/common.css"> 8<title>Web Audio Player</title> 9<style type="text/css"> 10</style> 11</head> 12<body> 13 14 <i id="createButton" class="fa fa-plus-square"></i> 15 16 <i id="checkSource" class="fa fa-search-plus"></i> 17 18 <div id="lineContext"> 19 </div> 20 21<script type="text/javascript" src="js/LineClass_clone.js" charset="utf-8"></script> 22<script type="text/javascript" src="js/controller_clone.js" charset="utf-8"></script> 23</body> 24</html>

css

1@charset "utf-8"; 2* { 3 margin: 0; 4 padding: 0; 5} 6body { 7 background-color: #420202; 8} 9.lineContainer { 10 background-color: #f2f2f2; 11 padding: 10px 10px; 12 margin: 5px; 13 width: 220px; 14 border-radius:5px; 15 border: solid 2px gray; 16 float: left; 17} 18.wetGainView,.dryGainView,.delayGainView,.feedbackView { 19 float:left; 20 width: 15px; 21 margin-left: 15px; 22 font-size: 10px; 23} 24.wetGain,.dryGain,.delayGain,.feedback{ 25 margin-left: 15px; 26} 27.wetGainInput,.dryGainInput,.delayGainInput,.feedbackInput { 28 margin-left: 15px; 29} 30.wetGain>p,.dryGain>p,.delayGain>p,.feedback>p { 31 font-size: 10px; 32} 33.start, .stop { 34 font-size:10px; 35 font-weight:bold; 36 text-decoration:none; 37 display:block; 38 text-align:center; 39 padding:6px 23px; 40 color:#fff; 41 background-color:#000000; 42 border-radius:5px; 43 float: left; 44 margin-left: 10px; 45} 46.files { 47 font-size: 10px; 48 margin: 10px 10px; 49} 50.clear { 51 overflow: hidden; 52 zoom: 1; 53} 54#drop_zone { 55 width: 320px; 56 height: 100px; 57 line-height: 100px; 58 text-align: center; 59 margin: 5px; 60 border: dashed 3px #a9a9a9; 61 border-radius: 5px; 62 font-weight: bold; 63 color: #a9a9a9; 64 background-color: #f2f2f2; 65} 66#createButton { 67 position: relative; 68 left: 0; 69 top: 0; 70 font-size: 100px; 71 color: #ffffff; 72 margin: 0 10px 0 0; 73 padding: 0px; 74 float: left; 75} 76#createButton:hover { 77 cursor:pointer; 78} 79#checkSource { 80 position: relative; 81 left: 0; 82 top: 0; 83 font-size: 100px; 84 color: #ffffff; 85 margin: 0 10px 0 0; 86 padding: 0px; 87} 88#checkSource:hover { 89 cursor:pointer; 90}

コードが長くなってしまいすみません。
WebAudioAPIをクラス化し、スライドバーを調節して得た値をインスタンス化したメンバ変数にセットして呼び出し、確認するコードです。
本来は音声の再生と停止のためにsourceNodeやそれぞれのNodeを繋ぐコードがありますが、長くなるので今回はGainを調節するコードのみです。

四角いPlusアイコンでインスタンスを生成し、配列にプッシュします。
虫眼鏡アイコンでスライドバーで調節したメンバ変数の値を確認できます。

前置きが長くなりましたが、困っていることは
2つ以上のインスタンスを生成した時、それぞれスライドバーで値を調節した後、虫眼鏡アイコンで確認すると、両方の値が変わってしまうことです。

そこでクラスからWebAudioAPIの要素を省いたシンプルなコードで実行しました。
一番始めにあるコードを下記のコードに丸々変更すると正常に動きます。

何故なのかどなたかアドバイスいただけないでしょうか?よろしくお願いします。

javascript

1//Lineクラス 2var Line = function(length){ 3 this.wetGainNode; 4 this.lineNum; 5 6 Line.prototype.init(length); 7 8 console.log( 9 '- WetGain' + this.wetGainNode 10 ); 11} 12 13Line.prototype.init = function(length){ 14 15 /* wetGain初期化 */ 16 this.wetGainNode = 0; 17 18 /* LineContainer ModuleRoot要素の作成 */ 19 Line.prototype.createElem(Line.prototype.setLineNum(length)); 20} 21 22Line.prototype.getWetGain = function(){ 23 return this.wetGainNode; 24} 25 26Line.prototype.setWetGain = function(val){ 27 this.wetGainNode = val; 28} 29 30Line.prototype.paramView = function(obj){ 31 console.log('wetGain : ' + obj.getWetGain()); 32} 33 34Line.prototype.setLineNum = function(length){ 35 return this.lineNum = length; 36} 37 38Line.prototype.createElem = function(linenum){ 39 //HTML構造生成 40 var pElem = document.querySelector('#lineContext'); //lineContext取得 41 var lineContainer = document.createElement("div"); //lineContainer 42 lineContainer.className = "lineContainer"; 43 lineContainer.setAttribute('data-linenum', linenum); 44 /*-------------------------------wetGain-------------------------------*/ 45 //wetGainContainer 46 var wetGainContainer = document.createElement("div"); 47 wetGainContainer.className = "wetGain"; 48 49 //h3 50 var wetGain__p = document.createElement("p"); 51 wetGain__p.innerHTML = "wetGain"; 52 53 //wetGainView 54 var wetGainView = document.createElement("div"); 55 wetGainView.className = "wetGainView"; 56 wetGainView.innerHTML = "0"; 57 58 //wetGain 59 var wetGainInput = document.createElement("input"); 60 wetGainInput.className = "wetGainInput"; 61 wetGainInput.type = "range"; 62 wetGainInput.value = "0"; 63 wetGainInput.step = "1"; 64 wetGainInput.max = "100"; 65 /*----------------------------------------------------------------------*/ 66 67 68 69 /*----------------------------------------------------------------------*/ 70 71 /*-------------------------------appendChild----------------------------*/ 72 //wetGain - appendChild 73 wetGainContainer.appendChild( wetGain__p ); 74 wetGainContainer.appendChild( wetGainView ); 75 wetGainContainer.appendChild( wetGainInput ); 76 77 //p - appendChild 78 pElem.appendChild( lineContainer ); 79 lineContainer.appendChild( wetGainContainer ); 80 /*----------------------------------------------------------------------*/ 81}

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

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

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

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

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

guest

回答1

0

ベストアンサー

テストコードのsetWetGainメソッドで

javascript

1Line.prototype.setWetGain = function(val){ 2// this.wetGainNode.gain.value = val; 3 console.log(this.hasOwnProperty('wetGainNode')); 4 console.log(this.wetGainNode); 5 this.wetGainNode = val; 6}

としてみると、1回目はfalse``0になります。継承を参照していることになります。
2回目はtrueになりますので、1回目のsetWetGainメソッド実行で、プロパティを生やしていることになりますね。

ここでテストコードの初期化関数を、

javascript

1Line.prototype.init = function(length){ 2 /* wetGain初期化 */ 3 this.wetGainNode = {gain:{value:0}}; 4 5 /* LineContainer ModuleRoot要素の作成 */ 6 Line.prototype.createElem(Line.prototype.setLineNum(length)); 7}

として変更して、本番コードのsetWetGain``getWetGain'を使ってみると、上手く動作しなくなります。 これは、setWetGainメソッドがwetGainNodeを書き換えずに、wetGainNode.gain.value`という継承されたオブジェクトを操作し続けるからです。

つまり、ひとことでいうと、thisが想定しているものを差していないのだと思います。

解決方法としては、

javascript

1var Line = function(length){ 2 this.audioContext 3 this.wetGainNode; 4 this.lineNum; 5 6 var webAudioAPI = (window.AudioContext || 7 window.webkitAudioContext || 8 window.mozAudioContext || 9 window.oAudioContext || 10 window.msAudioContext); 11 12 /* 外部クラスインスタンス化 */ 13 this.audioContext = new webAudioAPI(); 14 15 /* 各種ノード生成 */ 16 this.wetGainNode = this.audioContext.createGain(); //wetGainNode 17 18 /* wetGain初期化 */ 19 this.wetGainNode.gain.value = 0; 20 21 /* LineContainer ModuleRoot要素の作成 */ 22 Line.prototype.createElem(Line.prototype.setLineNum(length)); 23 24}

などとして、初期化関数をコンストラクタの中に入れてしまうのが分かりやすいのではないかと思います。動作は確認していませんので、それで全て解決するとは限らないのですが……

投稿2015/11/25 10:54

Lhankor_Mhy

総合スコア36074

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問