当用户触摸并移动他的手指时,如何获取触摸了哪些元素(vms)knockout.js

When user touches and moves his finger, how to get which elements (vms) were touched with knockout.js

我正在使用淘汰赛,我正在努力实现的是:

我希望用户select一些块:

  1. 单击第一个块(已 selected)
  2. 不释放鼠标按钮,移动鼠标
  3. 你经过的每一个街区都是selected
  4. 释放按钮停止selecting。

使用鼠标事件很容易做到,但我也需要针对触摸设备(android、iphone、触摸笔记本)。

如何使用带有敲除的触摸事件实现相同的行为?

  1. 触摸第一个方块
  2. 不松开手指,四处移动
  3. select 所有触摸块
  4. 松开手指

ps:我卡住了,因为在使用触摸事件时,事件源被锁定到第一个被触摸的元素(天哪,为什么???)我无法弄清楚哪些其他人阻止了用户触摸。

这是我的代码的 jsfiddle:

https://jsfiddle.net/m38tfpq4/2/

var vmBlock = function(label) {
  var self = this;
  self.text = label;
  self.color = ko.observable('grey');
}

var vm = function() {
  var self = this;
  self.isSelecting = false;
  self.blocks = [new vmBlock('a'), new vmBlock('b'), new vmBlock('c')];
  self.selectStart = function(block) {
    console.log('start');
    self.isSelecting = true;
    self.select(block);
  }
  self.selectEnd = function(block) {
    console.log('end');
    self.isSelecting = false;
  }
  self.select = function(block) {
    console.log('select: ' + self.isSelecting);
    if (!self.isSelecting) {
      return;
    }
    block.color('red');
  };
};

ko.applyBindings(new vm());
.block {
  width: 100px;
  height: 100px;
  margin: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="container" data-bind="foreach: blocks">
  <div class="block" onselectstart="return false" data-bind="text: text, style:{ 'background-color' : color }, event: { mousedown: $parent.selectStart, mouseover: $parent.select, mouseup: $parent.selectEnd }">
  </div>
</div>

可以使用document.elementFromPoint,但我无法想象这是best/only的方式...

感觉很笨拙和缓慢,因为它首先使用 touchxy 来精确定位元素,然后使用 ko.dataFor 到达block 视图模型...确实 工作...

临时解决方案可能是在元素的属性中存储块 id 属性,并保留 Mapid 道具链接到 block viewmodels 在你的 $parent 虚拟机中。可能会加快某些部分的逻辑。

我很好奇是否还有其他人想出一种更合乎逻辑的方法将这些奇怪的触摸事件链接到一个元素:)

要测试此代码段,请将您的开发人员工具设置为 emulate touches

var vmBlock = function(label) {
  var self = this;
  self.text = label;
  self.color = ko.observable('grey');
}

var vm = function() {
  var self = this;
  self.isSelecting = false;
  self.blocks = [new vmBlock('a'), new vmBlock('b'), new vmBlock('c')];
  
  self.select = function(block) {
    block.color("red");
  };
  
  self.startTouch = function(data, event) {
    self.isSelecting = true;
  };
  
  self.endTouch = function(data, event) {
    self.isSelecting = false;
  };
  
  self.touch = function(data, event) {
    if (!self.isSelecting) return;
    
    var x = event.touches[0].clientX;
    var y = event.touches[0].clientY;
    var target = document.elementFromPoint(x, y);
    var vm = ko.dataFor(target);
    if (vm && vm.color) self.select(vm);
  }
};

ko.applyBindings(new vm());
.block {
  display: inline-block;
  width: 100px;
  height: 100px;
  margin: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="container" data-bind="foreach: blocks, event: {
                                    touchstart: startTouch,
                                    touchend: endTouch,
                                    touchmove: touch
                                  }">
  <div class="block" onselectstart="return false" data-bind="text: text, style:{ 'background-color' : color }">
  </div>
</div>