当前位置: 首页 > news >正文

郑州做网站云极手游网站建设

郑州做网站云极,手游网站建设,搞外贸一般是干什么的,wordpress wplogin.php引言 视频截取在社交类 APP 中十分常见。有了上传视频的功能#xff0c;就不可避免地需要提供截取和编辑的选项。如果我们过度依赖第三方库#xff0c;项目的代码可能会变得异常臃肿#xff0c;因为这些库往往包含许多我们用不到的功能#xff0c;而且它们的 UI 样式和功能… 引言 视频截取在社交类 APP 中十分常见。有了上传视频的功能就不可避免地需要提供截取和编辑的选项。如果我们过度依赖第三方库项目的代码可能会变得异常臃肿因为这些库往往包含许多我们用不到的功能而且它们的 UI 样式和功能通常比较固定不支持定制。因此有条件的话尽可能自行实现这些功能。 原本我打算直接介绍视频截取的实现方式但发现相关的 UI 设计也非常有趣。如果不把 UI 和视频截取功能结合起来即使掌握了截取技术也可能难以打造出一个好用的视频编辑工具。因此在本篇博客中我们先来介绍视频截取中最常见的 UI 样式和小组件。 组件结构 我们创建一个继承自UIView的SVVideoEditBar类整个编辑的操作小组件可以分为播放控制和截取控制两部分 播放控制 第一部分是播放和暂停按钮控制截取后视频的播放和暂停功能这里比较简单只需要一个按钮就可以实现。 /// 播放按钮private var playButton UIButton()/// 添加播放按钮private func addPlayerButton() {playButton.setImage(UIImage(named: icon_play_light_fill_24), for: .normal)playButton.setImage(UIImage(named: icon_pause_light_fill_24), for: .selected)self.addSubview(playButton)playButton.snp.makeConstraints { make inmake.leading.equalToSuperview().offset(16.0)make.centerY.equalToSuperview()make.width.height.equalTo(24.0)}}截取控制 第二部分为截取控制部分可以再详细划分为展示部分和操作部分。 展示 对于展示部分我们采用UICollectionView来显示视频获取到的缩略图。 /// 列表private var collectionView:UICollectionView!/// 添加列表private func addCollectionView() {let layout UICollectionViewFlowLayout()layout.minimumLineSpacing 0.0layout.scrollDirection .horizontalcollectionView UICollectionView(frame: .zero, collectionViewLayout: layout)collectionView.contentInset UIEdgeInsets(top: 0.0, left: 10.0, bottom: 0.0, right: 10.0)collectionView.backgroundColor UIColor.clearcollectionView.showsHorizontalScrollIndicator falsecollectionView.delegate selfcollectionView.dataSource selfcollectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cell)self.addSubview(collectionView)collectionView.snp.makeConstraints { make inmake.leading.equalTo(lineView.snp.trailing).offset(20.0)make.trailing.equalToSuperview().offset(-20.0)make.top.equalToSuperview().offset(8.0)make.bottom.equalToSuperview().offset(-8.0)}collectionView.backgroundColor .red}关于列表中图片的尺寸会根据视频的尺寸来确定所以我们将大小在代理方法中进行设置 extension SVVideoEditBar: UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) - Int {return 10}func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) - UICollectionViewCell {let cell collectionView.dequeueReusableCell(withReuseIdentifier: cell, for: indexPath)return cell}func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) - CGSize {return CGSize(width: 40.0, height: collectionView.bounds.height)} } 滑动遮罩 遮罩也分为两部分一部分为黄色的边框边框内的内容表示的是视频截取后保留的部分而黄色边框以外的黑色半透明的遮罩则表示视频截取后舍弃的部分。 黄色的部分由我们自定义的视图SVEditorSliderView来实现。 /// 可拖拽滑动视图private var sliderView SVEditorSliderView()/// 添加滑动视图private func addSliderView() {self.addSubview(sliderView)sliderView.layer.cornerRadius 8.0sliderView.backgroundColor UIColor.yellowupdateLeftRightOffset()// 右侧拖拽回调sliderView.rightDragBlock { [weak self] x in...}// 左侧拖拽回调sliderView.leftDragBlock { [weak self] x in....}} /// 更新左右侧偏移private func updateLeftRightOffset() {sliderView.snp.remakeConstraints { make inmake.leading.equalTo(lineView.snp.trailing).offset(leftOffset)make.top.bottom.equalToSuperview()make.trailing.equalToSuperview().offset(rightOffset)}}两侧的黑色半透明遮罩直接通过UIView设置背景颜色的方式来实现 /// 左侧蒙层private var leftMaskView UIView()/// 右侧蒙层private var rightMaskView UIView()/// 添加左侧蒙层private func addLeftMaskView() {leftMaskView.backgroundColor UIColor.black.withAlphaComponent(0.3)self.addSubview(leftMaskView)leftMaskView.snp.makeConstraints { make inmake.top.bottom.equalToSuperview()make.leading.equalTo(self.lineView.snp.trailing)make.trailing.equalTo(sliderView.snp.leading)}}/// 添加右侧蒙层private func addRightMaskView() {rightMaskView.backgroundColor UIColor.black.withAlphaComponent(0.3)self.addSubview(rightMaskView)rightMaskView.snp.makeConstraints { make inmake.top.bottom.equalToSuperview()make.leading.equalTo(sliderView.snp.trailing)make.trailing.equalToSuperview()}} 进度条 另外还有一个在播放时会跟随播放进度而移动的进度条直接使用UIView加阴影的方式来实现。 class SVProgressLineView: UIView {override init(frame: CGRect) {super.init(frame: frame)self.backgroundColor .whiteself.layer.cornerRadius 1.0// 阴影self.layer.shadowColor UIColor.black.cgColorself.layer.shadowOffset CGSize(width: -1, height: 0)self.layer.shadowOpacity 0.5self.layer.shadowRadius 2.0}required init?(coder: NSCoder) {fatalError(init(coder:) has not been implemented)}}/// 进度线private var progressLineView SVProgressLineView()/// 添加进度线private func addProgressLineView() {self.addSubview(progressLineView)progressLineView.snp.makeConstraints { make inmake.leading.equalTo(sliderView).offset(20.0 10.0)make.centerY.equalToSuperview()make.width.equalTo(2.0)make.height.equalTo(self.snp.height).inset(8.0)}}实现操作视图 - SVEditorSliderView 接下来我们把重点集中到SVEditorSliderView上面首先它需要一个镂空效果来显示底部的缩图列表另外它的两侧还需要可拖拽来修改视频的截取区域。 镂空效果 那我们先来实现它的镂空效果采用图层的mask属性和贝塞尔曲线结合来实现镂空。 /// maskLayerprivate let maskLayer CAShapeLayer()/// pathprivate var path UIBezierPath()/// fullPathprivate var fullPath UIBezierPath() override init(frame: CGRect) {super.init(frame: frame)maskLayer.backgroundColor UIColor.black.cgColorself.layer.mask maskLayermaskLayer.fillRule .evenOdd...} override func layoutSubviews() {let width self.bounds.widthlet height self.bounds.heightfullPath UIBezierPath(rect: self.bounds)path UIBezierPath(rect: CGRect(x: 20.0, y: 8.0, width: width - 40.0, height: height - 16.0))fullPath.append(path)fullPath.usesEvenOddFillRule truemaskLayer.path fullPath.cgPath....} 拖拽事件 在视图的最左侧和最右侧添加可拖拽的UIView视图并处理拖拽事件由于该视图的布局在父视图上所以我们选择将退拽事件回调出去来处理。 /// 右侧可拖拽视图private let rightDragView UIView()/// 左侧可拖拽视图private let leftDragView UIView()/// 右侧退拽回调var rightDragBlock:((CGFloat)-Void)?/// 左侧拖拽回调var leftDragBlock:((CGFloat)-Void)?/// 添加右侧可拖拽视图private func addRightDragView() { // rightDragView.backgroundColor .whiteself.addSubview(rightDragView)let pan UIPanGestureRecognizer(target: self, action: #selector(panAction(_:)))rightDragView.addGestureRecognizer(pan)rightDragView.isUserInteractionEnabled true}/// 添加左侧可拖拽视图private func addLeftDragView() { // leftDragView.backgroundColor .whiteself.addSubview(leftDragView)let pan UIPanGestureRecognizer(target: self, action: #selector(panAction(_:)))leftDragView.addGestureRecognizer(pan)leftDragView.isUserInteractionEnabled true} objc private func panAction(_ pan:UIPanGestureRecognizer) {// 获取视图let view pan.viewif view rightDragView {let translation pan.translation(in: self)let x translation.xrightDragBlock?(x)} else if view leftDragView {let translation pan.translation(in: self)let x translation.xleftDragBlock?(x)}pan.setTranslation(.zero, in: self)}override func layoutSubviews() {let width self.bounds.widthlet height self.bounds.height...rightDragView.frame CGRect(x: width - 20.0, y: 0.0, width: 20.0, height: height)leftDragView.frame CGRect(x: 0.0, y: 0.0, width: 20.0, height: height)} 拖拽处理 处理拖拽事件是个细活在拖拽过程中我们需要更新sliderView的布局约束我们把它分成两个部分来讨论。 右侧拖拽事件 在SVVideoEditBar类中我们还定义另外两个CGFloat类型属性 /// 左侧偏移     private var leftOffset:CGFloat 0.0     /// 右侧偏移     private var rightOffset:CGFloat 0.0 分别表示sliderView的左侧约束的偏移量和右侧约束的偏移量默认都为0.0。 在进行右侧退拽时我们首先需要注意的是往右拖拽时不能超过SVVideoEditBar的最右端而往左退拽时不能超过sliderView自己的最左端的拖拽视图。 // 右侧拖拽回调sliderView.rightDragBlock { [weak self] x inguard let self self else { return }// 限制右侧往右的拖拽范围if self.sliderView.frame.maxX self.bounds.width x 0 {print(右侧往右拖拽到最大范围)self.rightOffset 0.0self.updateLeftRightOffset()return}// 限制右侧往左的拖拽范围if self.sliderView.frame.maxX (self.sliderView.frame.minX40.0) x 0 {print(右侧往左拖拽到最小范围)self.rightOffset -(self.bounds.width - self.sliderView.frame.minX - 40.0)self.updateLeftRightOffset()return}self.rightOffset self.rightOffset xself.updateLeftRightOffset()}左侧拖拽事件 当我们拖拽左侧是视图时需要注意当往左侧拖拽时不能超过左侧的起始位置也就是竖线的最最右侧。而往右拖拽时同样也不能超过右侧的拖拽视图。 // 左侧拖拽回调sliderView.leftDragBlock { [weak self] x inguard let self self else { return }// 限制左侧往左的拖拽范围if self.sliderView.frame.minX self.lineView.frame.maxX x 0 {print(左侧往左拖拽到最小范围)self.leftOffset 0.0self.updateLeftRightOffset()return}// 限制左侧往右的拖拽范围if self.sliderView.frame.minX (self.sliderView.frame.maxX-40.0) x 0 {print(左侧往右拖拽到最大范围)self.leftOffset self.sliderView.frame.maxX - 40.0 - self.lineView.frame.maxXself.updateLeftRightOffset()return}self.leftOffset self.leftOffset xself.updateLeftRightOffset()}这样像GIF图片一样的视频剪裁小组件的UI部分就实现了。 结语 本篇博客主要介绍了视频截取中的UI小组件介绍了如何实现镂空效果以及拖拽事件尤其是拖拽时临界值的处理。 获取到了裁剪区域之后我们就可以根据视频的长度来进行视频截取了那么下一篇博客我们将开始进入视频截取的数据处理部分。
http://www.hkea.cn/news/14266280/

