在Swift中建立个人资料图片的圆形图片集:如何将最后一张照片隐藏在第一张照片下?

佐拉尔

我试图建立一个UIView具有几个UIImageView布置成圆形S,重叠的方式(参见下图)。假设我们有N张图片。绘制第一个N-1很容易,只需使用sin / cos函数将UIImageViews的中心围绕一个圆排列即可问题在于最后一张图像似乎具有两个z-index值!我知道这是可能的,因为kik messenger具有相似的个人资料照片。

到目前为止,我想到的最好的主意是拍摄最后一张图像,将其拆分为“上半部分”和“下半部分”,并为每个图像分配不同的z值。当图像是最左边的图像时,这似乎可行,但是如果图像是最上面的图像,会发生什么呢?在这种情况下,我需要左右分开而不是上下分开。

由于这个问题,它可能不是顶部,左侧或右侧,而是更像是从整个面心从中心穿过某个假想轴的某个分裂UIImageView我该怎么办?

在此处输入图片说明

下面的代码将在圆圈中布局UIImageView

您需要导入SDWebImage并提供一些图像URL才能运行下面的代码。

import Foundation
import UIKit
import SDWebImage

class EventDetailsFacepileView: UIView {
    static let dimension: CGFloat = 66.0
    static let radius: CGFloat = dimension / 1.68
    
    private var profilePicViews: [UIImageView] = []
    var profilePicURLs: [URL] = [] {
        didSet {
            updateView()
        }
    }
    
    func updateView() {
        self.profilePicViews = profilePicURLs.map({ (profilePic) -> UIImageView in
            let imageView = UIImageView()
            imageView.sd_setImage(with: profilePic)
            imageView.roundImage(imageDimension: EventDetailsFacepileView.dimension, showsBorder: true)
            imageView.sd_imageTransition = .fade
            return imageView
        })
        self.profilePicViews.forEach { (imageView) in
            self.addSubview(imageView)
        }
        self.setNeedsLayout()
        self.layer.borderColor = UIColor.green.cgColor
        self.layer.borderWidth = 2
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        let xOffset: CGFloat = 0
        let yOffset: CGFloat = 0
        
        let center = CGPoint(x: self.bounds.size.width / 2, y: self.bounds.size.height / 2)
        let radius: CGFloat =  EventDetailsFacepileView.radius
        let angleStep: CGFloat = 2 * CGFloat(Double.pi) / CGFloat(profilePicViews.count)
        var count = 0
        for profilePicView in profilePicViews {
            let xPos = center.x + CGFloat(cosf(Float(angleStep) * Float(count))) * (radius - xOffset)
            let yPos = center.y + CGFloat(sinf(Float(angleStep) * Float(count))) * (radius - yOffset)
            profilePicView.frame = CGRect(origin: CGPoint(x: xPos, y: yPos),
                                          size: CGSize(width: EventDetailsFacepileView.dimension, height: EventDetailsFacepileView.dimension))
            count += 1
        }
    }
    
    override func sizeThatFits(_ size: CGSize) -> CGSize {
        let requiredSize = EventDetailsFacepileView.dimension + EventDetailsFacepileView.radius
        return CGSize(width: requiredSize,
                      height: requiredSize)
    }
}

唐马格

我认为尝试分割图像以超过/低于z索引不会取得太大的成功。

一种方法是使用遮罩以使图像视图看起来重叠。

总体思路是:

  • 子类 UIImageView
  • 在layoutSubviews()中
  • 将cornerRadius应用于图层以使图像变圆
  • 从“重叠视图”获得矩形
  • 将该矩形转换为本地坐标
  • 将矩形扩展到所需的“轮廓”宽度
  • 从那个矩形得到一条椭圆形的路径
  • 结合自我之路
  • 将其用作遮罩层

这是一个例子。

我不完全确定您的尺寸计算在做什么……试图按EventDetailsFacepileView原样在视图的右下角给我小图像?

因此,我EventDetailsFacepileView通过以下几种方式修改了您

  • 使用名为“ pro1”到“ pro5”的本地图片(您应该可以用替换SDWebImage
  • 使用自动布局约束而不是显式框架
  • 使用MyOverlapImageView类来处理遮罩

代码-无@IBOutlet连接,因此只需将空白视图控制器设置为OverlapTestViewController

class OverlapTestViewController: UIViewController {
    
    let facePileView = MyFacePileView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        facePileView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(facePileView)
        
        facePileView.dimension = 120
        let sz = facePileView.sizeThatFits(.zero)
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            facePileView.widthAnchor.constraint(equalToConstant: sz.width),
            facePileView.heightAnchor.constraint(equalTo: facePileView.widthAnchor),
            facePileView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            facePileView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
        ])
        
        facePileView.profilePicNames = [
            "pro1", "pro2", "pro3", "pro4", "pro5"
        ]
        
    }
    
}

class MyFacePileView: UIView {
    var dimension: CGFloat = 66.0
    lazy var radius: CGFloat = dimension / 1.68
    
