如何实现多项选择?

时间:2015-02-04 16:27:26

标签: javascript language-agnostic multipleselection

我正在使用绘图应用程序,用户可以在其中创建和删除形状,并使用鼠标选择它们来拖动它们。是否应在"选择"中引用选定的形状。数组还是每个都有一个isSelected属性?一种方法优于另一种方法有什么优势吗?这是我到目前为止所注意到的内容(我将根据人们发现的内容进行更新)。我主要关心的是编程的简单性和性能。这个问题在很大程度上与语言无关,但应用程序是在javascript中,渲染是在html5画布上完成的。

检查选择状态

虽然我们立即知道是否通过布尔属性选择了一个项目,但基于数组的解决方案需要循环遍历数组以搜索项目的引用。考虑到光标应该变为“拖动”,这种验证非常普遍。鼠标悬停所选形状或指针时的图标"图标悬停在未选择的项目上时。

取消选择项目

使用布尔属性即可选择和取消选择特定项目。但是,对于数组选择,我们必须首先遍历选择,以便在从选择中添加或删除项目之前查看该项目是否存在。这使得"切换选择"和"添加到选择"选项要慢得多。但是,此类绘图程序中最常见的操作是在选择特定元素之前清除选择。使用数组方法,清除选择就像替换数组一样简单,而布尔方法需要在所有项目上将isSelected属性设置为false。

删除项目

值得一提的是,必须在删除项目之前从选择数组中删除该项目。这个细节并没有出现在isSelected方法中。

调用所有选定的项目

适用于所有选定项目的操作需要最少的带有数组的代码,因为我们只需遍历选择并在每个元素上调用方法。如果选择与项目总量相比较小,则必须仅通过选择循环可能是相当长的时间增益。使用布尔属性,对所有选定项目调用操作所需的时间取决于项目的总数而不是选择的大小。

绘图时间

所选项目通常具有可通过其他元素看到的彩色边框。这意味着必须在所有其他元素的前面绘制选择边框。鉴于项目的数量" n"和所选项目的数量(" s")......

数组解决方案从O(n)2*O(n)进行渲染 布尔解决方案需要大约2*O(n)才能呈现。

虽然你可能认为这证明了自己选择数组方法是合理的,但请记住,重绘只能在触发操作后完成,而不是每秒60次。检查尖头形状以了解它是否被选中比绘图更常见。可能明显减慢的唯一功能是拖动,拉伸和进行矩形选择。由于应用程序用于表示现实生活中的项目,人们通常会在键盘上输入他们想要的大小,而不是实际拖动项目。

封装

使用布尔属性封装更强,因为项目知道它们是否被选中而不必查看应用程序范围变量。在严格范围的环境中,这种差异可能意味着很多,但它在javascript中并不是那么重要。我想人们可能会认为它的形状并不是很好。选择自己的角色。

1 个答案:

答案 0 :(得分:0)

我已经实现了boolean isSelected属性,随着应用程序的增长,我构建了越来越多应用于所有元素的函数。在每个函数中,我必须放置一个for循环,这将确保只更改所选项。我会编写某种伪代码来使这种解决方案语言不再存在。

for each item {
  if item is selected
    do stuff
}

每个地方都有同样的循环让我烦恼,感觉不对。当您在函数之间复制粘贴代码部分时,它永远不是一个好兆头。所以我创建了一个getSelection()函数,它返回了所选元素的数组。这似乎通过提取可怕的循环解决了我之前遇到的问题。

function getSelection() {
  selection = new empty array

  for each item in selection {
    if item is selected
      add item to selection array
  }
  return selection
}

function doStuffOnSelection() {
  selection = getSelection()

  for each item in selection {
    do stuff
  }
}

但这只会让事情变得更糟。操纵数组(不断地将项目推入数组,创建数组等)比仅查看它们要慢得多。这种变化使得应用程序变得非常缓慢,以至于在Firefox中,我甚至不能同时拥有100个项目,而我曾经能够拥有2000个没有帧丢失的项目。这样的减速都是因为我现在创建了一个数组。这是因为需要在程序的每一帧上调用getSelection函数,以在所有选定元素上绘制蓝色边框!

当我发布这个问题时,我不确定它是否过早优化,现在我知道它不是。

使用数组跟踪所选项目的主要缺点
  - 您需要查看所有选定的元素以确定是否选择了特定元素并更改该状态   - 要从所有元素的数组中删除所选元素,需要进行数组研究,当数组很大时,这一点特别慢。

使用每项布尔值跟踪所选项目的主要缺点
  - 您需要查看所有元素以了解选择了哪些元素并更改该状态。

所以我已经找到了一个更好的方法来处理所有的消极方面:做到这两点。我会在后台保留一系列选定的项目,这些项目会在选择和取消选择时更新。这消除了仅限数组选择的所有不良方面,因为我不再需要搜索任何数组来知道是否选择了特定元素(我可以查看它的布尔值)。并且所有适用于所选项但不选择和取消选择项的函数(例如移动,调整大小,绘制)都可以遍历选择数组。两全其美!