问题
hello friends i need to add mirror image in right corner and bottom. i create the type of view with the help of this answer
how to create a view like this shape in swift?
but i am not able to add image in right corner and bottom
回答1:
Current approach is somewhat different from the previous one.
Previously i've drawn the right and bottom corner and resized the image such that, the appearance is asked in that question.
But in this question, that approach won't work anymore. First reason is that draw(in rect: CGRect)
does not provide mirroring functionality for image while drawing. iOS only provide mirroring functionality while drawing in UIImageView
. So to do the mirroring we need to setup 3 image view.
So the approach to achieve it is following
- Put one
UIImageView
in center. - Put one
UIImageView
in the right of the center another to the bottom. - Now calculate the right mirrored image and apply shear the right image view.
- Do the same for the bottom.
One problem still remain in the approach described above. For example we shear the right image view according to y axis. The shear operation works along with center. So the left side and right side both shears across the y axis. So we translate positive to the x axis so that all the shear applies to the right of UIImageView
. Thats why overlap the right and main image view to fill the gap between to, as following
rightImageView.leadingAnchor.constraint(equalTo: mainImageView.trailingAnchor, constant: -stripSize / 2),
Same goes for the bottom image view.
Code
lass ViewController: UIViewController {
let mainImageView: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.clipsToBounds = true
return view
}()
let rightImageView: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.clipsToBounds = true
return view
}()
let bottomImageView: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.clipsToBounds = true
return view
}()
let rightDarkView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.4)
return view
}()
let bottomDarkView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.5)
return view
}()
let mainImageSize = CGSize(width: 240, height: 240)
let stripSize = CGFloat(20)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupView()
setupMirroView()
}
func setupView() {
view.addSubview(mainImageView)
view.addSubview(rightImageView)
view.addSubview(bottomImageView)
view.addSubview(rightDarkView)
view.addSubview(bottomDarkView)
NSLayoutConstraint.activate([
mainImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
mainImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
mainImageView.widthAnchor.constraint(equalToConstant: mainImageSize.width),
mainImageView.heightAnchor.constraint(equalToConstant: mainImageSize.height),
rightImageView.leadingAnchor.constraint(equalTo: mainImageView.trailingAnchor, constant: -stripSize / 2),
rightImageView.topAnchor.constraint(equalTo: mainImageView.topAnchor),
rightImageView.bottomAnchor.constraint(equalTo: mainImageView.bottomAnchor),
rightImageView.widthAnchor.constraint(equalToConstant: stripSize),
rightDarkView.leadingAnchor.constraint(equalTo: rightImageView.leadingAnchor),
rightDarkView.topAnchor.constraint(equalTo: rightImageView.topAnchor),
rightDarkView.trailingAnchor.constraint(equalTo: rightImageView.trailingAnchor),
rightDarkView.bottomAnchor.constraint(equalTo: rightImageView.bottomAnchor),
bottomImageView.topAnchor.constraint(equalTo: mainImageView.bottomAnchor, constant: -stripSize / 2),
bottomImageView.leadingAnchor.constraint(equalTo: mainImageView.leadingAnchor),
bottomImageView.trailingAnchor.constraint(equalTo: mainImageView.trailingAnchor),
bottomImageView.heightAnchor.constraint(equalToConstant: stripSize),
bottomDarkView.leadingAnchor.constraint(equalTo: bottomImageView.leadingAnchor),
bottomDarkView.topAnchor.constraint(equalTo: bottomImageView.topAnchor),
bottomDarkView.trailingAnchor.constraint(equalTo: bottomImageView.trailingAnchor),
bottomDarkView.bottomAnchor.constraint(equalTo: bottomImageView.bottomAnchor)
])
}
func setupMirroView() {
let image = UIImage(named: "image")
mainImageView.image = image
// prepare the image for the right image view
let rightImage = image?.cropped(to: CGSize(width: stripSize, height: mainImageSize.height),
drawInto: CGRect(x: stripSize - mainImageSize.width, y: 0, width: mainImageSize.width, height: mainImageSize.height))
let rightImageMirrored = UIImage(cgImage: rightImage!.cgImage!, scale: 1.0, orientation: .upMirrored)
rightImageView.image = rightImageMirrored
var rightTransform = CGAffineTransform.identity
rightTransform = rightTransform.translatedBy(x: stripSize / 2, y: 0)
rightTransform = rightTransform.concatenating(CGAffineTransform(a: 1.0, b: 1.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0))
rightImageView.transform = rightTransform
rightDarkView.transform = rightTransform
// prepare the image for the left image view
let downImage = image?.cropped(to: CGSize(width: mainImageSize.width, height: stripSize),
drawInto: CGRect(x: 0, y: stripSize - mainImageSize.height, width: mainImageSize.width, height: mainImageSize.height))
let downImageMirroed = UIImage(cgImage: downImage!.cgImage!, scale: 1.0, orientation: .downMirrored)
bottomImageView.image = downImageMirroed
var downTransform = CGAffineTransform.identity
downTransform = downTransform.translatedBy(x: 0, y: stripSize / 2)
downTransform = downTransform.concatenating(__CGAffineTransformMake(1.0, 0.0, 1.0, 1.0, 0.0, 0.0))
bottomImageView.transform = downTransform
bottomDarkView.transform = downTransform
}
}
extension UIImage {
func cropped(to size: CGSize, drawInto: CGRect) -> UIImage {
UIGraphicsBeginImageContext(size)
self.draw(in: drawInto)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
output
回答2:
One approach is to use 3 image views - the "main" imageView plus a right-side imageView and a bottom imageView.
- Scale your image to fit the main view + a small amount for the right-side and bottom.
- Set the main imageView's
.contentMode = .topLeft
to clip the right and bottom. - Set the right-side imageView to
.topRight
to clip the left and bottom. - Set the bottom imageView to
.leftBottom
to clip the top and right. - Darken the image for the right-side and bottom views (to make it look a little "shadowed"
Then, apply CGAffineTransform
to skew the right-side and bottom views.
Using this image (3:2 ratio):
and this code (everything is done via code - no IBOutlets needed):
import UIKit
import CoreImage
class ImageWorkViewController: UIViewController {
let mainImageView: UIImageView = {
let v = UIImageView()
v.translatesAutoresizingMaskIntoConstraints = false
v.clipsToBounds = true
v.contentMode = .topLeft
return v
}()
let rightImageView: UIImageView = {
let v = UIImageView()
v.translatesAutoresizingMaskIntoConstraints = false
v.clipsToBounds = true
v.contentMode = .topRight
return v
}()
let bottomImageView: UIImageView = {
let v = UIImageView()
v.translatesAutoresizingMaskIntoConstraints = false
v.clipsToBounds = true
v.contentMode = .bottomLeft
return v
}()
// this will be the width of the skewed right-side and height of the skewed bottom
let vDepth:CGFloat = 10.0
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(mainImageView)
view.addSubview(rightImageView)
view.addSubview(bottomImageView)
NSLayoutConstraint.activate([
// constrain main image view 40-pts from each side
mainImageView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 40.0),
mainImageView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -40.0),
// centered vertically
mainImageView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0.0),
// use 3:2 ratio
mainImageView.heightAnchor.constraint(equalTo: mainImageView.widthAnchor, multiplier: 2.0 / 3.0),
// constrain right image view to main image view
// right-edge
// top + 1/2 of vDepth
// equal height
// width = vDepth
rightImageView.leadingAnchor.constraint(equalTo: mainImageView.trailingAnchor, constant: 0.0),
rightImageView.topAnchor.constraint(equalTo: mainImageView.topAnchor, constant: vDepth / 2.0),
rightImageView.heightAnchor.constraint(equalTo: mainImageView.heightAnchor, multiplier: 1.0),
rightImageView.widthAnchor.constraint(equalToConstant: vDepth),
// constrain bottom image view to main image view
// left-edge + 1/2 of vDepth
// bottom
// equal width
// height = vDepth
bottomImageView.leadingAnchor.constraint(equalTo: mainImageView.leadingAnchor, constant: vDepth / 2.0),
bottomImageView.topAnchor.constraint(equalTo: mainImageView.bottomAnchor, constant: 0.0),
bottomImageView.widthAnchor.constraint(equalTo: mainImageView.widthAnchor, multiplier: 1.0),
bottomImageView.heightAnchor.constraint(equalToConstant: vDepth),
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// run this on viewDidLayoutSubviews() so we have valid frame sizes
if let sourceImg = UIImage(named: "goal3x2") {
// resize image to width and height of main image view, plus vDepth value
let mainImg = resizeImage(image: sourceImg, newSize: CGSize(width: mainImageView.frame.width + vDepth, height: mainImageView.frame.height + vDepth))
// set the main image
mainImageView.image = mainImg
// we're going to darken the right-side and bottom images a little bit
if let currentFilter = CIFilter(name: "CIColorControls") {
let context = CIContext(options: nil)
let beginImage = CIImage(image: mainImg)
currentFilter.setValue(beginImage, forKey: kCIInputImageKey)
// darken right-image by 40%
currentFilter.setValue(-0.4, forKey: kCIInputBrightnessKey)
if let output = currentFilter.outputImage {
if let cgimg = context.createCGImage(output, from: output.extent) {
let processedImage = UIImage(cgImage: cgimg)
// set the right-side image
rightImageView.image = processedImage
}
}
// darken bottom-image by 50%
currentFilter.setValue(-0.5, forKey: kCIInputBrightnessKey)
if let output = currentFilter.outputImage {
if let cgimg = context.createCGImage(output, from: output.extent) {
let processedImage = UIImage(cgImage: cgimg)
// set the bottom image
bottomImageView.image = processedImage
}
}
}
}
// skew the right-side and bottom image views
let skewVal: CGFloat = 1.0
// bottom part transform
let bottomTransform = CGAffineTransform(a: 1.0, b: 0.0, c: skewVal, d: 1.0, tx: 0.0, ty: 0.0)
bottomImageView.transform = bottomTransform
// right part transform
let rightTransform = CGAffineTransform(a: 1.0, b: skewVal, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0)
rightImageView.transform = rightTransform
}
func resizeImage(image: UIImage, newSize: CGSize) -> UIImage {
let newWidth = newSize.width
let newHeight = newSize.height
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image.draw(in: CGRect(x: 0.0, y: 0.0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
This is the result:
There is a variable named vDepth
that controls the width of the right-side and the height of the bottom imageViews.
Note: this is just example code... Hopefully this will get you on your way.
来源:https://stackoverflow.com/questions/57786763/how-add-mirror-image-to-2d-box-corners