    private var profilePicViews: [MyOverlapImageView] = []
    
    var profilePicNames: [String] = [] {
        didSet {
            updateView()
        }
    }
    
    func updateView() {
        self.profilePicViews = profilePicNames.map({ (profilePic) -> MyOverlapImageView in
            let imageView = MyOverlapImageView()
            if let img = UIImage(named: profilePic) {
                imageView.image = img
            }
            return imageView
        })
        
        // add MyOverlapImageViews to self
        //  and set width / height constraints
        self.profilePicViews.forEach { (imageView) in
            self.addSubview(imageView)
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.widthAnchor.constraint(equalToConstant: dimension).isActive = true
            imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor).isActive = true
        }
        
        // start at "12 o'clock"
        var curAngle: CGFloat = .pi * 1.5
        // angle increment
        let incAngle: CGFloat = ( 360.0 / CGFloat(self.profilePicViews.count) ) * .pi / 180.0

        // calculate position for each image view
        //  set center constraints
        self.profilePicViews.forEach { imgView in
            let xPos = cos(curAngle) * radius
            let yPos = sin(curAngle) * radius
            imgView.centerXAnchor.constraint(equalTo: centerXAnchor, constant: xPos).isActive = true
            imgView.centerYAnchor.constraint(equalTo: centerYAnchor, constant: yPos).isActive = true
            curAngle += incAngle
        }
        
        // set "overlapView" property for each image view
        let n = self.profilePicViews.count
        for i in (1..<n).reversed() {
            self.profilePicViews[i].overlapView = self.profilePicViews[i-1]
        }
        self.profilePicViews[0].overlapView = self.profilePicViews[n - 1]

        self.layer.borderColor = UIColor.green.cgColor
        self.layer.borderWidth = 2
        
    }
    
    override func sizeThatFits(_ size: CGSize) -> CGSize {
        let requiredSize = dimension * 2.0 + radius / 2.0
        return CGSize(width: requiredSize,
                      height: requiredSize)
    }

}

class MyOverlapImageView: UIImageView {
    
    // reference to the view that is overlapping me
    weak var overlapView: MyOverlapImageView?
    
    // width of "outline"
    var outlineWidth: CGFloat = 6
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // make image round
        layer.cornerRadius = bounds.size.width * 0.5
        layer.masksToBounds = true

        let mask = CAShapeLayer()
        
        if let v = overlapView {
            // get bounds from overlapView
            //  converted to self
            //  inset by outlineWidth (negative numbers will make it grow)
            let maskRect = v.convert(v.bounds, to: self).insetBy(dx: -outlineWidth, dy: -outlineWidth)
            // oval path from mask rect
            let path = UIBezierPath(ovalIn: maskRect)
            // path from self bounds
            let clipPath = UIBezierPath(rect: bounds)
            // append paths
            clipPath.append(path)
            mask.path = clipPath.cgPath
            mask.fillRule = .evenOdd
            // apply mask
            layer.mask = mask
        }
    }
    
}

结果:

在此处输入图片说明

(我通过搜索google来抓取随机图像sample profile pictures

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

拍摄的第一张照片与第二张照片叠加在一起,或者在第二张照片等之后消失

在具有AlbumIds的照片阵列中查找每个相册中的第一张照片

如何将一张照片放在其他两张照片的顶部中央?

jQuery幻灯片-上一张照片不会循环到带有动画的第一张照片

JavaScript幻灯片卡在第一张照片上

CSS:如何“筹集”此页面中的最后一张照片?

如何隐藏第一张图片的左箭头和最后一张图片的右箭头

Javascript代码将最后一张图片移动到多张图片之间的第一张图片

仅获取包含至少一张照片的PHAssetCollections

UiImagePickerController-多于一张照片

图库下一张照片脚本

滑动到下一张照片

在Colorbox中单击当前照片的左半部分即可显示上一张照片

我有2个盒子和一张照片。用户可以在2个框之间拖动图片。我如何知道图片从哪个框拖动?

拍摄一张照片并显示之前的一张 - VB - OpenCV

删除最后一张照片时,UIPageViewController 显示动画方向错误

如果上传了第二张图片,则第一张图片将被删除,第二张图片将取代此第一张图片,如何在本机中实现

在导航中成为第一张图片

从提要内容中删除第一张图片

我如何获得用户的上一张照片?

如何获取Facebook中一张照片的份额计数?

PC /电话如何识别一张照片的人?

防止在UIImagePickerController中两次选择同一张照片

动态显示相同项目的照片,如果只有一张照片,则隐藏轮播

Firebase ML Kit可以用于检测一张照片包含存在于另一张照片中的物体的可能性吗?

离开图片后,如何重置html图片库以第一张图片开头?

模态仅显示第一张图片(我应如何将代码从id更改为class?)

将一张图片放在 ngFor 列表 Angular 中的另一张图片下

如何将一张图片放在另一张图片上?