feat: Add 3D rotation to view - takeover of PR# 5950 (#8136)

* feat: add 3d rotation

* chore: fix build errors

* chore: fix tslint errors

* chore: add @types/chai dev dep

* chore: unused import cleanup

* chore: update tests for x,y rotation

* chore: rebase upstream/master

* fix: iOS Affine Transform test verification

* feat(css): Added optional css-tree parser (#8076)

* feat(css): Added optional css-tree parser

* test: css-tree parser compat tests

* test: more css-tree compat tests

* feat(dialogs): Setting the size of popup dialog thru dialog options (#8041)

* Added iOS specific height and width attributes to ShowModalOptions

* Set the height and width of the popup dialog to the presenting controller

* dialog options ios attributes presentationStyle, height & width are made optional

* Updated NativeScript.api.md for public API changes

* Update with git properties

* Public API

* CLA update

* fix: use iOS native-helper for 3d-rotate

* test: Fix tests using _getTransformMismatchError

* fix: view.__hasTransfrom not set updating properly

* test: fix css-animations test page

Co-authored-by: Alexander Vakrilov <alexander.vakrilov@gmail.com>
Co-authored-by: Darin Dimitrov <darin.dimitrov@gmail.com>
Co-authored-by: Shailesh Lolam <slolam@live.com>
Co-authored-by: Dimitar Topuzov <dtopuzov@gmail.com>
This commit is contained in:
Ryan Pendergast
2020-01-10 04:59:46 -06:00
committed by Alexander Vakrilov
parent 8550c3293d
commit e8f5ac8522
31 changed files with 709 additions and 192 deletions

View File

@@ -697,6 +697,27 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
this.style.rotate = value;
}
get rotateX(): number {
return this.style.rotateX;
}
set rotateX(value: number) {
this.style.rotateX = value;
}
get rotateY(): number {
return this.style.rotateY;
}
set rotateY(value: number) {
this.style.rotateY = value;
}
get perspective(): number {
return this.style.perspective;
}
set perspective(value: number) {
this.style.perspective = value;
}
get translateX(): dip {
return this.style.translateX;
}

View File

@@ -10,17 +10,18 @@ import {
} from "./view-common";
import {
Length, PercentLength, Visibility, HorizontalAlignment, VerticalAlignment,
perspectiveProperty, Length, PercentLength, Visibility, HorizontalAlignment, VerticalAlignment,
visibilityProperty, opacityProperty, horizontalAlignmentProperty, verticalAlignmentProperty,
minWidthProperty, minHeightProperty, widthProperty, heightProperty,
marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty,
rotateProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty,
rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty,
zIndexProperty, backgroundInternalProperty, androidElevationProperty, androidDynamicElevationOffsetProperty
} from "../../styling/style-properties";
import { Background, ad as androidBackground } from "../../styling/background";
import { profile } from "../../../profiling";
import { topmost } from "../../frame/frame-stack";
import { screen } from "../../../platform";
import { AndroidActivityBackPressedEventData, android as androidApp } from "../../../application";
import { device } from "../../../platform";
import lazy from "../../../utils/lazy";
@@ -911,6 +912,20 @@ export class View extends ViewCommon {
org.nativescript.widgets.ViewHelper.setRotate(this.nativeViewProtected, float(value));
}
[rotateXProperty.setNative](value: number) {
org.nativescript.widgets.ViewHelper.setRotateX(this.nativeViewProtected, float(value));
}
[rotateYProperty.setNative](value: number) {
org.nativescript.widgets.ViewHelper.setRotateY(this.nativeViewProtected, float(value));
}
[perspectiveProperty.setNative](value: number) {
const scale = screen.mainScreen.scale;
const distance = value * scale;
org.nativescript.widgets.ViewHelper.setPerspective(this.nativeViewProtected, float(distance));
}
[scaleXProperty.setNative](value: number) {
org.nativescript.widgets.ViewHelper.setScaleX(this.nativeViewProtected, float(value));
}

View File

@@ -75,6 +75,11 @@ export interface Point {
* Represents the y coordinate of the location.
*/
y: number;
/**
* Represents the z coordinate of the location.
*/
z?: number;
}
/**
@@ -315,10 +320,26 @@ export abstract class View extends ViewBase {
opacity: number;
/**
* Gets or sets the rotate affine transform of the view.
* Gets or sets the rotate affine transform of the view along the Z axis.
*/
rotate: number;
/**
* Gets or sets the rotate affine transform of the view along the X axis.
*/
rotateX: number;
/**
* Gets or sets the rotate affine transform of the view along the Y axis.
*/
rotateY: number;
/**
* Gets or sets the distance of the camera form the view perspective.
* Usually needed when rotating the view over the X or Y axis.
*/
perspective: number;
/**
* Gets or sets the translateX affine transform of the view in device independent pixels.
*/

View File

@@ -9,10 +9,12 @@ import {
import { ios } from "./view-helper";
import { ios as iosBackground, Background } from "../../styling/background";
import { ios as iosUtils } from "../../../utils/utils";
import { ios as iosNativeHelper } from "../../../utils/native-helper";
import {
Visibility,
perspectiveProperty, Visibility,
visibilityProperty, opacityProperty,
rotateProperty, scaleXProperty, scaleYProperty,
rotateProperty, rotateXProperty, rotateYProperty,
scaleXProperty, scaleYProperty,
translateXProperty, translateYProperty, zIndexProperty,
backgroundInternalProperty, clipPathProperty
} from "../../styling/style-properties";
@@ -156,6 +158,7 @@ export class View extends ViewCommon implements ViewDefinition {
}
public _setNativeViewFrame(nativeView: UIView, frame: CGRect): void {
let oldFrame = this._cachedFrame || nativeView.frame;
if (!CGRectEqualToRect(oldFrame, frame)) {
if (traceEnabled()) {
@@ -166,8 +169,8 @@ export class View extends ViewCommon implements ViewDefinition {
let transform = null;
if (this._hasTransfrom) {
// Always set identity transform before setting frame;
transform = nativeView.transform;
nativeView.transform = CGAffineTransformIdentity;
transform = nativeView.layer.transform;
nativeView.layer.transform = CATransform3DIdentity;
nativeView.frame = frame;
} else {
nativeView.frame = frame;
@@ -177,10 +180,10 @@ export class View extends ViewCommon implements ViewDefinition {
if (adjustedFrame) {
nativeView.frame = adjustedFrame;
}
if (this._hasTransfrom) {
// re-apply the transform after the frame is adjusted
nativeView.transform = transform;
nativeView.layer.transform = transform;
}
const boundsOrigin = nativeView.bounds.origin;
@@ -348,18 +351,25 @@ export class View extends ViewCommon implements ViewDefinition {
public updateNativeTransform() {
const scaleX = this.scaleX || 1e-6;
const scaleY = this.scaleY || 1e-6;
const rotate = this.rotate || 0;
let newTransform = CGAffineTransformIdentity;
newTransform = CGAffineTransformTranslate(newTransform, this.translateX, this.translateY);
newTransform = CGAffineTransformRotate(newTransform, rotate * Math.PI / 180);
newTransform = CGAffineTransformScale(newTransform, scaleX, scaleY);
if (!CGAffineTransformEqualToTransform(this.nativeViewProtected.transform, newTransform)) {
const perspective = this.perspective || 300;
let transform = new CATransform3D(CATransform3DIdentity);
// Only set perspective if there is 3D rotation
if (this.rotateX || this.rotateY) {
transform.m34 = -1 / perspective;
}
transform = CATransform3DTranslate(transform, this.translateX, this.translateY, 0);
transform = iosNativeHelper.applyRotateTransform(transform, this.rotateX, this.rotateY, this.rotate);
transform = CATransform3DScale(transform, scaleX, scaleY, 1);
if (!CATransform3DEqualToTransform(this.nativeViewProtected.layer.transform, transform)) {
const updateSuspended = this._isPresentationLayerUpdateSuspeneded();
if (!updateSuspended) {
CATransaction.begin();
}
this.nativeViewProtected.transform = newTransform;
this._hasTransfrom = this.nativeViewProtected && !CGAffineTransformEqualToTransform(this.nativeViewProtected.transform, CGAffineTransformIdentity);
this.nativeViewProtected.layer.transform = transform;
this._hasTransfrom = this.nativeViewProtected && !CATransform3DEqualToTransform(this.nativeViewProtected.transform3D, CATransform3DIdentity);
if (!updateSuspended) {
CATransaction.commit();
}
@@ -579,6 +589,27 @@ export class View extends ViewCommon implements ViewDefinition {
this.updateNativeTransform();
}
[rotateXProperty.getDefault](): number {
return 0;
}
[rotateXProperty.setNative](value: number) {
this.updateNativeTransform();
}
[rotateYProperty.getDefault](): number {
return 0;
}
[rotateYProperty.setNative](value: number) {
this.updateNativeTransform();
}
[perspectiveProperty.getDefault](): number {
return 300;
}
[perspectiveProperty.setNative](value: number) {
this.updateNativeTransform();
}
[scaleXProperty.getDefault](): number {
return 1;
}