2

初めてのポスターで、JavaScript/jQuery/Raphael の初心者をわずかに上回っています。違反を許してください。:)

それで、私は自分の質問に対する答えを高低を調べて、いくつかの有望な手がかりを見つけましたが、私のプログラミングスキルはあまりにも環境に優しく、すべてをまとめることができません. 私は Raphael と一緒にインタラクティブな米国の地図を作成し、さまざまな基準に基づいて最終的に州を強調表示する 13 個のチェック ボックスのセットをユーザーに提供しています。各チェック ボックスは、約 3 ~ 15 の状態 (もちろんすべてのパス) に関連付けられています。ユーザーがいくつかのチェック ボックスを選択すると、配列の交点を見つけて、それらの状態のみを強調表示する必要があります。例えば:

<input id="a1" value="arr1" type="checkbox" />
<input id="a2" value="arr2" type="checkbox" />
<input id="a3" value="arr3" type="checkbox" />
<input id="a4" value="arr4" type="checkbox" />
<input id="a5" value="arr5" type="checkbox" />

arr1 = [a,b,c];
arr2 = [b,c,d];
arr3 = [b,c,e];
arr4 = [a,e];
arr5 = [a,b];

たとえば、ユーザーが a1、a2、および a3 を選択した場合、交点用に別の配列を作成し (たとえば intArr = [b,c])、適切な Raphael の塗りつぶしの色を変更します。パス。

ここで見つけた巧妙な交差関数のおかげで、力ずくでこれを解決することができました。しかし、より洗練されたソリューションでは、文字通り約 100 行のコードを節約できます。ユーザーの選択に基づいて配列 (またはオブジェクト?) の配列を作成し、それを反復して最初の配列を比較する必要があると思います。マスター配列内のその他。問題があります。配列をすべて Raphael 要素変数にする必要があると思います。(各要素に id を与え、後で fill 属性を変更するためにそれらをターゲットにする必要がある場合を除きますか?)

これが私がそれを機能させる方法です:

var selectedStates = new Array();
var arr1 = new Array(stArr1,stArr2,stArr3,stArr4,stArr5,stArr6);
var arr2 = new Array(stArr2,stArr3,stArr7,stArr9);
// etc.

var arr1Sel = false;
var arr2Sel = false;
// etc.

$('#selecttools input').click(function(){ 
  // reset all global variables for each feature
  arr1Sel = false;
  arr2Sel = false;
  // etc. 

  // find checked boxes and set appropriate globals to true
  $('#selecttools').find(":checked").each(function() {
    if ($(this).val() == 'arr1') { arr1Sel = true; }
    if ($(this).val() == 'arr2') { arr2Sel = true; }
    //etc.

  // now run selectTheStates
  selectTheStates();
});

function selectTheStates() {
  // first reset selectedStates with the default fill color
  for (var i = 0; i < selectedStates.length; i++) {
    selectedStates[i].attr({fill: "#CCB2E5"});
  }
  // setup the intersect filter
  // thank so much, love this one http://jsfiddle.net/i_like_robots/KpCt2/
  $.arrayIntersect = function(a, b) {
    return $.grep(a, function(i) {
      return $.inArray(i, b) > -1;
    });
  }
  // first make a list of selected arrays
  var ourFinalList = new Array();
  // now, the real brute force...nested if statements that have to go!
  if (arr1Sel == true) {
    ourFinalList = arr1;
    if (arr2Sel == true) { ourFinalList = $.arrayIntersect(ourFinalList,arr2) }
    if (arr3Sel == true) { ourFinalList = $.arrayIntersect(ourFinalList,arr3) }
    // etc.
  } else if (arr2Sel == true) {
    ourFinalList = arr2;
    if (arr3Sel == true) { ourFinalList = $.arrayIntersect(ourFinalList,arr3) }
    // etc. lots of nesting here, yuck!
  } else if (arr13Sel == true) {
    ourFinalList = arr13;
  }
  // now paint all the states in our final list with Raphael
  for (var i = 0; i < ourFinalList.length; i++) {
    ourFinalList[i].attr({fill: "#B38CD8"});
  }
  // last step is reset selectedStates
  selectedStates = ourFinalList;
// end selectTheStates
}

信じられないかもしれませんが、これは機能します。しかし、コードは非常に肥大化しており、非常に素人っぽく見えるため、ここに投稿することさえ恥ずかしく思います。しかし、私は本当にこれを行う方法を学びたいです! 助けてください。

配列の配列を作成し、その配列の最初の配列を見つけて、配列内にある他の配列と比較/交差する必要があると思います。ただし、これを実行しようとすると、いくつかの問題に遭遇しました。1.実際には配列である変数の配列を作成しようとしているため、配列の値 (配列のプレースホルダーではなく) をマスター配列にプッシュしているように見えます。たぶん、これを行うにはオブジェクトが必要ですか?

あなたが提供できる助けをありがとう!

アップデート

デビッドに感謝します。私はついにそれを働かせました。私が理解しなければならなかった1つのトリック:

デビッドは私が次のことをすることを提案しました:

var selectedStates = selected.map(function() { return stateArrays[this]; });

いくつかの調査が必要でしたが、戻り値を二重にラップする必要があることがわかりました。そうしないと、配列全体が連結としてプッシュされます。したがって、これは機能しました:

var selectedStates = selected.map(function() { return [stateArrays[this]]; });

その後、彼が提案したように、配列の配列を反復処理する必要がありました。ただし、 pop(); を取得したことはありません。なぜか働くこと。そのため、交差ツールの最初の配列として selectedStates[0] を使用しました。

どうもありがとう、デビッド!

更新を終了

4

1 に答える 1

0

まず第一に、どの配列が選択されているかを知る何らかの方法が必要です。

var selected = $(':checkbox:checked').map(function() { return this.value; });
// selected = ['arr1','arr2','arr3'] for instance

:checkbox:checkedクラス名や、関心のあるチェックボックスを区別するために使用できるものを表示していないため、チェックされたすべてのチェックボックスを取得するために使用しています。.box-class:checkedまたはのようなものを使用する方がよい場合があります#parent :checkbox:checked

そこから、配列名のリストを実際の配列のリストに変換します。あなたのコードは現在、 などという名前の変数の束を作成したばかりですarr1arr2代わりに、オブジェクトのこれらのプロパティを作成したい場合があります。

var stateArrays = {
   arr1: [a,b,c],
   arr2: [b,c,d],
   ...
};

そうすれば、次の方法でそれらにアクセスできます。

var x = stateArrays[myVariable];
// x = [a,b,c] if myVariable = 'arr1'

個別の変数を保持したい場合は、もちろんそのようなオブジェクトを作成することもできます:

var stateArrays = {
   arr1: arr1, // where arr1 is already defined
   ...
};

したがって、あなたのシナリオでは:

var selectedStates = selected.map(function() { return stateArrays[this]; });
// selectedStates = [[a,b,c],[b,c,d],[c,d,e]] for instance

これで、交差を取得するために配列の配列をループするだけで済みます。

var result = selectedStates.pop();
selectedStates.forEach(function(x) {
   result = $.arrayIntersect(result, x);
});

// result = [c], given the value of selectedStates as above

上記のスニペット$.arrayIntersectは、投稿で定義したとおりに使用しています。

于 2013-03-19T15:12:44.557 に答える