How to animate a UI Element (label) to the top of the screen? - swift3

The logic I want to use is below, just not sure the exact code to pull this info in order to execute. I think I only need to figure out how to get the label height.
let labelHeight = ???
let screenHeight = self.view.bounds.height
let yPosition = ((screenHeight-labelHeight) / 2 ) - ~20
UIView.animate(withDuration: 3, animations: {
self.movingButton.center.y -= yPosition
}
A main question also is how do I pull the height of a specific label, if there are multiple on the screen.
Thanks!

Figured it out after much trial and error!
let buttonHeight = self.movingButton.bounds.height
let screenHeight = self.view.bounds.height
let buttonEndHeight = (screenHeight / 2) - (buttonHeight / 2)
UIView.animate(withDuration: 2, animations: {
self.movingButton.center.y -= buttonEndHeight - 30
I expect this to place the label 30 pixels below the top of the screen on any device.

Related

Sprite Kit Swift - Character accelerate and decelerate

I'm new to Swift Sprite Kit, I wanted to move a node with start speed = 0, until maximum speed when a button is press and hold for 2 seconds and decelerate with -5 speed until minimum speed when the button released. I've done something like this:
func moving(force : CGFloat){
self.player.physicsBody?.applyImpulse(CGVector(dx:force*cos(player.zRotation + 1.57079633), dy: initialforce*sin(player.zRotation + 1.57079633)))
}
In touch function:
let timerAction = SKAction.wait(forDuration: 0.05)
let update = SKAction.run({
if(self.initialforce < Constants.maximumMoveForce){
self.force += 1.0
}else{
self.moving(force: Constants.maximumMoveForce)
self.force = Constants.maximumMoveForce
}
})
let sequence = SKAction.sequence([timerAction, update])
let repeats = SKAction.repeatForever(sequence)
self.run(repeats, withKey:"repeatAction")
and how am I gonna decelerate it at touchEnd? Or am I making wrong approach? Need help.

Calculate videoHeight relative to videoWidth (aspect-ratio) plus 30px - JavaScript

I have a specific video-player which is embedded with an iframe. It has a toolbar at the bottom with a fixed height of 30px.
The video-width is scaled within a bootstrap framework and I want to calculate the height based on the current width.
Like: videoHeight = (videoWidth * 0.5625) + 30px
The value 0.5625 is based on 16*9 aspect-ratio.
Now have I tried the following code:
$(document).ready(function() {
var wide = $('#video-container').css('width');
var calculate = parseInt(wide, 10) * 0.5625;
var videoheight = calculate + 30;
$('#video-container').css('height', videoheight);
});
It works partially, it does calculate the aspect-ratio correctly but it does not add the 30px. Can anybody tell me where I'm going wrong?

How to scale CAShapeLayer to different UIImageView

I have a UIImageView that you can tap on and it draws a circle. I store the location of the circles in an Array of Dictionaries. This allows me to "replay" the drawing of the circles. However, when the UIImageView is a different size from the original, the circles don't scale to the new UIImageView.
How can I get the circles to scale? For demonstration purposes, the top picture is the size of the UIImageView used for input and the second one is the size for replay.
Inputing the circles:
Replay the circles (the circles should be in the blue UIImageView
import Foundation
import UIKit
class DrawPuck {
func drawPuck(circle: CGPoint, circleColour: CGColor, circleSize: CGFloat, imageView: UIImageView) {
let circleBezierPath = UIBezierPath(arcCenter: CGPoint(x: circle.x,y: circle.y), radius: CGFloat(circleSize), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circleBezierPath.cgPath
//change the fill color
shapeLayer.fillColor = circleColour
//you can change the stroke color
shapeLayer.strokeColor = UIColor.white.cgColor
//you can change the line width
shapeLayer.lineWidth = 0.5
imageView.layer.addSublayer(shapeLayer)
}
}
I was able to resolve this with CATransform3DMakeScale As long as I keep the original aspect ratio of the original image it works great.
let width = yellowImageView.frame.width / blueImageView.frame.width
let height = yellowImageView.frame.height / blueImageView.frame.height
shapeLayer.transform = CATransform3DMakeScale(height, width, 1.0)
view.layer.addSublayer(shapeLayer)

AVCapture and zooming of previewLayer in Swift

I have a camera app which allows the user to both take pictures and record video. The iPhone is attached to a medical otoscope using an adapter, so the video that is captured is very small (about the size of a dime). I need to be able to zoom the video to fill the screen, but have not been able to figure out how to do so.
I found this answer here on SO that uses ObjC but have not had success in translating it to Swift. I am very close but am getting stuck. Here is my code for handling a UIPinchGestureRecgoznier:
#IBAction func handlePinchGesture(sender: UIPinchGestureRecognizer) {
var initialVideoZoomFactor: CGFloat = 0.0
if (sender.state == UIGestureRecognizerState.began) {
initialVideoZoomFactor = (captureDevice?.videoZoomFactor)!
} else {
let scale: CGFloat = min(max(1, initialVideoZoomFactor * sender.scale), 4)
CATransaction.begin()
CATransaction.setAnimationDuration(0.01)
previewLayer?.transform = CGAffineTransform(scaleX: scale, y: scale)
CATransaction.commit()
if ((captureDevice?.lockForConfiguration()) != nil) {
captureDevice?.videoZoomFactor = scale
captureDevice?.unlockForConfiguration()
}
}
}
This line...
previewLayer?.transform = CGAffineTransform(scaleX: scale, y: scale)
... gives me the error 'Cannot assign value of type 'CGAffineTransform' to type 'CGTransform3D'. I'm trying to figure this out but my attempts to fix this have been unfruitful.
Figured it out: Changed the problematic line to:
previewLayer?.setAffineTransform(CGAffineTransform(scaleX: scale, y: scale))

Making charts in RaphaelJS that are 100% width?

I have seen graphs in Flash & stuff that basically adapt nicely to whatever the size of the browser or flexible element they are inside of.... I'm not really too well versed with raphaelJS but can you do this, and if so, how?
In raphaeljs, you can call .setSize on a Raphael object to update its size. To adapt to runtime changes in browser window size, you can respond to a window resize event. Using jQuery, you could do:
// initialize Raphael object
var w = $(window).width(),
h = $(window).height();
var paper = Raphael($("#my_element").get(0), w,h);
$(window).resize(function(){
w = $(window).width();
h = $(window).height();
paper.setSize(w,h);
redraw_element(); // code to handle re-drawing, if necessary
});
This will get you a responsive SVG
var w = 500, h=500;
var paper = Raphael(w,h);
paper.setViewBox(0,0,w,h,true);
paper.setSize('100%', '100%');
Normally you could set the width to %100 and define a viewBox within SVG. But, Raphael JS manually set a width and height directly on your SVG elements, which kills this technique.
Bosh's answer is great, but it was distorting the aspect ratio for me. Had to tweak a few things to get it working correctly. Also, included some logic to maintain a maximum size.
// Variables
var width;
var height;
var maxWidth = 940;
var maxHeight = 600;
var widthPer;
function setSize() {
// Setup width
width = window.innerWidth;
if (width > maxWidth) width = maxWidth;
// Setup height
widthPer = width / maxWidth;
height = widthPer * maxHeight;
}
var paper = Raphael(document.getElementById("infographic"), 940, 600);
paper.setViewBox(0, 0, 940, 600, true);
window.onresize = function(event) {
setSize();
paper.setSize(width,height);
redraw_element();
}