仿转转首页Banner图
2018-04-23 本文已影响41688人
z小志
4月-23-2018 14-04-47.gif
实现效果
- 当banner滚动的时候 首先会缩放当前以及上一个或下一个banner图,
- 当banner滚动时会,背景会随滚动系数变化
部分实现
1、缩放(自动滚动)
自动滚动开始时 缩放当前cell
@objc func automaticScroll(){
if totalItemCount == 0{return}
let currentIndex = self.currentIndex()
let targetIndex = currentIndex + 1
let cell = banner.cellForItem(at: IndexPath.init(row: currentIndex, section: 0))
UIView.animate(withDuration: 0.2, animations: {
cell?.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
}) { (finish) in
self.scrollToIndex(targetIndex: targetIndex)
}
}
//滚动动画结束后还原 当前 以及 前后的cell
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
self.autoScrollIndex = self.currentIndex()
let cell1 = banner.cellForItem(at: IndexPath.init(row: self.autoScrollIndex - 1 < 0 ? totalItemCount : self.autoScrollIndex - 1, section: 0))
let cell2 = banner.cellForItem(at: IndexPath.init(row: self.autoScrollIndex , section: 0))
let cell3 = banner.cellForItem(at: IndexPath.init(row: self.autoScrollIndex + 1 > totalItemCount ? totalItemCount/2 : 0, section: 0))
UIView.animate(withDuration: 0.2) {
cell1?.transform = CGAffineTransform(scaleX: 1, y: 1)
cell2?.transform = CGAffineTransform(scaleX: 1, y: 1)
cell3?.transform = CGAffineTransform(scaleX: 1, y: 1)
}
}
2、缩放(拖动)
if scrollView.isDragging || scrollView.isDecelerating{
let itemIndex = self.pageControlIndexWithCurrentCellIndex(index: draggingIndex)
//向左
if lastContentOffset > curretContentOffset{
let cell1 = banner.cellForItem(at: IndexPath.init(row: self.draggingIndex, section: 0))
let cell2 = banner.cellForItem(at: IndexPath.init(row: self.draggingIndex - 1 < 0 ? totalItemCount: self.draggingIndex - 1, section: 0))
UIView.animate(withDuration: 0.1) {
cell1?.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
cell2?.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
}
let topIndex = itemIndex - 1 < 0 ? self.banners.count - 1 : itemIndex - 1
let bottomIndex = itemIndex
self.topImage.sd_setImage(with: URL.init(string: banners[topIndex].bgImg!), completed: nil)
self.bottomImage.sd_setImage(with: URL.init(string: banners[bottomIndex].bgImg!), completed: nil)
UIView.animate(withDuration: 0.5, animations: {
self.leftView.setRadius(radius: (mainW * CGFloat(self.draggingIndex) - curretContentOffset) * 2, direction: .right)
self.rightView.setRadius(radius: 0, direction: .left)
})
}else{
//向右
let cell1 = banner.cellForItem(at: IndexPath.init(row: self.draggingIndex, section: 0))
let cell2 = banner.cellForItem(at: IndexPath.init(row: self.draggingIndex + 1 >= totalItemCount ? totalItemCount/2 : draggingIndex + 1, section: 0))
UIView.animate(withDuration: 0.1) {
cell1?.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
cell2?.transform = CGAffineTransform(scaleX: 0.85, y: 0.85)
}
let topIndex = itemIndex + 1 > self.banners.count - 1 ? 0 : itemIndex + 1
let bottomIndex = itemIndex
self.topImage.sd_setImage(with: URL.init(string: banners[topIndex].bgImg!), completed: nil)
self.bottomImage.sd_setImage(with: URL.init(string: banners[bottomIndex].bgImg!), completed: nil)
UIView.animate(withDuration: 0.5, animations: {
self.leftView.setRadius(radius: 0, direction: .right)
self.rightView.setRadius(radius: (mainW * CGFloat(self.draggingIndex) - curretContentOffset) * 2, direction: .left)
})
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
//拖动结束后
lastContentOffset = scrollView.contentOffset.x
self.autoScrollIndex = self.currentIndex()
let cell1 = banner.cellForItem(at: IndexPath.init(row: self.autoScrollIndex - 1 < 0 ? totalItemCount : self.autoScrollIndex - 1 , section: 0))
let cell2 = banner.cellForItem(at: IndexPath.init(row: self.autoScrollIndex , section: 0))
let cell3 = banner.cellForItem(at: IndexPath.init(row: self.autoScrollIndex + 1 > totalItemCount ? totalItemCount/2 : 0, section: 0))
UIView.animate(withDuration: 0.2) {
cell1?.transform = CGAffineTransform(scaleX: 1, y: 1)
cell2?.transform = CGAffineTransform(scaleX: 1, y: 1)
cell3?.transform = CGAffineTransform(scaleX: 1, y: 1)
}
}
2、背景动画
思路:
在view底层有两个imageView 在最上层的view加个MaskView(遮罩)MaskView 上分别添加两个view即leftView以及当banner滚动时 改变左右的圆的半径 实现动画效果
UIView.animate(withDuration: 0.5, animations: {
self.leftView.setRadius(radius: (curretContentOffset - mainW * CGFloat(itemIndex)) * 2, direction: .right)
self.rightView.setRadius(radius: 0, direction: .left)
})
UIView.animate(withDuration: 0.5, animations: {
self.leftView.setRadius(radius: 0, direction: .right)
self.rightView.setRadius(radius: (curretContentOffset - mainW * CGFloat(self.autoScrollIndex)) * 2, direction: .left)
})
import UIKit
enum MDBannerSrollDirection {
case unknow
case left
case right
}
class MDMaskView: UIView {
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
var maskRadius:CGFloat = 0
var direction:MDBannerSrollDirection = .unknow
func setRadius(radius:CGFloat,direction:MDBannerSrollDirection){
self.maskRadius = radius
self.direction = direction
if self.direction != .unknow{
self.setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
self.backgroundColor = .clear
if direction != .unknow{
let ctx = UIGraphicsGetCurrentContext()
if direction == .left{
ctx?.addArc(center: CGPoint(x: self.center.x + rect.width/2, y: self.center.y), radius: maskRadius, startAngle: 0, endAngle: .pi * 2, clockwise: false)
}else{
ctx?.addArc(center: CGPoint(x: self.center.x - rect.width/2, y: self.center.y), radius: maskRadius, startAngle: 0, endAngle: .pi * 2, clockwise: false)
}
ctx?.setFillColor(UIColor.white.cgColor)
ctx?.fillPath()
}
}
}
github地址 https://github.com/daimengxiaozhi/MDShockBannerView 给个Star吧!
2018.4.27 新增OC版本 2018.5.3 新增Android版本
注:初步尝试可能会有bug,欢迎大家提出建议。
附安卓使用代码:
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
mBannerList = result.data;
mBOneBanner.setImages(mBannerList)
.setImageLoader(new GlideImageLoader()).start();
@Override
public void onStart() {
super.onStart();
mBOneBanner.stopAutoPlay();
}
@Override
public void onStop() {
super.onStop();
//结束轮播
mBOneBanner.stopAutoPlay();
}
@Override
public void OnBannerClick(int position) {
//点击事件
}