I want to have a label which should be displayed upside down. That means after creating the label I want to turn it around 90 degrees. That works but now the label is anywhere. I don't know HOW the label is rotated. Maybe one could help me. The code is the following:
let label = CreatorClass.createLabelWithFrame(CGRect(x: 10, y: 10, width: 150, height: 15), text: "aString", size: 12.0, bold: false, textAlignment: .Left, textColor: UIColor.whiteColor(), addToView: self)
label.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
CreatorClass creates a label and add it to a certain view (it adds to self because this code is called in a subclass of UIView). Actually it's self-explanatory I think.
you label rotate around its center, that means:
You label rotate around : x = 10 + 75 = 85
y = 10 + 7.5 = 17.5
This is also the center of the new position, what has a width of 15.0 and height of 150;
The new rect of your view, after the transfer is:
x = 85 - 7.5 = 77.5;
y = 17.5 - 75 = -57.5;
width = 15 , height = 150.
It could be out of the self bounds.
You might want to go back your label to its init position, only need to put it to init position:
label.frame = CGRect(x: 10, y: 10, width: 15, height: 150)
Related
I'm trying to setup a CARenderer to draw into a mtlTexture, but all my attempts to get this working in a playground don't draw anything.
The resulting image is solid red, the yellow layer doesn't seem to be rendered at all.
Here's the simplest version of what I've tried:
import QuartzCore
import Metal
let layerTest = CATextLayer()
layerTest.frame = .init(origin: .zero, size: .init(width: 1920, height: 1080))
layerTest.string = "TEST"
layerTest.foregroundColor = .black
layerTest.backgroundColor = CGColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1.0)
layerTest.position = CGPoint(x:0.0, y:0.0)
layerTest.anchorPoint = CGPoint(x:0.0, y:0.0)
layerTest.masksToBounds = true
let device = MTLCreateSystemDefaultDevice()!
let context = CIContext(mtlDevice: device)
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .rgba8Unorm, width: 1920, height: 1080, mipmapped: false)
textureDescriptor.usage = [.unknown]
textureDescriptor.storageMode = .private
let bytes = UnsafeMutablePointer<UInt8>.allocate(capacity: 1920 * 1080 * 4)
//fill the buffer with red
let pattern = UnsafeMutablePointer<UInt8>.allocate(capacity: 4)
(pattern + 0).initialize(to: 255)
(pattern + 1).initialize(to: 0)
(pattern + 2).initialize(to: 0)
(pattern + 3).initialize(to: 255)
memset_pattern4(bytes, pattern, 1920 * 1080 * 4)
let mtlBuffer = device.makeBuffer(bytes: bytes, length: 1920 * 1080 * 4)!
let mtlTexture = mtlBuffer.makeTexture(descriptor: textureDescriptor, offset: 0, bytesPerRow: 1920 * 4)!
let render = CARenderer(mtlTexture: mtlTexture)
render.bounds = layerTest.frame
render.layer = layerTest
render.setDestination(mtlTexture)
render.beginFrame(atTime: CACurrentMediaTime(), timeStamp: nil)
render.addUpdate(render.bounds)
render.render()
render.endFrame()
let ciImage = CIImage(mtlTexture: mtlTexture)!
let cgImage: CGImage = context.createCGImage(ciImage, from: ciImage.extent)! //<- this is just red frame
I submitted this to apple DTS and got a reply:
Setting the root layer of the CARenderer requires one implicit CATransaction to transfer ownership of the layer tree to the CARenderer’s context. CARenderer frame render methods will not work correctly until this ownership transfer is complete.
To complete the current transaction we call flush() and then commit() it:
render.layer = layerTest
CATransaction.flush()
CATransaction.commit()
Adding these two lines resolved the issue for me.
I would like to append a color bar to my image to indicate what value corresponds to which color.
Something similar to the calibration bar in ImageJ.
Thank you for your help
What you are looking for is the "Intensity bar".
Example script right from the F1 help documenation:
image img := RealImage("Test",4,512,512)
img = itheta
img.ShowImage()
imageDisplay disp = img.ImageGetImageDisplay(0)
number kSCALEBAR = 31
number kINTENSITYBAR = 33
component scalebar = NewComponent( kSCALEBAR, 450, 100, 480, 300 )
disp.ComponentAddChildAtEnd( scalebar )
component intbar = NewComponent( kINTENSITYBAR, 50, 400, 450, 490 )
disp.ComponentAddChildAtEnd( intbar )
It appears that, in SpriteKit, when I use a mask in a SKCropNode to hide some content, it fails to change the frame calculated by calculateAccumulatedFrame. I'm wondering if there's any way to calculate the visible frame.
A quick example:
import SpriteKit
let par = SKCropNode()
let bigShape = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 100, height: 100))
bigShape.fillColor = UIColor.redColor()
bigShape.strokeColor = UIColor.clearColor()
par.addChild(bigShape)
let smallShape = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 20, height: 20))
smallShape.fillColor = UIColor.greenColor()
smallShape.strokeColor = UIColor.clearColor()
par.maskNode = smallShape
par.calculateAccumulatedFrame() // returns (x=0, y=0, width=100, height=100)
I expected par.calculateAccumulatedFrame() to return (x=0, y=0, width=20, height=20) based on the crop node mask.
I thought maybe I could code the function myself as an extension that basically reimplements calculateAccumulatedFrame with support for checking for SKCropNodes and their masks, but it occurred to me that I would need to consider the alpha of that mask to determine if there's actual content that grows the frame. Sounds difficult.
Is there an easy way to calculate this?
I need to find the Line coordinates(x1,y1,x2,y2) after the object has been modified. (moved, scaled, rotated)
I thought to use the oCoords information and based on angle and flip information to decide which corners are the line ends, but it seems that it will not be too accurate…
Any help?
Example:
x1: 164,
y1: 295.78334045410156,
x2: 451,
y2: 162.78334045410156
x: 163, y: 161.78334045410156 - top left corner
x: 452, y: 161.78334045410156 - top right corner
x: 163, y: 296.78334045410156 - bottom left corner
x: 452, y: 296.78334045410156 - bottom right corner
When Fabric.js calculates oCoords - i.e. object's corners' coordinates - it takes into account the object's strokeWidth:
// fabric.Object.prototype
_getNonTransformedDimensions: function() {
var strokeWidth = this.strokeWidth,
w = this.width + strokeWidth,
h = this.height + strokeWidth;
return { x: w, y: h };
},
For most objects, stroke is kind of a border that outlines the outer edges, so it makes perfect sense to account for strokeWidth it when calculating corner coordinates.
In fabric.Line, though, stroke is used to draw the body of the line. There is no example in the question but I assume this is the reason behind discrepancies between the real end-point coordinates and those in oCoords.
So, if you really want to use oCoords to detect the coordinates of the end points, you'll have to adjust for strokeWidth / 2, e.g.
const realx1 = line.oCoords.tl.x + line.strokeWidth / 2
const realy1 = line.oCoords.tl.y + line.strokeWidth / 2
Keep in mind that fabric.Line's own _getNonTransformedDimensions() does adjust for strokeWidth, but only when the line's width or height equal 0:
// fabric.Line.prototype
_getNonTransformedDimensions: function() {
var dim = this.callSuper('_getNonTransformedDimensions');
if (this.strokeLineCap === 'butt') {
if (this.width === 0) {
dim.y -= this.strokeWidth;
}
if (this.height === 0) {
dim.x -= this.strokeWidth;
}
}
return dim;
},
According to this question
Raphael - event when mouse near element
i create a invisible rectangle around another rectangle ,
when the mouse is over that large rect, a circle will appear.
but because the large rect is on top of the small rect,
i can't process another event when mouse is over the small rect.
(if the small rect is on top , the point will disappear when i reach the small rect)
And i want also to have another event with the circle.
Is there any solution for this?
Hier is the code
Kind of mimicking the events of the larger rectangle with the smaller one:
var paper = new Raphael(0, 0, 500, 500);
createRect(100, 100, 100, 50);
function createRect(x, y, width, height) {
var boundrect = paper.rect(x - 30, y - 30, width + 60, height + 60).attr({
"fill": "pink",
"stroke": "none"
}).mouseover(function(event) {
topCtrl.show()
}).mouseout(function(event) {
topCtrl.hide()
})
,
rect = paper.rect(x, y, width, height).attr({
"fill": "white",
"stroke": "red"
}).mouseover(function(event) {
topCtrl.show();
topCtrl.attr({
"fill": "white"
})
}),
topCtrl = paper.circle(x + (width / 2), y, 5).attr({
"fill": "red"
});
}