demo 传送门
demo

ios 10.0
因为 UI 做了一些很别致的进度条效果图,而且在网上又找不到合适的三方库,自己在网上查查资料做了出来,然后整理了一下,分享给大家使用
首先,这个东西只是用贝赛尔曲线做出来的,并不是很难,做出来只是略微麻烦一点,网上也有很多资料,不过并不是很多,所以我就整理了一下,一是整理备份一下记录,二是分享给大家看下
UI 设计很漂亮,但是由于数据过多或过少,导致太难看,最后放弃

///贝塞尔直线
private lazy var path: UIBezierPath = {
let bezierPath = UIBezierPath()
bezierPath.move(to: CGPoint(x: 0, y: 0))
bezierPath.addLine(to: CGPoint(x: bounds.size.width, y: 0))
return bezierPath
}()
此处 lineDashPattern 是长度对比,一长一短线,我使用的是两个数据,多个的话,暂时没弄明白,有大佬了解的留个言,
建议:此处进度最好和你自己进度比率相同,要不然会出现上图的情况(一线两色)
///背景线
private lazy var backLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.fillColor = UIColor.clear.cgColor
layer.strokeColor = .green.cgColor
layer.lineWidth = 2
layer.lineDashPattern = [15, 3]
layer.path = path.cgPath
return layer
}()
///进度条线
private lazy var progressLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.fillColor = UIColor.clear.cgColor
layer.strokeColor = .red.cgColor
layer.lineWidth = 2
layer.lineDashPattern = [15, 3]
layer.strokeStart = 0
layer.strokeEnd = 0
layer.path = path.cgPath
return layer
}()
直接设置 progressLayer.strokeEnd = progress 会显得突兀,我再此添加了一个动画,
后续此处就不一一说明
///数据
layer.addSublayer(backLayer)
layer.addSublayer(progressLayer)
///进度
public var progress: CGFloat = 0.0 {
didSet {
CATransaction.begin()
CATransaction.setDisableActions(false)
CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .linear))
CATransaction.setAnimationDuration(2)
progressLayer.strokeEnd = progress
CATransaction.commit()
}
}

///背景颜色
public var backColor: UIColor = .gray
///进度条颜色
public var progressColor: UIColor = .red
///线宽
public var lineWidth: CGFloat = 2.0
///圆直径
public var realWidth: CGFloat = 100
///圆起点角度。角度从水平右侧开始为0,顺时针为增加角度。直接传度数 如-90
public var startAngle: CGFloat = 0.5 * .pi
///圆结束角度。角度从水平右侧开始为0,顺时针为增加角度。直接传度数 如-90
public var endAngle: CGFloat = 0.5 * .pi
///动画时长
public var duration: CGFloat = 2
设置中心点、半径(通过直径 - 宽度计算得来)、起始位置,结束位置
let radius = realWidth / 2 - lineWidth
///贝塞尔直线
private lazy var path: UIBezierPath = {
let bezierPath = UIBezierPath(arcCenter: CGPoint(x: realWidth/2, y: realWidth/2),
radius: radius,
startAngle: startAngle,
endAngle: 2 * .pi + endAngle,
clockwise: true)
return bezierPath
}()
然后 添加到视图,和设置进度我就不说了,上面都有, 至于是多少角度的圆形,设置起始角度和结束角度就可以了
///背景圆环
private lazy var backLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.frame = bounds
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = lineWidth
layer.strokeColor = backColor.cgColor
layer.lineCap = .round
layer.path = path.cgPath
return layer
}()
///进度圆环
private lazy var progressLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.frame = bounds
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = lineWidth
layer.strokeColor = progressColor.cgColor
layer.lineCap = .round
layer.path = path.cgPath
layer.strokeEnd = 0
return layer
}()

