简体   繁体   English

当用户触摸并移动手指时,如何获取使用敲出.js触摸了哪些元素(虚拟机)

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

I'm using knockout and I'm trying to achieve is this: 我正在使用淘汰赛,我正在努力实现以下目标:

I want the user to select some blocks: 我希望用户选择一些块:

  1. click the first block (it is selected) 单击第一个块(已选中)
  2. without releasing the mouse button, move the mouse around 在不释放鼠标键的情况下,将鼠标移动
  3. every block you pass through is selected 您经过的每个街区都会被选中
  4. release the button to stop selecting. 释放按钮停止选择。

It's very easy to do it using mouse events, but I need to target touch devices too (android, iphone, touch notebooks). 使用鼠标事件很容易做到,但我也需要定位触摸设备(Android,iPhone,触摸笔记本)。

How to have the same behavior using touch events with knockout? 带有敲除的触摸事件如何具有相同的行为?

  1. touch the first block 触摸第一个街区
  2. without releasing the finger, move around 在不松开手指的情况下移动
  3. select all touched blocks 选择所有触摸的块
  4. release the finger 松开手指

ps: I got stuck because when using touch events, the event source is locked to the first touched element (oh god, why???) and I can't figure out which others blocks the user touches. ps:我陷入困境是因为在使用触摸事件时,事件源被锁定到第一个被触摸的元素(哦,天哪,为什么???),我无法弄清还有哪些阻止用户触摸。

Here is a jsfiddle with my code: 这是我的代码的jsfiddle:

https://jsfiddle.net/m38tfpq4/2/ 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> 

You could use document.elementFromPoint , but I can't imagine it's the best/only way... 可以使用document.elementFromPoint ,但我无法想象这是最好/唯一的方法...

Feels hacky and slow, since it first uses the x and y of a touch to pinpoint an element, and then uses ko.dataFor to get to the block viewmodel... It does work though... 由于它先使用touchxy来精确定位元素,然后再使用ko.dataFor来获取block视图模型,因此感觉很笨拙且缓慢...尽管它确实可以工作...

An interim solution could be to store a block id property in an attribute on the element, and keep a Map linking id props to block viewmodels in your $parent vm. 临时解决方案可能是将block id属性存储在元素的属性中,并使Mapid道具链接到$parent vm中的block viewmodel。 Might speed up some parts of the logic. 可能会加速逻辑的某些部分。

I'm curious to see if anyone else comes up with a more logical way of linking those weird touch events to an element :) 我很好奇,看看是否还有其他人提出了将这些怪异的触摸事件链接到元素的更合理的方法:)

To test this snippet, set your developer tools to 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM