[英]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: 我希望用户选择一些块:
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? 带有敲除的触摸事件如何具有相同的行为?
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... 由于它先使用touch
的x
和y
来精确定位元素,然后再使用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
属性存储在元素的属性中,并使Map
将id
道具链接到$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.