147 lines
5.5 KiB
Swift
147 lines
5.5 KiB
Swift
//
|
||
// MPPositive_PlayerSilder.swift
|
||
// MusicPlayer
|
||
//
|
||
// Created by Mr.Zhou on 2024/5/8.
|
||
//
|
||
|
||
import UIKit
|
||
///b面播放器进度条(展示缓存效果,聚焦时进行尺寸变化)
|
||
class MPPositive_PlayerSilder: UISlider {
|
||
/// 触控扩展边距
|
||
var hitTestEdgeInsets: UIEdgeInsets = UIEdgeInsets(top: -20, left: -20, bottom: -20, right: -20)
|
||
/// 原始的Slider大小
|
||
var originalFrame: CGRect?
|
||
//滑块图片
|
||
var thumbImage:UIImage = .init(named: "Player_Slider'logo")!
|
||
//滑轨槽高度
|
||
var trackHeight: CGFloat = 6*width
|
||
//进度渐变色
|
||
var minTrackColors: [UIColor]!
|
||
//槽位渐变色
|
||
var maxTrackColors:[UIColor]!
|
||
//进度渐变色定位列表(与渐变色数量保持一致)
|
||
var minTrackLocations:[CGFloat]!
|
||
//槽位渐变色定位列表(与渐变色数量保持一致)
|
||
var maxTrackLocations:[CGFloat]!
|
||
|
||
//初始化
|
||
override init(frame:CGRect) {
|
||
super.init(frame: frame)
|
||
setUpLayout()
|
||
}
|
||
override func awakeFromNib() {
|
||
super.awakeFromNib()
|
||
print("调整Slider大小")
|
||
originalFrame = self.frame
|
||
}
|
||
|
||
required init?(coder: NSCoder) {
|
||
super.init(coder: coder)
|
||
}
|
||
private func setUpLayout() {
|
||
layer.masksToBounds = false
|
||
setThumbImage(thumbImage, for: .normal)
|
||
//设置进度图片
|
||
let minTrackImg = makeTrackImage(rect: frame, colors: [UIColor.white], locations: [0,1])
|
||
setMinimumTrackImage(minTrackImg, for: .normal)
|
||
// 设置槽位
|
||
let maxTrackImg = makeTrackImage(rect: frame, colors: [UIColor(hex: "#FFFFFF", alpha: 0.1)], locations: [0,1])
|
||
setMaximumTrackImage(maxTrackImg, for: .normal)
|
||
}
|
||
|
||
/// 滑块设置
|
||
/// - Parameters:
|
||
/// - rect: 滑块大小
|
||
/// - color: 滑块颜色
|
||
/// - Returns: 返回的滑块图片
|
||
private func makeThumbImage(rect: CGRect, color:UIColor) -> UIImage {
|
||
let lineWidth: CGFloat = 2
|
||
//开始绘制
|
||
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
|
||
//填充内部颜色
|
||
color.setFill()
|
||
//曲线路径
|
||
let oval = UIBezierPath(ovalIn: rect)
|
||
//填充路径
|
||
oval.fill()
|
||
//设置路径颜色为白色
|
||
UIColor.white.setStroke()
|
||
//路径宽度
|
||
oval.lineWidth = lineWidth
|
||
oval.stroke()
|
||
//转为图片
|
||
let thumbImg = UIGraphicsGetImageFromCurrentImageContext()!
|
||
//转化结束
|
||
UIGraphicsEndImageContext()
|
||
return thumbImg
|
||
}
|
||
|
||
|
||
/// 生成滑轨图片
|
||
/// - Parameters:
|
||
/// - rect: 滑轨大小
|
||
/// - colors: 颜色列表
|
||
/// - locations: 位置分布列表
|
||
/// - Returns: 生成的图片
|
||
private func makeTrackImage(rect: CGRect, colors:[UIColor], locations:[CGFloat]) -> UIImage {
|
||
let rect = CGRect(x: rect.minX, y: rect.minY, width: rect.width, height: self.trackHeight)
|
||
//开始绘制
|
||
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
|
||
let ctx = UIGraphicsGetCurrentContext()!
|
||
// 创建并设置路径
|
||
let cornerRadius: CGFloat = rect.height * 0.5
|
||
let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
|
||
// 添加路径到图形上下文
|
||
ctx.addPath(path)
|
||
ctx.clip()
|
||
// 使用rgb颜色空间
|
||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||
//获取cgcolors
|
||
var cgColors:[CGColor] = []
|
||
colors.forEach { item in
|
||
cgColors.append(item.cgColor)
|
||
}
|
||
// 定义渐变色
|
||
let gradient:CGGradient = CGGradient(colorsSpace: colorSpace, colors: cgColors as CFArray, locations: locations)!
|
||
// 渐变开始位置
|
||
let start = CGPoint(x: self.bounds.minX, y: self.bounds.minY)
|
||
// 渐变结束位置
|
||
let end = CGPoint(x: self.bounds.maxX, y: self.bounds.minY)
|
||
// 绘制渐变
|
||
ctx.drawLinearGradient(gradient, start: start, end: end, options: .drawsBeforeStartLocation)
|
||
//转为图片
|
||
let trackImg = UIGraphicsGetImageFromCurrentImageContext()!
|
||
UIGraphicsEndImageContext()
|
||
return trackImg
|
||
}
|
||
// 重写【thumb】显示区域 方法
|
||
override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
|
||
let rect = super.thumbRect(forBounds: bounds, trackRect: rect, value: value)
|
||
// 设置thumb投影效果
|
||
// (这样设置的投影效果,如果调用setValue(_:animated:)的时候,animated参数为true,会有阴影和thumb不同步的问题,目前还不知到怎么解决)
|
||
self.layer.shadowColor = UIColor.black.cgColor
|
||
self.layer.shadowOffset = CGSize(width: 0, height: 0)
|
||
self.layer.shadowOpacity = 0.15
|
||
self.layer.shadowRadius = 3
|
||
self.layer.shadowPath = UIBezierPath(cgPath: CGPath(ellipseIn: rect.insetBy(dx: 3, dy: 3), transform: nil)).cgPath
|
||
return rect
|
||
}
|
||
// 重写【track】显示区域 方法
|
||
override func trackRect(forBounds bounds: CGRect) -> CGRect {
|
||
return CGRect(x: 0, y: 0, width: bounds.width, height: self.trackHeight)
|
||
}
|
||
//MARK: - 交互代码
|
||
//当用户点击时
|
||
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||
//对Slider添加一个边距范围
|
||
let largerFrame: CGRect = self.bounds.inset(by: hitTestEdgeInsets)
|
||
//检索当前点击点是否在边距范围内
|
||
let isInside = largerFrame.contains(point)
|
||
|
||
return true
|
||
}
|
||
//当用户焦点汇聚到slider
|
||
|
||
}
|