相关文章:

  • 网站提示未备案有哪些企业公司
  • 高企达建设有限公司网站哪家公司做网站结算好
  • 越城区建设和交通运输局网站广州建筑信息平台
  • 一家企业如何建设自己的网站 下载凡科论坛网站制作
  • 网站购物车作用网站设计与制作优点
  • 安联建设集团股份公司网站网站会员注册怎么做
  • 舆情运营岗位主要做什么win7优化配置的方法
  • 韶关哪里做网站最好wordpress一键还原
  • app网站与普通网站的区别wordpress文章页面
  • 台山市网站建设企业网站管理系统信得过y湖南岚鸿怎么样
  • 外贸西班牙语网站建设网站制作价格 上海
  • 电子商务网站建设调查报告软件推广是什么工作
  • 德州中文网站建设网页美工设计需求说明
  • 做化工行业网站中立建设集团有限公司网站
  • 网站开发个性化书签制作方法
  • 网站名称跟域名手帐风格wordpress主题
  • 网站建设域名注册免费河南洛阳网络公司
  • 做网站需要哪些东西wordpress固定链接
  • 网站即将 模板做网站时的尺寸
  • 网上祭奠类网站怎么做wordpress seo
  • 新手做网站看什么书盐城网页制作哪家好
  • 商务网站建设实训报告今天刚刚发生的新闻事故
  • 招标网站都有哪些家装设计图纸
  • 做视频网站需要多大的带宽美容网站模版
  • 河南建设通网站长宁专业网站制作公司
  • 盘锦企业网站建设广州网站备案
  • 如何选择五屏网站建设北京展览设计制作工厂
  • 站群系统有哪些免费网站推广网站破解版
  • 旅行社做境外购物网站wordpress小工具是什么意思
  • 在线可以做翻译的网站赣州建设网站公司