Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS: animation problem on multiple and continuous events #13162

Closed
alexlarocca opened this issue Nov 2, 2021 · 4 comments
Closed

iOS: animation problem on multiple and continuous events #13162

alexlarocca opened this issue Nov 2, 2021 · 4 comments

Comments

@alexlarocca
Copy link
Sponsor Contributor

alexlarocca commented Nov 2, 2021

On iOS I have a view working like a clock with an hand that rotates 360°. This worked properly until SDK 9.3.2.
With SDK 10.1.0.GA something goes wrong with animation.

It seems not to be related to function convertPointToView modified since SDK 10.0.0. It uses the right unit (dp).
The problem happens while receiving multiple and continuous touchmove events. Then multiple and continuous animations are executed.

Single animation (click on the clockView) works properly on SDK 10.1.0 too.

Video SDK 9.3.2: https://youtu.be/Teq2jfxNKSY
Video SDK 10.1.0: https://youtu.be/VDXVGHBiV5g

const win = Ti.UI.createWindow();

const SIZE = 240;

const clockView = Ti.UI.createView({
	width: SIZE, height: SIZE, 
	borderRadius: SIZE / 2, borderWidth: 2,
});

win.add(clockView);

// single animation works on SDK 10 too
clockView.addEventListener('click', function(e) {
	rotateHand({x: e.x, y: e.y});
});

const hourHand = Ti.UI.createView({
	width: 120, height: 28, 
	left: (SIZE / 2) - 14, top: (SIZE / 2) - 14, // 14 = 28 / 2
	anchorPoint: {y: 0.5, x: 0.1166}, // x = 14 / 120
	degrees: 90,
	t: Ti.UI.createMatrix2D(),
	backgroundColor: 'red',
});

clockView.add(hourHand);

// multiple animations do not works on SDK 10
hourHand.addEventListener('touchmove', function(e) {
	var convPoint = e.source.convertPointToView({x: e.x, y: e.y}, clockView);
	rotateHand({x: convPoint.x, y: convPoint.y});
});

function angle(center, p1) {
    var p0 = {x: center.x, y: center.y - Math.sqrt(Math.abs(p1.x - center.x) * Math.abs(p1.x - center.x)
            + Math.abs(p1.y - center.y) * Math.abs(p1.y - center.y))};
    return (2 * Math.atan2(p1.y - p0.y, p1.x - p0.x)) * 180 / Math.PI;
}

const degreesLabel = Ti.UI.createLabel({top: 100, text: hourHand.degrees + '°', font: {fontSize: 50}, width: Ti.UI.SIZE});
win.add(degreesLabel);

function rotateHand(e) {
	var center = {x: 0, y: 0};
	var point = {x: e.x - (SIZE / 2), y: e.y - (SIZE / 2)};
	var degrees = Math.round(angle(center, point));
	var delta = degrees - hourHand.degrees;
	currentDegrees = degrees;

	if (delta != 0) {
		degreesLabel.text = degrees + '°';
		hourHand.degrees = degrees;
		hourHand.t = hourHand.t.rotate(delta);
		hourHand.animate({transform: hourHand.t, duration: 10});
	}	
}

win.open();

Environment

Titanium SDK version: 9.3.2.GA and 10.1.0.GA
CLI version: 5.4.0

@jquick-axway
Copy link
Contributor

There was a convertToPoint() change to make it respect the "tiapp.xml" units on both Android and iOS. There might be an edge case that the new code isn't considering. I don't have time to look at it yet other than to post the code change here for the moment.
#12320

@alexlarocca
Copy link
Sponsor Contributor Author

I was aware of this change but, as I wrote, it's not a conversion issue. That function is working properly.
The problem seems to be related to animation and the way it updates the view properties. If I run a single animation, it works well. But listening to touchmove event, a lot of animations occurs. And I guess that when a new animation starts, probably the previous one has not updated yet the view position. Indeed the rotation seems to start from the initial position

@m1ga
Copy link
Contributor

m1ga commented Nov 3, 2021

If you use a touchstart instead of move (and remove the click) you can see a difference:
if you click in the bottom right corner of the red square the box will rotate. 9.3.2: you can click again and the handle stays. 10.0.2+ the handle moves again. There is a different e.x/e.y inside the touchstart event but I'm not sure why or how to fix it. For the Android example I moved the touch event on the outer view, not the handle so the coordinates won't change

@alexlarocca
Copy link
Sponsor Contributor Author

Solved thanks to @m1ga tip. On rotateHand, delta must to be calculated starting from the position when touch started.

With this change, it works on SDK 10.x and no more on SDK 9.3.2. But it does not matter.

var initialDegrees;
var currentDegrees = 90;

hourHand.addEventListener('touchstart', function(e) {
	var convPoint = e.source.convertPointToView({x: e.x, y: e.y}, clockView);
	var point = {x: convPoint.x - (SIZE / 2), y: convPoint.y - (SIZE / 2)};
	initialDegrees = getDegrees(point);
});

function getDegrees(point) {
	return Math.round(angle({x: 0, y: 0}, point));
}

function rotateHand(e) {
	var point = {x: e.x - (SIZE / 2), y: e.y - (SIZE / 2)};
	var delta =  getDegrees(point) - initialDegrees;

	currentDegrees += delta;

	if (delta != 0) {
		degreesLabel.text = currentDegrees + '°';
		hourHand.t = hourHand.t.rotate(delta);
		hourHand.animate({transform: hourHand.t, duration: 10});
	}	
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants