SwiftUISwiftUI

SwiftUI学习(6)-Image

2020-10-12  本文已影响0人  摇滚马农

基本使用

自动大小

Image通过imageName初始化,如果不设置图片大小,会自动读取图片大小

Image("cover")

根据2x,3x算出来pt

resizable,重新设置大小

Image必须通过resizable方法才能调整大小,否则设置frame没有作用
resizable有两个参数可以调整capInsets和resizingMode
capInsets表示内间距
resizingMode表示渲染模式
ResizingMode是一个枚举类型有两个取值

public enum ResizingMode {
    case tile //瓦片方式
    case stretch //拉抻方式
}

具体代码如

Image("cover")
     .resizable(capInsets: EdgeInsets(), resizingMode: .tile)
     .frame(height:40)

两种方式效果


瓦片方式 拉抻方式

interpolation,插值

在渲染大小大于图片大小的时候,可以通过interpolation方法进行插值方式的设置
Interpolation是个枚举,具体取值如下:

public enum Interpolation {
        case none //无插值
        case low //低插值
        case medium
        case high
}

具体代码如

Image("cover")
     .resizable()
     .interpolation(.none)
     .frame(width: 150, height: 150, alignment: .center)

具体表现如下图


无插值 高插值

antialiased 抗锯齿

antialiased方法需要传一个bool值确定是否打开抗锯齿。
锯齿何来?
当位图进行旋转和缩放就会产生锯齿。以旋转举例,图像都是数字化非连续的,由像素组成,每个点都是最小单位。当旋转到非水平和垂直的方向时候,它仍然需要落在某一行的某一个格子,而这个格子并不是它应该的位置,所以要么靠前,要么靠后,就出现了锯齿。除非以更小的点作为基本单位,直到突破肉眼分辨率的极限,但是这些图像放大后仍然有锯齿,这是由于位图的显示原理导致的。
而抗锯齿技术的原理就是对于边界通过渐变色的方式,弱化靠前,靠后的影响,视觉上弱化锯齿效果。
打开抗锯齿需要消耗一定的性能,在旋转的时候,我们可以明显的看到抗锯齿的效果

具体代码如

Image("cover2")
       .resizable()
       .antialiased(true)
       .transformEffect(.init(rotationAngle: CGFloat(Double.pi/8)))
       .frame(width: 80, height: 80, alignment: .center)

打开和关闭的效果分别如图


打开抗锯齿 关闭抗锯齿

通过系统提供的图片初始化

iOS系统提供了很多图片给开发者用,这些图片都是系统内置的,用这些图片不需要倒入到项目里面,如:

Image(systemName: "gear")
       .resizable()
       .frame(width: 80, height: 80, alignment: .center)

如图


7.png

我们如何知道系统有哪些图可用呢?
苹果官方提供了一个mac版的app,里面有所有的图片(其实主要是icon)和对应的名字,
下载地址如下:
https://developer.apple.com/sf-symbols/
具体的软件截图如下:

1602493163271.jpg

clipShape,裁剪

这个方法并不是Image独有的,只要是View就有这个方法,图片做clipShape比较普遍,就在这里讲一下。
该方法有两个参数:
shape 实现Shape协议的对象
style FillStyle对象

先说下Shape是一个协议,Shape也遵循View协议,所以也是一个View,在(2)那篇文章介绍过,有Capsule,Circle,ContainerRelativeShape,Ellipse,OffsetShape,Path,Rectangle,RotatedShape,RoundedRectangle(圆角矩形),ScaledShape,TransformedShape。也就是说图片会按照Shape的形状进行裁剪。

再说下FillStyle,FillStype是一个struct,具体定义如下:

public struct FillStyle : Equatable {
    public var isEOFilled: Bool //默认false
    public var isAntialiased: Bool //默认false
}

它有两个属性,isAntialiased不难理解就是上面介绍的是否支持抗锯齿。
isEOFilled就比较难以理解了。
只要是路径填充,都有两种规则,nonzero和even-odd。
true表示even-odd。false表示nonzero。
那问题来了,nonzero和even-odd又是啥?
首先我们要知道图形(Shape)由stroke(笔触)和fill(填充)组成的。而Shape只是提供了store(笔触)或者说path(路径),但是并没有提供填充的信息。

而nonzero和even-odd正是填充信息的描述。

nonzero表示非0填充。其实这个是比较好理解的。
具体来讲就是一个坐标点是否在图形的内部,如果在图形内部我就填充,否则我就不填充。这就完全跟我们理解上是一致的。只有在闭合路径的内部就填充,外面就不填充。

even-odd比较难以理解。even-odd表示奇偶填充。
图形由一条条路径拼接而成。even-odd的含义表示任意一点往任意方向延伸出一条射线,跟图形中每一条路径相交计数为1,如果相交个数为奇数就填充,相交个数为偶数就不填充,如下图。


10.png 11.png 12.png

所以如上图A不填充,B不填充,C填充。
同理我们可知,对于这个图片如果以nonzero方式进行填充,结果则为A填充,B不填充,C填充。

填充方式 A B C
nonzero 填充 不填充 填充
even-odd 不填充 不填充 填充

具体的代码如下:

Image("cover2")
       .resizable()
       .frame(width: 80, height: 80, alignment: .center)
       .clipShape(Circle())

效果如图:


1602496269769.jpg

mask遮罩

与clipShape极其类似,mask是遮罩,它需要传一个遵循View协议的对象。

方法 参数
clipShape 必须是Shape,支持FillStyle填充
mask 任意View,不支持FillStyle填充

代码如下:

Image("cover2")
       .resizable()
       .frame(width: 80, height: 80, alignment: .center)
       .mask(Circle())

展示效果与clipShape是相同的

cornerRadius

这个方法也不是Image独有的它也是View的方法,比UIKit它直接可以设置圆角不同通过layer层,方便很多
代码如下:

Image("cover2")
       .resizable()
       .frame(width: 80, height: 80, alignment: .center)
       .cornerRadius(15)

效果如图:


1602496460320.jpg

shadow

shadow也是View的方法,它表示阴影。可以传Color,radius(size)和x,y(position)
代码如下:

Image("cover")
       .shadow(color:.gray,radius: 3)

效果如图:


1602496740942.jpg

overlay

这个也是View的方法。overlay表示覆盖。
它有两个参数:
overlay:任意遵循View类型的对象
alignment:对齐方式

Alignment是一个struct有两个属性
一个horizontal一个vertical, 分别是两个struct HorizontalAlignment,VerticalAlignment
Alignment有很多全局成员,例如:

public static let center: Alignment
public static let leading: Alignment
public static let trailing: Alignment
public static let top: Alignment
public static let bottom: Alignment
public static let topLeading: Alignment
public static let topTrailing: Alignment
public static let bottomLeading: Alignment
public static let bottomTrailing: Alignment

这些对象的名字已经很明确的表示了它的含义。

overlay的使用方式如下:

Image("cover")
       .overlay(Color.blue.clipShape(Circle()))

效果如下:


1602498031391.jpg

代码Demo

Demo

struct ImageViewTestView: View {
    @State private var animationAmount: CGFloat = 1
    @State private var large = false
    
    var body: some View {
        VStack(alignment: .center, spacing: 10, content: {
            Image("cover")
            
            Image("cover")
                .resizable(capInsets: EdgeInsets(), resizingMode: .tile)
                .frame(height:40)
            
            Image("cover")
                .resizable(capInsets: EdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 0), resizingMode: .stretch)
                .frame(height:40)
            
            Image("cover")
                .resizable()
                .interpolation(.none)
                .frame(width: 150, height: 150, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
            
            Image("cover")
                .resizable()
                .interpolation(.high)
                .frame(width: 150, height: 150, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
        })
        
        VStack {
            Image("cover2")
                .resizable()
                .antialiased(true)
                .transformEffect(.init(rotationAngle: CGFloat(Double.pi/8)))
                .frame(width: 80, height: 80, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
            
            Spacer()
            
            Image("cover2")
                .resizable()
                .antialiased(false)
                .transformEffect(.init(rotationAngle: CGFloat(Double.pi/8)))
                .frame(width: 80, height: 80, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
            
            Spacer()
            
            Image(systemName: "gear")
                .resizable()
                .frame(width: 80, height: 80, alignment: .center)
            
            Image("cover2")
                .resizable()
                .frame(width: 80, height: 80, alignment: .center)
                .cornerRadius(15)
            
            Image("cover2")
                .resizable()
                .frame(width: 80, height: 80, alignment: .center)
                .clipShape(Circle())
        }
        
        VStack {
            Image("cover2")
                .resizable()
                .frame(width: 80, height: 80, alignment: .center)
                .mask(Capsule()
                        .frame(width: 80, height: 60, alignment: .center))

            Image("cover")
                .shadow(color:.gray,radius: 3)
            
            Image("cover")
                .overlay(Color.blue.clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/))
        }
    }
}

struct ImageViewTestView_Previews: PreviewProvider {
    static var previews: some View {
        ImageViewTestView()
    }
}

效果图

1602498137038.jpg 1602498151063.jpg 1602498163466.jpg

苹果官方的一个例子

代码

struct ContentView: View {
    
    var body: some View {
        Image("cover")
            .resizable()
            .frame(width: 80, height: 80, alignment: .center)
            .clipShape(Circle())
            .overlay(Circle().stroke(Color.white, lineWidth: 4),alignment: .bottom)
            .shadow(radius: 10)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

效果

1602498306415.jpg
上一篇 下一篇

猜你喜欢

热点阅读