相同参数我就不在一一叙述
///渐变颜色
public var colors: [CGColor] = [UIColor.red.cgColor, UIColor.green.cgColor]
///渐变色位置
public var locations: [NSNumber] = [0, 1]
///渐变色起始位置
public var startPoint: CGPoint = CGPoint(x: 0, y: 0)
///渐变色结束位置
public var endPoint: CGPoint = CGPoint(x: 1, y: 0)
///渐变背景
private lazy var gradientLayer: CAGradientLayer = {
let layer = CAGradientLayer()
layer.frame = bounds
layer.colors = colors
layer.locations = locations
layer.startPoint = startPoint
layer.endPoint = endPoint
return layer
}()
然后加载进度就可以了
gradientLayer.mask = progressLayer
layer.addSublayer(gradientLayer)

此处我使用了 UIView,你可以采用图片、渐变 view 等
在 layer.addSublayer(progressLayer) 后面放入,
addSubview(dot)
dot.isHidden = true
使用 CAAnimation 加载动画
整圆和非整圆这块加载我没给弄清楚,有了解的大佬请给予指出,虽然结果没错,但是两套逻辑总感觉很奇怪
private lazy var pointAnimation: CAAnimation = {
let animation = CAKeyframeAnimation(keyPath: "position")
animation.timingFunction = CAMediaTimingFunction(name: .linear)
animation.fillMode = .forwards
animation.calculationMode = CAAnimationCalculationMode.paced
animation.isRemovedOnCompletion = false
animation.duration = duration
///此处记得加载代理,不用执行方法
animation.delegate = self
var end = 2 * .pi * progress + startAngle
///非整圆
if data.startAngle != data.endAngle {
end = (2 * .pi - CGFloat(fabs(Double(endAngle))) - startAngle) * progress + startAngle
}
let imagePath = UIBezierPath(arcCenter: CGPoint(x: realWidth/2, y: realWidth/2),
radius: radius,
startAngle: startAngle,
endAngle: end,
clockwise: true)
animation.path = imagePath.cgPath
return animation
}()
执行加载动画, 此处跟谁到 progress 设置进度后面即可
dot.isHidden = false
dot.layer.add(pointAnimation, forKey: "pointAnimation")

