php 仿高德,仿高德路线规划滑动效果
因为项目有个界面要模仿高德地图路径规划滑动效果,因此写了demo,并简单说下分析过程。
高德地图效果演示:
仿高德路线规划滑动.gif
demo效果演示:
高德地图规划滑动.gif
一. 分析
首先,我们可以看出这个滚动的视图应该是UIScrollView或者UIScrollView的子类(比如:UITableView);
其次,从高德地图里的视图一开始的滑动,可以看出这个滑动是平稳的滑动,没有加速和减速,因此这里不可能是UIScrollView的滚动效果,因为UIScrollView的滚动效果是由一个加减速的过程,因此一开始滑动,应该是通过滑动手势UIPanGestureRecognizer,来移动UIScrollView的y值来移动
接着滑动到指定位置之后,UIScrollView的y值固定不动,然后UIScrollView的内容进行滚动。这里就涉及到滑动手势UIPanGestureRecognizer的滑动,还有UIScrollView内部的滚动的处理。高德地图的演示效果里面,一开始滑动视图向上移动,移动到指定的点之后,立马就变成视图的滚动,这里可以分析,UIScrollView既支持手势的滑动又支持视图的滚动,只是通过条件来判断限制两者的执行逻辑。
同时我们可以看到,如果一开始向上拉动视图力度大一点,视图会直接滚动到指定位置,如果力度小,就恢复到原来位置,因此这里需要依据手势滑动的加速度来进行判断处理。
而当你滑动到中间位置的时候,也需要依据最后滑动的位置来判断应该动画滚动到上方还是下方。
最后滑动的时候上方的视图和滑动视图本身有背景颜色的渐变效果,这里需要依据滑动距离来判断。
二.代码分析:
首先由于滚动视图(demo里面是UITableView)需要支持手势滑动和内部滚动,因此需要写一个类FJBaseTableView继承自UITableView,然后在FJBaseTableView的实现里面重写如下方法:
// 当有 多个手势 都可以 响应
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
来支持响应多个手势。
然后给滚动视图tableView添加滑动手势,当tableView从底部滑动到顶部指定位置时,应该限制tableView内部的视图滚动。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.tableView.frame.origin.y > _scrollViewStartPositionY) {
[scrollView setContentOffset:CGPointMake(0, 0)];
}
}
这里的_scrollViewStartPositionY是顶部指定位置。
接着看下手势滑动的处理逻辑:
#pragma mark - 手势处理
- (void)handlePanGesture:(UIPanGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
_beganPoint = [sender locationInView:sender.view.superview];
_curPoint = sender.view.center;
_topTipContainerViewCurrentY = _topContainerView.frame.origin.y;
_previousOffsetY = self.tableView.contentOffset.y;
} else if(sender.state == UIGestureRecognizerStateChanged) {
CGPoint point = [sender locationInView:sender.view.superview];
CGFloat offsetY = _previousOffsetY - self.tableView.contentOffset.y;
NSInteger y_offset = point.y - _beganPoint.y - offsetY;
if (sender.view.frame.origin.y >= _scrollViewStartPositionY || (self.tableView.contentOffset.y == 0 && self.tableView.contentSize.height > self.tableView.frame.size.height)) {
sender.view.center = CGPointMake(_curPoint.x, _curPoint.y + y_offset);
[self updateViewControlsWithSlideOffset:y_offset];
}
if (sender.view.frame.origin.y > _scrollViewLimitMaxY) {
sender.view.y = _scrollViewLimitMaxY;
[self updateViewControlsWithSlideUp:NO];
}
else if(sender.view.frame.origin.y < _scrollViewStartPositionY) {
sender.view.y = _scrollViewStartPositionY;
[self updateViewControlsWithSlideUp:YES];
}
} else if(sender.state == UIGestureRecognizerStateEnded) {
if (sender.view.frame.origin.y <= _scrollViewStartPositionY || sender.view.frame.origin.y > _scrollViewLimitMaxY) {
if (sender.view.frame.origin.y <= _scrollViewStartPositionY) {
[self updateViewControlsWithSlideUp:YES];
}
if (sender.view.frame.origin.y > _scrollViewLimitMaxY) {
[self updateViewControlsWithSlideUp:NO];
}
return;
}
// 滑动速度处理
CGPoint velocity = [sender velocityInView:self.view];
CGFloat speed = 350;
if (velocity.y < - speed) {
// 快速向上
[self tableViewMoveToTop];
return;
} else if (velocity.y > speed) {
// 快速向下
[self tableViewMoveToBottom];
return;
}
// 滑动临界值
CGFloat criticalValue = _scrollViewLimitMaxY/2.0;
if (sender.view.frame.origin.y <= criticalValue) {
[self tableViewMoveToTop];
} else {
[self tableViewMoveToBottom];
}
}
}
这里几个点需要注意:
_beganPoint、_curPoint两个参数是用来计算手势滑动距离然后调整scrollView的滑动距离。而_previousOffsetY是用来记录滑动之前tableView的内部视图的偏移距离,因为当tableView滑动到顶部指定位置后,tableView开始滚动,这时候tableView向下滑动是先移动了tableView内部的滚动距离,然后才是滑动距离,因此需要将这部分值先记录,然后去除掉,才是tableView向下真正需要滑动的距离。
CGFloat offsetY = _previousOffsetY - self.tableView.contentOffset.y;
NSInteger y_offset = point.y - _beganPoint.y - offsetY;
2.滑动过程中,顶部视图的移动和渐变处理,这里先依据滑动的距离算出tableView滑动距离与tableView最大滑动距离的比值,然后再算出顶部视图需要移动的距离和背景的透明度。
- (void)updateViewControlsWhenSliding {
if (self.tableView.frame.origin.y > _scrollViewStartPositionY && self.tableView.frame.origin.y < _scrollViewLimitMaxY) {
CGFloat offsetLimitDistance = _scrollViewLimitMaxY - _scrollViewStartPositionY;
CGFloat offsetDistance = self.tableView.frame.origin.y - _scrollViewStartPositionY;
if (offsetDistance > 0 && offsetDistance < offsetLimitDistance) {
CGFloat topViewHeight = [FJFTopContainerView viewHeight];
CGFloat topViewHeightOffset = offsetDistance * (topViewHeight / offsetLimitDistance);
CGFloat viewAlpha = offsetDistance / offsetLimitDistance;
_topContainerView.y = topViewHeightOffset - topViewHeight;
_topContainerView.alpha = viewAlpha;
}
}
}
3.滑动速度处理,依据velocityInView函数获取速度值,然后依据当前速度值大小和正负和设定的速度值比较来判断是否需要向上或向下移动。
// 滑动速度处理
CGPoint velocity = [sender velocityInView:self.view];
CGFloat speed = 350;
if (velocity.y < - speed) {
// 快速向上
[self tableViewMoveToTop];
return;
} else if (velocity.y > speed) {
// 快速向下
[self tableViewMoveToBottom];
return;
}
4.滑动临界值处理,判断最后滑动位置与底部指定位置一半,两个值的大小来判断滑动的方向。
// 滑动临界值
CGFloat criticalValue = _scrollViewLimitMaxY/2.0;
if (sender.view.frame.origin.y <= criticalValue) {
[self tableViewMoveToTop];
} else {
[self tableViewMoveToBottom];
}
三.总结
这里最主要就是介绍了分析的思路,来找出可靠的实现方法,具体逻辑,详见demo
php 仿高德,仿高德路线规划滑动效果相关推荐
- Android 高德地图中路线规划绘制界面线路
Android 高德地图中路线规划绘制界面线路 下面代码是根据很多的经纬度的点,绘制出直线的线路.比较死板 /*** 绘制景区的路线*/private void setRouteInfo(List&l ...
- uniapp H5端使用高德地图完成路线规划
本项目是H5端,APP端地图的使用方法请参考我的另一篇博客uniapp,map地图组件打包原生APP 首先到高德地图API,申请web端key 参考高德H5端教程开始写代码高德地图JS API 1.准 ...
- 高德地图API路线规划
高德地图API基础使用 高德地图API体验 申请Key 初体验 添加插件 点击事件返回地址值 两点之间获取驾车导航路线 高德地图API体验 申请Key 申请高德地图账号 登录后,应用管理下创建自己的应 ...
- Android高德地图多路线规划----可点击选择路线
最近项目上有用到高德sdk,需求上要求多路线规划,并且可以在地图上点击选择路线.本着不想重复造轮子的驱使下(其实想偷懒),网上似乎没有例子,也可能是我找不到.最后没办法,只能自己实现. 在此做为记录, ...
- 高德地图之路线规划 多点路线规划路线最短原则之二 TSP算法
经过这段时间的使用和研究,我发现点和点之间的最短路线并不是最优的.针对所有点的组合可能, 得到的最短路线才是最好的(也就是TSP方法),然后再结合点对点之间的距离进行比较,得到的才是相对最优方案. 举 ...
- android 步行距离,Android 高德地图 步行 路线规划
路线规划就是给RouteSearch设置一个监听,里面有步行规划,骑车,驾车,公交等线路的规划 第 1 步,初始化 RouteSearch 对象 routeSearch = new RouteSear ...
- Android 高德地图 步行 路线规划
路线规划就是给RouteSearch设置一个监听,里面有步行规划,骑车,驾车,公交等线路的规划 第 1 步,初始化 RouteSearch 对象 routeSearch = new RouteSear ...
- 高德地图实现路线规划+轨迹回放(显示车牌)
联系作者Q/V:783021975 Tips: 1.高德好的方法非同步执行.一定要注意执行顺序或等待执行完成再进行具体的操作 2.高德地图不支持label旋转哦~ 3.百度是支持的.可以参考 百度地图 ...
- 微信小程序uniapp高德开放平台路线规划1对多导航路线方法记录
在高德开放平台申请key并下载sdk:amap-wx.js放到pages同级目录libs里面 <template><view class="content"> ...
最新文章
- Java项目:企业员工绩效工资管理系统(java+SpringBoot+FreeMarker+Mysql)
- 构造函数中,成员变量一定要通过初始化列表来初始化的几种情况(转载)
- 在oracle中怎么判断一个日期是否在一定时间范围内
- android sqlite 怎么写入存储时间
- c++max函数怎么用_比函数还强大的Excel分列技巧,你知道怎么用吗
- 网络编程学习笔记(readv和writev函数)
- 微信小程序图表插件 echarts-for-weixin
- 使用自定义的item、Adapter和AsyncTask、第三方开源框架PullToRefresh联合使用实现自定义的下拉列表(从网络加载图片显示在item中的ImageView)...
- 两数相加python代码实现(leetcode2)
- mybaitplus 根据id批量进行修改_批量重命名工具
- No module named 'oscar.apps.promotions'
- .Net架构必备工具列表
- python 分类变量xgboost_XGBoost 原理 及 常见面试题
- lodash是否是数组_lodash源码解析:for家族
- tuple操作、dict、其他常用操作
- Win11自动生成文件目录
- loss weight
- eclipse,wtp配置
- 亲爱的我把孩子放大了文案解说
- c++ strstr函数的实现
热门文章
- python文件读写用到的库_Python使用pyshp库读取shapefile信息的方法
- c语言实现链表结构6,用c语言实现的链表结构--数据结构实验
- ssh查找linux端口,linux – 查找当前连接的端口号SSH
- 电源变换适用于非独立源码_适用于非None测试的Python程序
- 记一次阿里巴巴一面的经历
- 如何在使用ASPMVC4的分部视图中获取数据展示
- SSH:hql语句传参报错,及antlr-2.7.2.jar重复包的删除
- 使用onclick跳转到其他页面/跳转到指定url
- Windows10安装Anaconda和Pytorch(CPU版,无GPU加速)
- postgres 把一个表的值转成另一个表的字段名_用LUT来做一个可动态配置的卷积核...