【问题标题】:When user touches and moves his finger, how to get which elements (vms) were touched with knockout.js当用户触摸并移动他的手指时,如何使用 knockout.js 获取哪些元素(vms)被触摸
【发布时间】:2017-01-12 22:00:13
【问题描述】:

我正在使用淘汰赛,我试图实现的是:

我希望用户选择一些块:

  1. 单击第一个块(已选中)
  2. 不松开鼠标按钮,移动鼠标
  3. 您经过的每个街区都被选中
  4. 松开按钮停止选择。

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

如何使用带有敲除的触摸事件来获得相同的行为?

  1. 触摸第一块
  2. 不松开手指,四处移动
  3. 选择所有触摸的块
  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>

【问题讨论】:

  • 你的js小提琴是空的
  • @AdamWolski 已修复,谢谢!

标签: javascript knockout.js touch


【解决方案1】:

可以使用document.elementFromPoint,但我无法想象这是最好/唯一的方式...

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

临时解决方案可能是将块id 属性存储在元素的属性中,并在$parent vm 中保留Map 链接id 道具到block 视图模型。可能会加速某些部分的逻辑。

我很想知道是否有其他人想出一种更合乎逻辑的方法来将这些奇怪的触摸事件与元素联系起来:)

要测试这个 sn-p,请将您的开发者工具设置为 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>

【讨论】:

  • 不错的收获!我也觉得这不是最好的解决方案,但是对于 javascript 中的常见问题有很多 hacky 解决方案,如果使用 elementFromPoint 是最好的方法,我不会感到惊讶。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多