Showing posts with label rotation. Show all posts
Showing posts with label rotation. Show all posts

Sunday, November 19, 2017

Dragging a rotated view by adjusting layout params

Leave a Comment

I am trying to make a view follow my finger and do some rotation and scaling in multitouch with the following code

@Override public boolean onTouch(View view, MotionEvent motionEvent) {      final int action = motionEvent.getActionMasked();     int newPosX,newPosY;     switch (action) {         case MotionEvent.ACTION_DOWN: {             final int pointerIndex = motionEvent.getActionIndex();             final float x = motionEvent.getX( pointerIndex);             final float y = motionEvent.getY( pointerIndex);              RelativeLayout.LayoutParams parms = (RelativeLayout.LayoutParams) view.getLayoutParams();              // Remember where we started (for dragging)             mLastTouchX = (int) x;             mLastTouchY = (int) y;             // Save the ID of this pointer (for dragging)             mActivePointerId = motionEvent.getPointerId( 0);             break;         }          case MotionEvent.ACTION_MOVE: {             if(motionEvent.getPointerCount()==2){                 float newDist = spacing(motionEvent);                 float scale = newDist / oldDist * view.getScaleX();                 view.setScaleY(scale);                 view.setScaleX(scale);                  float newAngle = rotation(motionEvent);                 float a = newAngle - oldAngle;                 view.animate().rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator()).start();             }             // Find the index of the active pointer and fetch its position             final int pointerIndex =                     motionEvent.findPointerIndex( mActivePointerId);              final float x = motionEvent.getX( pointerIndex);             final float y = motionEvent.getY( pointerIndex);              // Calculate the distance moved             final float dx = x - mLastTouchX;             final float dy = y - mLastTouchY;             RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();              layoutParams.leftMargin += dx;             layoutParams.topMargin += dy;              view.setLayoutParams(layoutParams);              break;         }         case MotionEvent.ACTION_POINTER_DOWN:{             oldDist = spacing(motionEvent);             oldAngle = rotation(motionEvent);             break;         }          case MotionEvent.ACTION_UP: {             mActivePointerId = INVALID_POINTER_ID;             break;         }          case MotionEvent.ACTION_CANCEL: {             mActivePointerId = INVALID_POINTER_ID;             break;         }          case MotionEvent.ACTION_POINTER_UP: {              final int pointerIndex = motionEvent.getActionIndex();             final int pointerId = motionEvent.getPointerId( pointerIndex);              if (pointerId == mActivePointerId) {                 // This was our active pointer going up. Choose a new                 // active pointer and adjust accordingly.                 final int newPointerIndex = pointerIndex == 0 ? 1 : 0;                 mLastTouchX = (int) motionEvent.getX( newPointerIndex);                 mLastTouchY = (int) motionEvent.getY( newPointerIndex);                 mActivePointerId = motionEvent.getPointerId( newPointerIndex);             }             break;         }     }     return true;  }     private float spacing(MotionEvent event) {     float x = event.getX(0) - event.getX(1);     float y = event.getY(0) - event.getY(1);     return (float) Math.sqrt(x * x + y * y); }  private float rotation(MotionEvent event) {     double delta_x = (event.getX(0) - event.getX(1));     double delta_y = (event.getY(0) - event.getY(1));     double radians = Math.atan2(delta_y, delta_x);     return (float) Math.toDegrees(radians); } 

Everything is working well until the view is rotated. When it is rotated above 90 degrees and we try to drag it it's jumping around the touch point. I think it has something to do with

layoutParams.leftMargin += dx; layoutParams.topMargin += dy;  setLayoutParams(layoutParams); 

I am working to make this work for last two days with no success.

NOTE: what I am trying to achieve is to make a view drag rotate and scale with 2 fingers(drag with single finger also) I followed the drag code from Google's documentation so as to make it not jump while switching fingers. I am using this to rotate view.animate().rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator()).start();

because when i use view.setRotate(),the view is vibrating.

EDIT 1: I removed

layoutParams.leftMargin += dx; layoutParams.topMargin += dy; 

and replaced it with:

//To get the moved distance of the finger(X and Y)  float diffX = motionEvent.getX(pointerIndex) - mLastTouchX;                     float diffY = motionEvent.getY(pointerIndex) - mLastTouchY;  //to get the distance from touch point and the top or left of the view                     final float dx = motionEvent.getRawX() - (motionEvent.getRawX()-motionEvent.getX());                     final float dy = motionEvent.getRawY() - (motionEvent.getRawY()-motionEvent.getY());                     RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();  //Settings appropriate value for the margin top and margin left.                      layoutParams.leftMargin = (int) ((( motionEvent.getRawX() )-dx )+ diffX );                     layoutParams.topMargin = (int) ((( motionEvent.getRawY() )-dy )+ diffY ); 

Now even after rotating the view is not moving around. but when i switch the active finger its jumping around from the actual position.

On ACTION_POINTER_UP i am doing this to change shift the active finger

case MotionEvent.ACTION_POINTER_UP: {                  final int pointerIndex = motionEvent.getActionIndex();                 final int pointerId = motionEvent.getPointerId( pointerIndex);                  if (pointerId == mActivePointerId) {                     // This was our active pointer going up. Choose a new                     // active pointer and adjust accordingly.                     final int newPointerIndex = pointerIndex == 0 ? 1 : 0;                     Log.d(TAG,"New pointer index :"+newPointerIndex);                     mLastTouchX = (int) motionEvent.getX( newPointerIndex);                     mLastTouchY = (int) motionEvent.getY( newPointerIndex);                     mActivePointerId = motionEvent.getPointerId( newPointerIndex);                 }                 break;             } 

0 Answers

Read More

Sunday, August 20, 2017

Rotate android layout view about its center using touch listener

Leave a Comment

Here is how my set up to rotate looks.

enter image description here

I am listening for action down and move on the rotation icon, trying to calculate the angle of rotation and applying that angle of rotation to entire layout encapsulating the edittext. The applied rotation has to be about the center of encapsulating relative layout.

Here is how I am trying to achieve this, in the touchListener for rotation icon.

if(v == ivRotateSticker){           //TODO grab xc and yc using (top and bottom)/2 and (left and right)/2 to grab center of sticker after each rotation         final float x = event.getX();         final float y = event.getY();         rlTextStickerLayout.getGlobalVisibleRect(myViewRect);         xc = myViewRect.width()/2;         yc = myViewRect.height()/2;          dx = scaleReceiver.getWidth() - myViewRect.width();         dy = scaleReceiver.getHeight() - myViewRect.height();          leftBound = scaleReceiver.getX();         topBound = scaleReceiver.getY();          switch (event.getAction()){              case MotionEvent.ACTION_DOWN:                 mViewAngle = rlTextStickerLayout.getRotation();                 mPrevAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));                  break;              case MotionEvent.ACTION_MOVE:                  Log.d("EventRegistered", " " + event.getRawX() + "--" + dx + " -- " + dy);                  mCurrAngle = Math.toDegrees(Math.atan2(x - xc, yc - y));                 if (x >= leftBound && y >= topBound && x <= dx && y <= dy) {                     float rot = (float) (mViewAngle + mCurrAngle - mPrevAngle);                     rlTextStickerLayout.setRotation((float) (mViewAngle + mCurrAngle - mPrevAngle));                     Log.d("stickerRotation"," "+rot);                 }                 break;          }          return true;      } 

But the resulting rotation is glitchy and not as desired smooth. Also, if I move the sticker to a different location, how do I update the new center for rotation, as rotation after moving the sticker dramatically changes the center of rotation. How can I achieve a far more smooth rotation?

2 Answers

Answers 1

  1. View's rotation to be animated to the specified values (90, 180, 270) in 1000ms:

    view.animate().rotation(90f).setDuration(1000).start(); view.animate().rotation(180f).setDuration(1000).start(); view.animate().rotation(270f).setDuration(1000).start();

  2. Using this library you can rotate whole view hierarchy https://github.com/rongi/rotate-layout

Answers 2

I think this library will help you a lot.

https://github.com/kencheung4/android-StickerView

its smooth and easy.

Read More

Wednesday, February 15, 2017

iOS: Default IB popover transition does strange things

Leave a Comment

I bumped into a strange issue where when a view controller is presented in a popover, the presenting view controllers view is not snapped to the bottom edge of it's superview, in that case the window itself.

AppDelegate code:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {     // Override point for customization after application launch.     let window = UIWindow(frame: UIScreen.main.bounds)     window.rootViewController = UIStoryboard(name: "NavigationController", bundle: Bundle.main).instantiateInitialViewController()     window.makeKeyAndVisible()     window.backgroundColor = .yellow // Needed to detect the issue.     self.window = window      return true } 

Storyboard to test:

<?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="4lt-Df-IeL">     <device id="retina5_5" orientation="portrait">         <adaptation id="fullscreen"/>     </device>     <dependencies>         <deployment identifier="iOS"/>         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>     </dependencies>     <scenes>         <!--Navigation Controller (locked)-->         <scene sceneID="ryr-GW-wBz">             <objects>                 <viewController storyboardIdentifier="NavigationController" definesPresentationContext="YES" id="4lt-Df-IeL" userLabel="Navigation Controller (locked)" sceneMemberID="viewController">                     <layoutGuides>                         <viewControllerLayoutGuide type="top" id="gxR-oc-l6J"/>                         <viewControllerLayoutGuide type="bottom" id="Py7-tH-kHP"/>                     </layoutGuides>                     <view key="view" contentMode="scaleToFill" id="865-DH-bRZ" userLabel="Background View">                         <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>                         <subviews>                             <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="535-Cq-y2B">                                 <rect key="frame" x="54" y="64" width="360" height="618"/>                                 <connections>                                     <segue destination="G7K-pY-ZSi" kind="embed" identifier="ContainerViewController" id="0Mw-mh-5NT"/>                                 </connections>                             </containerView>                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xLz-jb-9OM" userLabel="Left View">                                 <rect key="frame" x="0.0" y="64" width="54" height="672"/>                                 <subviews>                                     <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="bls-BC-WIu" userLabel="Left Stack View">                                         <rect key="frame" x="0.0" y="0.0" width="54" height="672"/>                                     </stackView>                                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Zbx-7u-5oe" userLabel="Hairline View">                                         <rect key="frame" x="53" y="0.0" width="1" height="672"/>                                         <color key="backgroundColor" red="0.43079092749999998" green="0.1140047376" blue="0.1180379456" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                                         <constraints>                                             <constraint firstAttribute="width" constant="1" id="kna-vk-GlF" customClass="OnePixelConstraint" customModule="segue_issue" customModuleProvider="target"/>                                         </constraints>                                     </view>                                 </subviews>                                 <color key="backgroundColor" red="0.627" green="0.114" blue="0.14099999999999999" alpha="1" colorSpace="calibratedRGB"/>                                 <constraints>                                     <constraint firstAttribute="width" constant="54" id="2bA-Ap-aup"/>                                     <constraint firstItem="bls-BC-WIu" firstAttribute="leading" secondItem="xLz-jb-9OM" secondAttribute="leading" id="3sM-Bd-eEq"/>                                     <constraint firstAttribute="bottom" secondItem="Zbx-7u-5oe" secondAttribute="bottom" id="9PW-0y-kBv"/>                                     <constraint firstAttribute="trailing" secondItem="Zbx-7u-5oe" secondAttribute="trailing" id="RlN-G4-8iD"/>                                     <constraint firstAttribute="trailing" secondItem="bls-BC-WIu" secondAttribute="trailing" id="anE-HT-oQp"/>                                     <constraint firstItem="Zbx-7u-5oe" firstAttribute="top" secondItem="xLz-jb-9OM" secondAttribute="top" id="bxG-xS-wdV"/>                                     <constraint firstItem="bls-BC-WIu" firstAttribute="top" secondItem="xLz-jb-9OM" secondAttribute="top" id="ds3-z5-Dpv"/>                                     <constraint firstAttribute="bottom" secondItem="bls-BC-WIu" secondAttribute="bottom" id="f9r-FV-enN"/>                                 </constraints>                             </view>                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="V3o-XH-Xkn" userLabel="Bottom View">                                 <rect key="frame" x="0.0" y="682" width="414" height="54"/>                                 <subviews>                                     <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="fM3-hA-kGa" userLabel="Bottom Stack View">                                         <rect key="frame" x="0.0" y="0.0" width="414" height="54"/>                                     </stackView>                                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Gtr-bO-frP" userLabel="Hairline View">                                         <rect key="frame" x="0.0" y="0.0" width="414" height="1"/>                                         <color key="backgroundColor" red="0.43079092749999998" green="0.1140047376" blue="0.1180379456" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                                         <constraints>                                             <constraint firstAttribute="height" constant="1" id="K5f-m2-BpE" customClass="OnePixelConstraint" customModule="segue_issue" customModuleProvider="target"/>                                         </constraints>                                     </view>                                 </subviews>                                 <color key="backgroundColor" red="0.627" green="0.114" blue="0.14099999999999999" alpha="1" colorSpace="calibratedRGB"/>                                 <constraints>                                     <constraint firstItem="Gtr-bO-frP" firstAttribute="leading" secondItem="V3o-XH-Xkn" secondAttribute="leading" id="9fX-NI-RdG"/>                                     <constraint firstAttribute="bottom" secondItem="fM3-hA-kGa" secondAttribute="bottom" id="KxS-jW-8Rh"/>                                     <constraint firstItem="fM3-hA-kGa" firstAttribute="top" secondItem="V3o-XH-Xkn" secondAttribute="top" id="VLk-U3-Dgt"/>                                     <constraint firstAttribute="trailing" secondItem="Gtr-bO-frP" secondAttribute="trailing" id="aDz-aj-8ah"/>                                     <constraint firstAttribute="trailing" secondItem="fM3-hA-kGa" secondAttribute="trailing" id="bzw-Bv-nvH"/>                                     <constraint firstAttribute="height" constant="54" id="ghd-qS-t3l"/>                                     <constraint firstItem="Gtr-bO-frP" firstAttribute="top" secondItem="V3o-XH-Xkn" secondAttribute="top" id="nZz-Tn-i7X"/>                                     <constraint firstItem="fM3-hA-kGa" firstAttribute="leading" secondItem="V3o-XH-Xkn" secondAttribute="leading" id="sxO-BS-rki"/>                                 </constraints>                             </view>                             <navigationBar contentMode="scaleToFill" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SAV-Rj-fPh">                                 <rect key="frame" x="0.0" y="0.0" width="414" height="64"/>                                 <color key="barTintColor" red="0.627" green="0.114" blue="0.14099999999999999" alpha="1" colorSpace="calibratedRGB"/>                                 <textAttributes key="titleTextAttributes">                                     <fontDescription key="fontDescription" type="system" pointSize="18"/>                                     <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>                                     <offsetWrapper key="textShadowOffset" horizontal="0.0" vertical="0.0"/>                                 </textAttributes>                             </navigationBar>                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NmK-Xz-xl3" userLabel="Navigation Bar Hairline">                                 <rect key="frame" x="0.0" y="64" width="414" height="1"/>                                 <color key="backgroundColor" red="0.43079092750694548" green="0.11400473755687479" blue="0.11803794560598729" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                                 <constraints>                                     <constraint firstAttribute="height" constant="1" id="ENM-UW-O3D" customClass="OnePixelConstraint" customModule="segue_issue" customModuleProvider="target"/>                                 </constraints>                             </view>                             <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="alk-Uo-pMv">                                 <rect key="frame" x="192" y="0.0" width="46" height="30"/>                                 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>                                 <state key="normal" title="Button"/>                                 <connections>                                     <segue destination="G7K-pY-ZSi" kind="popoverPresentation" popoverAnchorView="alk-Uo-pMv" id="XuB-dB-CVh">                                         <popoverArrowDirection key="popoverArrowDirection" up="YES" down="YES" left="YES" right="YES"/>                                     </segue>                                 </connections>                             </button>                         </subviews>                         <constraints>                             <constraint firstItem="535-Cq-y2B" firstAttribute="leading" secondItem="xLz-jb-9OM" secondAttribute="trailing" id="0Ya-fi-fwL"/>                             <constraint firstItem="535-Cq-y2B" firstAttribute="trailing" secondItem="865-DH-bRZ" secondAttribute="trailing" id="2xc-7B-pd6"/>                             <constraint firstAttribute="trailing" secondItem="V3o-XH-Xkn" secondAttribute="trailing" id="4Qi-nQ-1b5"/>                             <constraint firstAttribute="trailing" secondItem="NmK-Xz-xl3" secondAttribute="trailing" id="4nX-tS-V49"/>                             <constraint firstAttribute="bottom" secondItem="V3o-XH-Xkn" secondAttribute="top" constant="54" id="8oE-54-0JN"/>                             <constraint firstItem="SAV-Rj-fPh" firstAttribute="top" secondItem="865-DH-bRZ" secondAttribute="top" id="DdA-dN-ucd"/>                             <constraint firstItem="V3o-XH-Xkn" firstAttribute="leading" secondItem="865-DH-bRZ" secondAttribute="leading" id="KzS-R2-JSi"/>                             <constraint firstItem="SAV-Rj-fPh" firstAttribute="bottom" secondItem="gxR-oc-l6J" secondAttribute="bottom" constant="44" id="Okf-F1-Bwv">                                 <variation key="heightClass=regular-widthClass=regular" constant="64"/>                             </constraint>                             <constraint firstItem="NmK-Xz-xl3" firstAttribute="top" secondItem="SAV-Rj-fPh" secondAttribute="bottom" id="Z7z-vD-Ypi"/>                             <constraint firstItem="SAV-Rj-fPh" firstAttribute="leading" secondItem="865-DH-bRZ" secondAttribute="leading" id="ZYY-Wz-1eh"/>                             <constraint firstAttribute="trailing" secondItem="SAV-Rj-fPh" secondAttribute="trailing" id="ein-Qv-Vwc"/>                             <constraint firstAttribute="bottom" secondItem="xLz-jb-9OM" secondAttribute="bottom" id="fmP-cS-nYy"/>                             <constraint firstItem="NmK-Xz-xl3" firstAttribute="leading" secondItem="865-DH-bRZ" secondAttribute="leading" id="nYe-rf-Zht"/>                             <constraint firstItem="xLz-jb-9OM" firstAttribute="top" secondItem="SAV-Rj-fPh" secondAttribute="bottom" id="tqI-Vx-dCH"/>                             <constraint firstAttribute="leading" secondItem="xLz-jb-9OM" secondAttribute="trailing" constant="-54" id="vuB-AY-U4j"/>                             <constraint firstItem="V3o-XH-Xkn" firstAttribute="top" secondItem="535-Cq-y2B" secondAttribute="bottom" id="wCH-Rs-saK"/>                             <constraint firstItem="535-Cq-y2B" firstAttribute="top" secondItem="SAV-Rj-fPh" secondAttribute="bottom" id="yeH-A6-JEo"/>                         </constraints>                     </view>                     <extendedEdge key="edgesForExtendedLayout"/>                     <simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>                     <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>                     <size key="freeformSize" width="414" height="736"/>                 </viewController>                 <placeholder placeholderIdentifier="IBFirstResponder" id="bpj-us-mEU" userLabel="First Responder" sceneMemberID="firstResponder"/>             </objects>             <point key="canvasLocation" x="681" y="-398"/>         </scene>         <!--View Controller-->         <scene sceneID="O4R-kZ-Pdk">             <objects>                 <viewController storyboardIdentifier="ContainerViewController" id="G7K-pY-ZSi" sceneMemberID="viewController">                     <layoutGuides>                         <viewControllerLayoutGuide type="top" id="ffW-Hu-TSB"/>                         <viewControllerLayoutGuide type="bottom" id="0mf-BW-Ssn"/>                     </layoutGuides>                     <view key="view" contentMode="scaleToFill" id="x2i-Md-44j">                         <rect key="frame" x="0.0" y="0.0" width="360" height="618"/>                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>                         <color key="backgroundColor" red="0.94235802664974622" green="0.91986702625601058" blue="0.90890064764795653" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                     </view>                 </viewController>                 <placeholder placeholderIdentifier="IBFirstResponder" id="B2f-Up-4gW" userLabel="First Responder" sceneMemberID="firstResponder"/>             </objects>             <point key="canvasLocation" x="1537.68115942029" y="-398.64130434782612"/>         </scene>     </scenes>     <inferredMetricsTieBreakers>         <segue reference="XuB-dB-CVh"/>     </inferredMetricsTieBreakers>     <color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/> </document> 

Copy everything inside a new project, remove main as the main storyboard to launch.

  1. Run the project on an iPhone X Plus simulator (or real device).
  2. Click on the bottom to present a view controller. 2.1. Enable slow motion (simulator only).
  3. Rotate your device.

The issue I'm talking about is when the yellow view is visible (window). One rotation does layout the presenting view controller correctly, the other does begin in wrong state.

enter image description here

Is that a bug that my storyboard has or something from UIKit?

Update: The project uses latest iOS SDK and no deprecated APIs (as shown above 'almost everything is build with IB').

Update 2: I updated the original sentence to make it crystal clear that it's not a UIPopoverController.

0 Answers

Read More

Sunday, February 5, 2017

iOS: Default IB popover transition does strange things

Leave a Comment

I bumped into a strange issue where when a popover view controller is presended, the presenting view controllers view is not snapped to the bottom edge of it's superview, in that case the window itself.

AppDelegate code:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {     // Override point for customization after application launch.     let window = UIWindow(frame: UIScreen.main.bounds)     window.rootViewController = UIStoryboard(name: "NavigationController", bundle: Bundle.main).instantiateInitialViewController()     window.makeKeyAndVisible()     window.backgroundColor = .yellow // Needed to detect the issue.     self.window = window      return true } 

Storyboard to test:

<?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="4lt-Df-IeL">     <device id="retina5_5" orientation="portrait">         <adaptation id="fullscreen"/>     </device>     <dependencies>         <deployment identifier="iOS"/>         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>     </dependencies>     <scenes>         <!--Navigation Controller (locked)-->         <scene sceneID="ryr-GW-wBz">             <objects>                 <viewController storyboardIdentifier="NavigationController" definesPresentationContext="YES" id="4lt-Df-IeL" userLabel="Navigation Controller (locked)" sceneMemberID="viewController">                     <layoutGuides>                         <viewControllerLayoutGuide type="top" id="gxR-oc-l6J"/>                         <viewControllerLayoutGuide type="bottom" id="Py7-tH-kHP"/>                     </layoutGuides>                     <view key="view" contentMode="scaleToFill" id="865-DH-bRZ" userLabel="Background View">                         <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>                         <subviews>                             <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="535-Cq-y2B">                                 <rect key="frame" x="54" y="64" width="360" height="618"/>                                 <connections>                                     <segue destination="G7K-pY-ZSi" kind="embed" identifier="ContainerViewController" id="0Mw-mh-5NT"/>                                 </connections>                             </containerView>                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xLz-jb-9OM" userLabel="Left View">                                 <rect key="frame" x="0.0" y="64" width="54" height="672"/>                                 <subviews>                                     <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="bls-BC-WIu" userLabel="Left Stack View">                                         <rect key="frame" x="0.0" y="0.0" width="54" height="672"/>                                     </stackView>                                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Zbx-7u-5oe" userLabel="Hairline View">                                         <rect key="frame" x="53" y="0.0" width="1" height="672"/>                                         <color key="backgroundColor" red="0.43079092749999998" green="0.1140047376" blue="0.1180379456" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                                         <constraints>                                             <constraint firstAttribute="width" constant="1" id="kna-vk-GlF" customClass="OnePixelConstraint" customModule="segue_issue" customModuleProvider="target"/>                                         </constraints>                                     </view>                                 </subviews>                                 <color key="backgroundColor" red="0.627" green="0.114" blue="0.14099999999999999" alpha="1" colorSpace="calibratedRGB"/>                                 <constraints>                                     <constraint firstAttribute="width" constant="54" id="2bA-Ap-aup"/>                                     <constraint firstItem="bls-BC-WIu" firstAttribute="leading" secondItem="xLz-jb-9OM" secondAttribute="leading" id="3sM-Bd-eEq"/>                                     <constraint firstAttribute="bottom" secondItem="Zbx-7u-5oe" secondAttribute="bottom" id="9PW-0y-kBv"/>                                     <constraint firstAttribute="trailing" secondItem="Zbx-7u-5oe" secondAttribute="trailing" id="RlN-G4-8iD"/>                                     <constraint firstAttribute="trailing" secondItem="bls-BC-WIu" secondAttribute="trailing" id="anE-HT-oQp"/>                                     <constraint firstItem="Zbx-7u-5oe" firstAttribute="top" secondItem="xLz-jb-9OM" secondAttribute="top" id="bxG-xS-wdV"/>                                     <constraint firstItem="bls-BC-WIu" firstAttribute="top" secondItem="xLz-jb-9OM" secondAttribute="top" id="ds3-z5-Dpv"/>                                     <constraint firstAttribute="bottom" secondItem="bls-BC-WIu" secondAttribute="bottom" id="f9r-FV-enN"/>                                 </constraints>                             </view>                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="V3o-XH-Xkn" userLabel="Bottom View">                                 <rect key="frame" x="0.0" y="682" width="414" height="54"/>                                 <subviews>                                     <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="fM3-hA-kGa" userLabel="Bottom Stack View">                                         <rect key="frame" x="0.0" y="0.0" width="414" height="54"/>                                     </stackView>                                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Gtr-bO-frP" userLabel="Hairline View">                                         <rect key="frame" x="0.0" y="0.0" width="414" height="1"/>                                         <color key="backgroundColor" red="0.43079092749999998" green="0.1140047376" blue="0.1180379456" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                                         <constraints>                                             <constraint firstAttribute="height" constant="1" id="K5f-m2-BpE" customClass="OnePixelConstraint" customModule="segue_issue" customModuleProvider="target"/>                                         </constraints>                                     </view>                                 </subviews>                                 <color key="backgroundColor" red="0.627" green="0.114" blue="0.14099999999999999" alpha="1" colorSpace="calibratedRGB"/>                                 <constraints>                                     <constraint firstItem="Gtr-bO-frP" firstAttribute="leading" secondItem="V3o-XH-Xkn" secondAttribute="leading" id="9fX-NI-RdG"/>                                     <constraint firstAttribute="bottom" secondItem="fM3-hA-kGa" secondAttribute="bottom" id="KxS-jW-8Rh"/>                                     <constraint firstItem="fM3-hA-kGa" firstAttribute="top" secondItem="V3o-XH-Xkn" secondAttribute="top" id="VLk-U3-Dgt"/>                                     <constraint firstAttribute="trailing" secondItem="Gtr-bO-frP" secondAttribute="trailing" id="aDz-aj-8ah"/>                                     <constraint firstAttribute="trailing" secondItem="fM3-hA-kGa" secondAttribute="trailing" id="bzw-Bv-nvH"/>                                     <constraint firstAttribute="height" constant="54" id="ghd-qS-t3l"/>                                     <constraint firstItem="Gtr-bO-frP" firstAttribute="top" secondItem="V3o-XH-Xkn" secondAttribute="top" id="nZz-Tn-i7X"/>                                     <constraint firstItem="fM3-hA-kGa" firstAttribute="leading" secondItem="V3o-XH-Xkn" secondAttribute="leading" id="sxO-BS-rki"/>                                 </constraints>                             </view>                             <navigationBar contentMode="scaleToFill" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SAV-Rj-fPh">                                 <rect key="frame" x="0.0" y="0.0" width="414" height="64"/>                                 <color key="barTintColor" red="0.627" green="0.114" blue="0.14099999999999999" alpha="1" colorSpace="calibratedRGB"/>                                 <textAttributes key="titleTextAttributes">                                     <fontDescription key="fontDescription" type="system" pointSize="18"/>                                     <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>                                     <offsetWrapper key="textShadowOffset" horizontal="0.0" vertical="0.0"/>                                 </textAttributes>                             </navigationBar>                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NmK-Xz-xl3" userLabel="Navigation Bar Hairline">                                 <rect key="frame" x="0.0" y="64" width="414" height="1"/>                                 <color key="backgroundColor" red="0.43079092750694548" green="0.11400473755687479" blue="0.11803794560598729" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                                 <constraints>                                     <constraint firstAttribute="height" constant="1" id="ENM-UW-O3D" customClass="OnePixelConstraint" customModule="segue_issue" customModuleProvider="target"/>                                 </constraints>                             </view>                             <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="alk-Uo-pMv">                                 <rect key="frame" x="192" y="0.0" width="46" height="30"/>                                 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>                                 <state key="normal" title="Button"/>                                 <connections>                                     <segue destination="G7K-pY-ZSi" kind="popoverPresentation" popoverAnchorView="alk-Uo-pMv" id="XuB-dB-CVh">                                         <popoverArrowDirection key="popoverArrowDirection" up="YES" down="YES" left="YES" right="YES"/>                                     </segue>                                 </connections>                             </button>                         </subviews>                         <constraints>                             <constraint firstItem="535-Cq-y2B" firstAttribute="leading" secondItem="xLz-jb-9OM" secondAttribute="trailing" id="0Ya-fi-fwL"/>                             <constraint firstItem="535-Cq-y2B" firstAttribute="trailing" secondItem="865-DH-bRZ" secondAttribute="trailing" id="2xc-7B-pd6"/>                             <constraint firstAttribute="trailing" secondItem="V3o-XH-Xkn" secondAttribute="trailing" id="4Qi-nQ-1b5"/>                             <constraint firstAttribute="trailing" secondItem="NmK-Xz-xl3" secondAttribute="trailing" id="4nX-tS-V49"/>                             <constraint firstAttribute="bottom" secondItem="V3o-XH-Xkn" secondAttribute="top" constant="54" id="8oE-54-0JN"/>                             <constraint firstItem="SAV-Rj-fPh" firstAttribute="top" secondItem="865-DH-bRZ" secondAttribute="top" id="DdA-dN-ucd"/>                             <constraint firstItem="V3o-XH-Xkn" firstAttribute="leading" secondItem="865-DH-bRZ" secondAttribute="leading" id="KzS-R2-JSi"/>                             <constraint firstItem="SAV-Rj-fPh" firstAttribute="bottom" secondItem="gxR-oc-l6J" secondAttribute="bottom" constant="44" id="Okf-F1-Bwv">                                 <variation key="heightClass=regular-widthClass=regular" constant="64"/>                             </constraint>                             <constraint firstItem="NmK-Xz-xl3" firstAttribute="top" secondItem="SAV-Rj-fPh" secondAttribute="bottom" id="Z7z-vD-Ypi"/>                             <constraint firstItem="SAV-Rj-fPh" firstAttribute="leading" secondItem="865-DH-bRZ" secondAttribute="leading" id="ZYY-Wz-1eh"/>                             <constraint firstAttribute="trailing" secondItem="SAV-Rj-fPh" secondAttribute="trailing" id="ein-Qv-Vwc"/>                             <constraint firstAttribute="bottom" secondItem="xLz-jb-9OM" secondAttribute="bottom" id="fmP-cS-nYy"/>                             <constraint firstItem="NmK-Xz-xl3" firstAttribute="leading" secondItem="865-DH-bRZ" secondAttribute="leading" id="nYe-rf-Zht"/>                             <constraint firstItem="xLz-jb-9OM" firstAttribute="top" secondItem="SAV-Rj-fPh" secondAttribute="bottom" id="tqI-Vx-dCH"/>                             <constraint firstAttribute="leading" secondItem="xLz-jb-9OM" secondAttribute="trailing" constant="-54" id="vuB-AY-U4j"/>                             <constraint firstItem="V3o-XH-Xkn" firstAttribute="top" secondItem="535-Cq-y2B" secondAttribute="bottom" id="wCH-Rs-saK"/>                             <constraint firstItem="535-Cq-y2B" firstAttribute="top" secondItem="SAV-Rj-fPh" secondAttribute="bottom" id="yeH-A6-JEo"/>                         </constraints>                     </view>                     <extendedEdge key="edgesForExtendedLayout"/>                     <simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>                     <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>                     <size key="freeformSize" width="414" height="736"/>                 </viewController>                 <placeholder placeholderIdentifier="IBFirstResponder" id="bpj-us-mEU" userLabel="First Responder" sceneMemberID="firstResponder"/>             </objects>             <point key="canvasLocation" x="681" y="-398"/>         </scene>         <!--View Controller-->         <scene sceneID="O4R-kZ-Pdk">             <objects>                 <viewController storyboardIdentifier="ContainerViewController" id="G7K-pY-ZSi" sceneMemberID="viewController">                     <layoutGuides>                         <viewControllerLayoutGuide type="top" id="ffW-Hu-TSB"/>                         <viewControllerLayoutGuide type="bottom" id="0mf-BW-Ssn"/>                     </layoutGuides>                     <view key="view" contentMode="scaleToFill" id="x2i-Md-44j">                         <rect key="frame" x="0.0" y="0.0" width="360" height="618"/>                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>                         <color key="backgroundColor" red="0.94235802664974622" green="0.91986702625601058" blue="0.90890064764795653" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>                     </view>                 </viewController>                 <placeholder placeholderIdentifier="IBFirstResponder" id="B2f-Up-4gW" userLabel="First Responder" sceneMemberID="firstResponder"/>             </objects>             <point key="canvasLocation" x="1537.68115942029" y="-398.64130434782612"/>         </scene>     </scenes>     <inferredMetricsTieBreakers>         <segue reference="XuB-dB-CVh"/>     </inferredMetricsTieBreakers>     <color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/> </document> 

Copy everything inside a new project, remove main as the main storyboard to launch.

  1. Run the project on an iPhone X Plus simulator (or real device).
  2. Click on the bottom to present a view controller. 2.1. Enable slow motion (simulator only).
  3. Rotate your device.

The issue I'm talking about is when the yellow view is visible (window). One rotation does layout the presenting view controller correctly, the other does begin in wrong state.

enter image description here

Is that a bug that my storyboard has or something from UIKit?

0 Answers

Read More

Monday, April 25, 2016

Making a Sphere Rotate in WebGL

Leave a Comment

Not sure what I'm missing here. Trying to make a planet (i.e. sphere) rotate by having the user click on a 'Rotate' button, but can't seem to figure it out. I do have the following segment which rotates the sphere by way of user interaction with the mouse:

    document.onmousemove = function() {         if (!mouseDown) {             return;         }         var newX = event.clientX;         var newY = event.clientY;          var deltaX = newX - lastMouseX         var newRotationMatrix = mat4.create();         mat4.identity(newRotationMatrix);         mat4.rotate(newRotationMatrix, degToRad(deltaX / 10), [0, 1, 0]);          var deltaY = newY - lastMouseY;         mat4.rotate(newRotationMatrix, degToRad(deltaY / 10), [1, 0, 0]);          mat4.multiply(newRotationMatrix, planetRotationMatrix, planetRotationMatrix);          lastMouseX = newX         lastMouseY = newY; } 

This one works fine, but I also want to make the planet rotate automatically after the user clicks the button. Here is my onLoad function:

    window.onload = function onLoad() {         canvas = document.getElementById("gl-canvas");         initGL(canvas);         initShaders();         initBuffers();         initTexture();         initEvtHandlers();          gl.clearColor(0.0, 0.0, 0.0, 1.0);         gl.enable(gl.DEPTH_TEST);          var newRotationMatrix = mat4.create();         mat4.identity(newRotationMatrix);         document.getElementById("rotate").onclick = function () {             // rotation code goes here?         }         render();  } 

My question is: How can I 'toggle' the rotation after the user clicks the button? So far what I've tried is modify the onmousemove function in an attempt to make the sphere rotate without user interaction, but that's not working.

As an update, here is a new doRotate() function I added:

var myRotationMatrix = mat4.create(); mat4.identity(myRotationMatrix);  doRotate = function () {     var dx = 1;     var newMatrix = mat4.create();     mat4.identity(newMatrix);     mat4.rotate(newMatrix, degToRad(dx / 10), [0, 1, 0]);      mat4.multiply(newMatrix, myRotationMatrix);     requestAnimFrame(doRotate); } 

Which is currently not working for me. This function is supposed to be called when the button is clicked, toggling the rotation.

Update:

For a similar demo, please see this page. What I'm trying to do is make the sphere rotate automatically after the user clicks the relevant button. This is obviously not in the demo linked--that's only for clarification purposes.

Update 2:

I've since figured it out. Please see my answer below for details.

0 Answers

Read More

Tuesday, March 8, 2016

How to rotate left or right in Cesium Map based on view bounds

Leave a Comment

Want to mimic the left-right arrow keys in CesiumJS app similar to Google Earth navigation. Press right or left arrow keys should rotate the globe ~5% of the view bounds to the right or left, respectively. If zoomed out then it rotates a large extent and zoomed in rotates a smaller extent.

Already looked at the documentation for Viewer, Camera, Scene, etc. but it's not obvious how to do something that should be simple.

Able to rotate a fixed amount right or left but want to rotate amount based on the width in the view extent. How do you get the max extent top, left, right, bottom for the view in cesium?

var viewer = new Cesium.Viewer('cesiumContainer', {   navigationHelpButton: false, animation: false, timeline: false }); var camera = viewer.camera; document.addEventListener('keydown', function(e) {     setKey(e); }, false);  function setKey(event) {    if (event.keyCode == 39) {  // right arrow    camera.rotateRight(Cesium.Math.toRadians(10.0));  } else if (event.keyCode == 37) {  // left arrow   camera.rotateLeft(Cesium.Math.toRadians(10.0));  } } 

To test, visit SandCastle app and paste in the javascript snippet above. To activate the keyboard bindings, click full screen mode and the arrow keys will work.

Alternatively, the camera can be used to access positionCartographic, but this is only the cartographic position of the camera, not the view bounds.

  var positionCartographic = camera.positionCartographic;   var height = positionCartographic.height;   var lat = positionCartographic.latitude;                 var lon = positionCartographic.longitude + Cesium.Math.toRadians(10.0);       camera.flyTo({     destination: Cesium.Cartesian3.fromRadians(lon, lat, height),     duration: 1.0   }); 

Here a fixed angle is added to the center view point, but the angle needs to be a percentage of the difference between max and min longitude values in the view extent; e.g. angle = (maxLon - minLon) / 20

1 Answers

Answers 1

You're in luck. The much-requested feature for Camera.computeViewRectangle was just added in Cesium 1.19, released about a week ago as of this writing. Here it is in action.

Note that browsers are generally not comfortable with embedded documents receiving keypress events, so this doesn't work too well as a Stack Snippet. You have to click the magnifying-glass geocoder search box (to get a text entry field), that can receive arrow key events, and then this demo will work. Outside of Stack Overflow, you may find it easier to receive keypresses.

var viewer = new Cesium.Viewer('cesiumContainer', {      navigationHelpButton: false, animation: false, timeline: false  });    var camera = viewer.camera;    document.addEventListener('keydown', function(e) {      setKey(e);  }, false);    function setKey(event) {      var horizontalDegrees = 10.0;      var verticalDegrees = 10.0;      var viewRect = camera.computeViewRectangle();      if (Cesium.defined(viewRect)) {          horizontalDegrees *= Cesium.Math.toDegrees(viewRect.east - viewRect.west) / 360.0;          verticalDegrees *= Cesium.Math.toDegrees(viewRect.north - viewRect.south) / 180.0;      }            if (event.keyCode === 39) {  // right arrow           camera.rotateRight(Cesium.Math.toRadians(horizontalDegrees));      } else if (event.keyCode === 37) {  // left arrow          camera.rotateLeft(Cesium.Math.toRadians(horizontalDegrees));      } else if (event.keyCode === 38) {  // up arrow          camera.rotateUp(Cesium.Math.toRadians(verticalDegrees));      } else if (event.keyCode === 40) {  // down arrow          camera.rotateDown(Cesium.Math.toRadians(verticalDegrees));      }  }
html, body, #cesiumContainer {    width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;    font-family: sans-serif;  }
<link href="http://cesiumjs.org/releases/1.19/Build/Cesium/Widgets/widgets.css"         rel="stylesheet"/>  <script src="http://cesiumjs.org/releases/1.19/Build/Cesium/Cesium.js">  </script>  <div id="cesiumContainer"></div>

Read More