Hello I am trying to get the offsetX,Y of touch event which should be identical to offsetX of mouse event. To do so I have used this code:
ev.offsetX = ev.targetTouches[0].pageX- canvasName.offsetLeft
I have even tried to simulate the touch event into mouse event but for that purpose i need the offsetX/Y, which is unavailable in touch event. Is there any way offsetX/Y can be calculated for touch? Please help
I use this
var rect = e.target.getBoundingClientRect();
var x = e.targetTouches[0].pageX - rect.left;
var y = e.targetTouches[0].pageY - rect.top;
The best answer here don't work for me, on webpage with scrolling! This will work better:
var bcr = e.target.getBoundingClientRect();
var x = e.targetTouches[0].clientX - bcr.x;
var y = e.targetTouches[0].clientY - bcr.y;
I used it to solve my problem.
I know this is an old question but the first in a google of "offsetX touch event".. I ended up using something like this after the research I did.
function getOffsetPosition(evt, parent){
var position = {
x: (evt.targetTouches) ? evt.targetTouches[0].pageX : evt.clientX,
y: (evt.targetTouches) ? evt.targetTouches[0].pageY : evt.clientY
};
while(parent.offsetParent){
position.x -= parent.offsetLeft - parent.scrollLeft;
position.y -= parent.offsetTop - parent.scrollTop;
parent = parent.offsetParent;
}
return position;
}
You should use clientX
/ clientY
properties of mouse event (or pageX
/ pageY
) if you have scrolling on your page.
As for your solution. It can be corrected by using getElementById(canvasName).clientX
ev.offsetX = ev.targetTouches[0].pageX - getElementById(canvasName).clientX
canvasName.offsetLeft
is offset of canvasName
with respect to it's parent. So if you want to use offsetLeft
you should do something like the following
var left = 0,
elem = getElementById(canvasName);
while(elem) {
left = left + parseInt(elem.offsetLeft);
elem = elem.offsetParent;
}
ev.offsetX = ev.targetTouches[0].pageX - left
If you are using jQuery touchend events, the layerX and layerY attributes provide the relative x and y, but do not take into account the transform. So I manually applied the transform by grabbing the transform scale values from the css.
e = the touchend event from jQuery
parent = the jQuery object of the parent element where the "transform" is applied. For me it was $(e.target.parentNode);
const layerX = e.originalEvent.layerX;
const layerY = e.originalEvent.layerY;
const currentScale = 1 / parseFloat(parent.css('transform').match(/-?[\d\.]+/g)[0]);
const offsetX = layerX * currentScale;
const offsetY = layerY * currentScale;
To make the last two lines compatible with touch and click events:
const offsetX = e.offsetX || layerX * currentScaleX;
const offsetY = e.offsetY || layerY * currentScaleY;
Reference for grabbing transform values: Fetch the css value of transform directly using jquery
If you are using Reactjs onClick
then you can get the layerX and layerY values with: e.nativeEvent.layerX
. For some reason the layerX and layerY are not available on the React touch events. If you do need to use the React onTouchEnd
:
const rect = e.nativeEvent.target.getBoundingClientRect();
const layerX = e.changedTouches[0].clientX - rect.left;
const layerY = e.changedTouches[0].clientY - rect.top;
const currentScale = 1 / parseFloat(parent.css('transform').match(/-?[\d\.]+/g)[0]);
const offsetX = layerX * currentScale;
const offsetY = layerY * currentScale;
Note: It is better to store the values of the transform in Redux rather than grabbing them with jQuery.
Credits to https://stackoverflow.com/a/11396681/1997890
function recoverOffsetValues(e) {
var rect = e.target.getBoundingClientRect();
var bodyRect = document.body.getBoundingClientRect();
var x = e.originalEvent.changedTouches[0].pageX - (rect.left - bodyRect.left);
var y = e.originalEvent.changedTouches[0].pageY - (rect.top - bodyRect.top);
return [x, y];
}
I use this:
const {x, y, width, height} = e.target.getBoundingClientRect();
const offsetX = (e.touches[0].clientX-x)/width*e.target.offsetWidth;
const offsetY = (e.touches[0].clientY-y)/height*e.target.offsetHeight;
You could use PointerEvent instead of touch events, they have more properties. For example:
div.addEventListener('pointermove', console.log);
Output:
isTrusted: true
altKey: false
altitudeAngle: 1.5707963267948966
azimuthAngle: 0
bubbles: true
button: -1
buttons: 1
cancelBubble: false
cancelable: true
clientX: 203
clientY: 483
composed: true
ctrlKey: false
currentTarget: null
defaultPrevented: false
detail: 0
eventPhase: 0
fromElement: null
height: 23
isPrimary: true
layerX: 203
layerY: 177
metaKey: false
movementX: 0
movementY: -1
offsetX: 203
offsetY: 177.6875
pageX: 203
pageY: 483
pointerId: 9
pointerType: "touch"
pressure: 1
relatedTarget: null
returnValue: true
screenX: 734
screenY: 621
shiftKey: false
sourceCapabilities: null
tangentialPressure: 0
tiltX: 0
tiltY: 0
toElement: null
twist: 0
type: "pointermove"
which: 0
width: 23
x: 203
y: 483
[[Prototype]]: PointerEvent
Usage example: MDN: Pinch zoom gestures
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.