Day_Count_Memory_Days/anniversary_Project/Tool/MLSliderRulerScrollView.swift
2024-07-15 11:52:15 +08:00

159 lines
5.9 KiB
Swift

//
// MLSliderRuler.swift
// MLSilderRulerView
//
// Created by Macro on 2018/1/25.
// Copyright © 2018 CodeMarco. All rights reserved.
//
import UIKit
let DISTANCELEFTANDRIGHT: CGFloat = 8.0 //
let DISTANCEVALUE: CGFloat = 8.0 // 8
let DISTANCETOPANDBOTTOM: CGFloat = 5.0 //
class MLSliderRulerScrollView: UIScrollView {
var maxValue: CGFloat = 2000
var minValue: CGFloat = 0
var rulerAverage: CGFloat = 1
var rulerCount: Int {
return Int(maxValue - minValue)
}
var isShowShortSymbol = true
var isSmallModel: Bool = true
var binary: Int = 10
var ruleFont = UIFont.systemFont(ofSize: 12)
var longSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
didSet {
longSymbol.strokeColor = longSymbolColor.cgColor
}
}
var middleSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
didSet {
middleSymbol.strokeColor = middleSymbolColor.cgColor
}
}
var shortSymbolColor = UIColor.hexSting(color: "#B6BCC7", alpha: 1) {
didSet {
shortSymbol.strokeColor = shortSymbolColor.cgColor
}
}
fileprivate lazy var longSymbol: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.strokeColor = longSymbolColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 3
shapeLayer.lineCap = .round
return shapeLayer
}()
fileprivate lazy var middleSymbol: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.strokeColor = middleSymbolColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 3
shapeLayer.lineCap = .round
return shapeLayer
}()
fileprivate lazy var shortSymbol: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.strokeColor = shortSymbolColor.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 3
shapeLayer.lineCap = .round
return shapeLayer
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupSubviews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupSubviews() {
layer.addSublayer(shortSymbol)
layer.addSublayer(middleSymbol)
layer.addSublayer(longSymbol)
backgroundColor = UIColor.white
}
func drawRuler() {
layer.sublayers?.forEach { (sublayer) in
if sublayer.isKind(of: CATextLayer.self) {
sublayer.removeFromSuperlayer()
}
}
let longPathRef = CGMutablePath()
let middlePathRef = CGMutablePath()
let shortPathRef = CGMutablePath()
for idx in 0 ... rulerCount {
let i = CGFloat(idx)
let rule = CATextLayer()
rule.foregroundColor = UIColor.lightGray.cgColor
rule.font = ruleFont
rule.fontSize = ruleFont.pointSize
rule.contentsScale = UIScreen.main.scale
rule.string = String(format: "%.0f", (i + minValue) * rulerAverage)
let textSize = (rule.string as! NSString).size(withAttributes: [NSAttributedString.Key.font: ruleFont])
rule.bounds = CGRect(origin: CGPoint.zero, size: textSize)
let xPos = DISTANCELEFTANDRIGHT + DISTANCEVALUE * i
if idx % Int(binary) == 0 {
longPathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 5))
longPathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
rule.position = CGPoint(x: xPos, y: 5 + textSize.height / 2)
layer.addSublayer(rule)
} else if idx % Int(binary / 2) == 0 {
middlePathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 10))
middlePathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
} else if isShowShortSymbol {
shortPathRef.move(to: CGPoint(x: xPos, y: DISTANCETOPANDBOTTOM + textSize.height + 15))
shortPathRef.addLine(to: CGPoint(x: xPos, y: bounds.height - DISTANCETOPANDBOTTOM))
}
}
longSymbol.path = longPathRef
let longSymbolFrame = longSymbol.path?.boundingBoxOfPath ?? .zero
let longSymbolCenterY = longSymbolFrame.midY
middleSymbol.path = middlePathRef
shortSymbol.path = shortPathRef
middleSymbol.position.y += (longSymbolCenterY - (middlePathRef.boundingBoxOfPath.midY))
shortSymbol.position.y += (longSymbolCenterY - (shortPathRef.boundingBoxOfPath.midY))
if isSmallModel {
contentInset = UIEdgeInsets(top: 0, left: bounds.width / 2 - DISTANCELEFTANDRIGHT, bottom: 0, right: bounds.width / 2 - DISTANCELEFTANDRIGHT)
contentOffset = CGPoint(x: DISTANCEVALUE * ((currentRulerValue - minValue) / rulerAverage) - bounds.width + (bounds.width / 2 + DISTANCELEFTANDRIGHT), y: 0)
} else {
contentOffset = CGPoint(x: DISTANCEVALUE * ((currentRulerValue - minValue) / rulerAverage) - bounds.width / 2.0 + DISTANCELEFTANDRIGHT, y: 0)
}
contentSize = CGSize(width: CGFloat(rulerCount) * DISTANCEVALUE + DISTANCELEFTANDRIGHT * 2, height: bounds.height)
}
// Computed property to get the current ruler value based on scroll position
var currentRulerValue: CGFloat {
let offsetX = contentOffset.x + bounds.size.width / 2 - DISTANCELEFTANDRIGHT
return (offsetX / DISTANCEVALUE) * rulerAverage + minValue
}
}