当用户触摸和移动手指时,如何使用knockout.js获取哪些元素(vm)被触摸



我正在使用淘汰赛,我正在努力实现这一点:

我想让用户选择一些区块:

  1. 单击第一个块(已选中)
  2. 在不释放鼠标按钮的情况下,移动鼠标
  3. 你经过的每个街区都会被选中
  4. 松开按钮停止选择

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

如何在淘汰赛中使用触摸事件进行相同的行为?

  1. 触摸第一块
  2. 不松开手指,四处移动
  3. 选择所有触摸的块
  4. 松开手指

ps:我被卡住了,因为在使用触摸事件时,事件源被锁定在第一个被触摸的元素上(哦,天哪,为什么???),我不知道其他哪些元素阻止了用户触摸。

下面是我的代码:

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,但我无法想象这是最好/唯一的方法。。。

感觉既粗糙又缓慢,因为它首先使用touchxy来精确定位元素,然后使用ko.dataFor来获取block视图模型。。。它确实工作。。。

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

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

若要测试此片段,请将开发人员工具设置为模拟触摸

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>

最新更新