此处总长度是圆周长长度,这个切记要计算好,否则最后一根线会有问题
///线间距 间断进度条专属 直线计算长度,圆计算周长
public var lineDashPattern: [NSNumber] = [15 , 5]
///贝塞尔直线
private lazy var path: UIBezierPath = {
let bezierPath = UIBezierPath(arcCenter: CGPoint(x: data.realWidth / 2, y: data.realWidth / 2),
radius: radius,
startAngle: startAngle,
endAngle: 2 * .pi + endAngle,
clockwise: true)
return bezierPath
}()
///背景
private lazy var backLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.frame = bounds
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = lineWidth
layer.strokeColor = backColor.cgColor
layer.path = cgPath
layer.lineDashPattern = lineDashPattern
return layer
}()
///进度条
private lazy var progressLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.frame = bounds
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = lineWidth
layer.strokeColor = progressColor.cgColor
layer.path = path.cgPath
layer.strokeEnd = 0
layer.lineDashPattern = lineDashPattern
return layer
}()
添加和设置进度和之前一样,我就不一一赘述
1、通过设置 type 类型,添加各种类型的进度条
let newView = HJProgress(frame: CGRect(x: 10, y: 110, width: 120, height: 120))
newView.type = .circle
2、通过设置HJData() 设置各种参数,添加数据之后,才会出现进度条
var data = HJData()
data.realWidth = 120
data.lineWidth = 2
newView.data = data
3、通过设置progress 加载进度条
具体例子看我上面的 demo 吧,欢迎来提建议
我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r
我一直在搜索net/http代码,但还没有找到解决方案。我需要执行一个多部分POST请求,我已经弄清楚了,但是在上传中定期注入(inject)一个回调真的很好,这样我就可以增加一个进度条。有谁知道一种方法可以让代码执行HTTPpost期间发送的每X个字节? 最佳答案 看起来您没有使用Rails,但我认为最简单的方法是从客户端进行。在浏览器设置中,您可以使用Flash(SWFUpload)或仅使用新的XMLHttpRequest内容向新浏览器提供进度条(上传在旧浏览器中仍然有效...只是没有进度条)。它的工作原理与您描述的略有不同,但
我正在尝试将温度从华氏度转换为摄氏度:puts'ConvertirgradosFahrenheitaCelcius'STDOUT.flushx=gets.chompaprox=(x*100.0).round(2)/100.0resultado=(aprox-32)/1.8putsresultado我使用正确的公式将华氏度转换为摄氏度:Celsius=Fahrenheit-32/1.8但是,当我在控制台中运行它时,出现以下错误:`round':wrongnumberofarguments(1for0)(ArgumentError)我尝试过不同的方法,但我不明白为什么这不起作用。
我希望能够在使用Ruby复制文件时显示文件复制操作的进度(当前使用FileUtils.cp)我已经尝试将verbose选项设置为是的,但这似乎只是向我展示了发出的复制命令。我现在正在从命令行运行这个脚本,所以理想情况下我希望能够像SCP在复制文件时那样呈现一些东西,但只要我能,我就不太在意呈现查看进度。 最佳答案 因为我没有足够的代表来编辑答案,所以这是我基于pisswillis答案的版本,我找到了progressbargem我也在我的例子中使用。我已经对此进行了测试,到目前为止它工作正常,但它可以做一些清理工作:require'r
我正在开发一个Sinatra应用程序,它包含一个上传表单,并带有一个进度条,指示上传完成了多少。该过程,如ryandahl所述,如下:HTTPuploadprogressbarsareratherobfuscated-theytypicallyinvolveaprocessrunningontheserverkeepingtrackofthesizeofthetempfilethattheHTTPserveriswritingto,thenontheclientsideanAJAXcallismadeeverycouplesecondstotheserverduringtheuploa
有谁知道在下载文件时从ruby的Net::FTP库获取状态更新的方法吗?我正在尝试实现一个Web界面,该界面显示从远程FTP服务器下载文件时剩余百分比的进度条。 最佳答案 供将来引用-我偶然发现了一个解决方案:filesize=ftp.size(filename)transferred=0p"Beginningdownload,filesize:#{filesize}"ftp.getbinaryfile(filename,"#{SOURCE_IMPORT_DIRECTORY}/#{filename}",1024){|data|t
当您运行gitclone时,它会就地更新进度。例如,接收到位置变化的对象的百分比。user@athena:~/cloj/src$gitclonegit://git.boinkor.net/slime.gitInitializedemptyGitrepositoryin/home/user/cloj/src/slime/.git/remote:Countingobjects:15936,done.remote:Compressingobjects:100%(5500/5500),done.Receivingobjects:28%(4547/15936),3.16MiB|165KiB/s这
我在更新jquery进度条时遇到了一些问题。这个进度条在页面加载期间不在文档中,我只是在用户单击按钮时添加它,如下所示:$(this).parent().append('');$(this).parent().children('div.progressbar').show();$(this).parent().children('div.progressbar').progressbar({value:20});然后,使用超时,我正在尝试更新它functionupdateProgressBar(){$('.progressbar').each(function(){myNewValu
我目前正在开发一个文件转换程序,文件上传后,它会将文件转换为不同的文件格式(ppt、pdf),这通常需要很长时间,具体取决于文件大小。由于文件转换发生在后端,我希望用户看到文件转换的进度(类似于进度条,例如“正在转换52%的文件”),无论如何我可以向用户显示当前的进度文件转换(发生在后端)?在文件转换期间,我只能显示状态(以数字表示(由我正在使用的API提供))我不知道从哪里开始有人可以提供一些见解或方法吗? 最佳答案 如果您使用的是Struts2,请查看ExecuteandWaitInterceptor.它会为您的任务创建新线程,
我有html代码。我需要一些javascript代码来更新每次迭代的值for(i=0;i我试着做这样的事情:varprogressBar=document.getElementById("progressBar");progressBar.value+=i;但这行不通。它在循环结束时更新进度条。 最佳答案 我为此苦苦挣扎了好几天,最后将我学到的知识应用到以下相当简单的解决方案中,该解决方案在HTML页面上放置了一个按钮和一个进度条。单击按钮时,javascript开始计数,并随着计数的进行更新进度条。计数在按钮定义中设置为默认值43