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 并稍后以某种方式定位它们以更改填充属性?)

这是我如何让它工作的:

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. 因为我试图创建一个实际上是数组的变量数组,所以我似乎将数组的值(而不是数组的占位符)推送到主数组中。也许我需要对象来做到这一点?

非常感谢您提供的任何帮助!

更新

特别感谢大卫。我终于让它工作了。我必须弄清楚的一个技巧:

大卫建议我做以下事情:

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

花了一些研究,但我发现我需要双重包装我的返回值,否则整个数组将作为一个 concat 推送。所以,这行得通:

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:checkedor的东西#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 回答