- Notifications
You must be signed in to change notification settings - Fork0
nanxiaobei/taro-ux-kits
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Create now ➫🔗 kee.so
使用 Taro 开发FUTAKE 小程序时,7 个与用户体验有关的优化。
参考官方 Dark Mode 适配指南 添加theme.json,并在app.config.js 中添加相关配置。
小程序自身 UI 的 Dark Mode,可使用 CSS 变量来控制,其它需要变化的色值,均源自 CSS 变量即可。
完整代码 →github.com/nanxiaobei/taro-ux-kits/tree/main/dark-mode
▶ 点击查看代码
// less 主题文件#theme() {--dark:#000;--darken:0,0,0;--light:#fff;--lighten:255,255,255;--yellow:#ff9500;--green:#34c759;--blue:#007aff;--indigo:#048;--red:#ff3b30;}#dark-theme() {--dark:#fff;--darken:255,255,255;--light:#000;--lighten:0,0,0;--yellow:#ff9500;--green:#30d158;--blue:#0a84ff;--indigo:#bce;--red:#ff453a;}page {#theme();}@media (prefers-color-scheme:dark) {page {#dark-theme(); }}
FUTAKE 实现了类似手机原生弹窗的效果 —— 按住弹窗体后,可上下拖动弹窗。
实现方式即监听 touch 相关事件,动态设置 CSS 偏移。
完整代码 →github.com/nanxiaobei/taro-ux-kits/tree/main/draggable-modal
▶ 点击查看代码
// 核心代码(省略了工具函数)constonTouchStart=useCallback((event)=>{if(stopClose)return;const{ pageX, pageY}=event.changedTouches[0];startX.current=pageX;startY.current=pageY;startTime.current=Date.now();},[stopClose],);constonTouchMove=useCallback((event)=>{if(stopClose)return;constdiffY=getDiffY(event.changedTouches[0]);if(!diffY)return;setBottomRef.current(diffY);},[stopClose],);constonTouchEnd=useCallback((event)=>{if(stopClose)return;constdiffY=getDiffY(event.changedTouches[0]);if(!diffY){setBottomRef.current(0);return;}if(diffY>200||(diffY>10&&Date.now()-startTime.current<200)){onClose();setTimeout(()=>setBottomRef.current(0),200);return;}setBottomRef.current(0);},[onClose,stopClose],);
使用自定义 tarBar,实现模糊半透明的毛玻璃效果,随着页面滚动 tabBar 一直动态变化。
使用 CSS 的backdrop-filter 来实现。
完整代码 →github.com/nanxiaobei/taro-ux-kits/tree/main/custom-tab-bar
▶ 点击查看代码
.tab-bar { --lighten: 255, 255, 255; position: fixed; right: 0; bottom: 0; left: 0; display: flex; align-items: center; backdrop-filter: blur(24px);}.tab { position: relative; display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; height: calc(96px + constant(safe-area-inset-bottom)); height: calc(96px + env(safe-area-inset-bottom)); padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);}.icon { width: 44px; height: 44px; opacity: 0.2;}.tab.active .icon,.tab.hover .icon { opacity: 1;}@media (prefers-color-scheme: dark) { .tab-bar { --lighten: 0, 0, 0; } .icon { filter: invert(1); }}手机系统为左侧边缘向右滑返回,但如果屏幕过大,操作并不太顺手。
在一些 App 中,实现了直接在页面上右滑返回的效果,例如 Slack 和 Snapchat,体验非常顺滑。
在 Taro 小程序中,首先需要添加一个公共组件,页面均使用此公共组件包裹,然后在公共组件中监听 touch 相关事件。
这里的重点是需要计算滑动的角度,例如→ 这样的可以返回,但↘ 和↓ 这样的,应该忽略掉。
完整代码 →github.com/nanxiaobei/taro-ux-kits/tree/main/touch-move-back
▶ 点击查看代码
// React Hooks(省略了工具函数)constuseMoveX=({ toLeft, toRight, disable})=>{conststartX=useRef(0);conststartY=useRef(0);conststartTime=useRef(0);constonTouchStart=useCallback((event)=>{if(disable)return;const{ pageX, pageY}=event.changedTouches[0];startX.current=pageX;startY.current=pageY;startTime.current=Date.now();},[disable],);constgetAbsAngle=useCallback((diffX,pageY)=>{constdiffY=pageY-startY.current;constangle=getAngle(diffX,diffY);returnMath.abs(angle);},[]);constonTouchEnd=useCallback((event)=>{if(disable)return;const{ pageX, pageY}=event.changedTouches[0];constdiffX=pageX-startX.current;if(diffX>0){if(!toRight||getAbsAngle(diffX,pageY)>20)return;if(diffX>70||(diffX>10&&Date.now()-startTime.current<200))toRight();}else{if(!toLeft||getAbsAngle(diffX,pageY)<160)return;if(diffX<-70||(diffX<-10&&Date.now()-startTime.current<200))toLeft();}},[disable,getAbsAngle,toLeft,toRight],);return{ onTouchStart, onTouchEnd};};
小程序原生的下拉加载也不错,但不够特别。FUTAKE 实现了毛玻璃下拉加载效果:
GIF 较模糊,强烈建议体验小程序的实际效果。
同样是监听 touch 事件,但实现更复杂一些,需要根据偏移,处理毛玻璃的模糊度,以及触发 loading 动画等。
在 React 中使用时,要注意将 loading 元素隔离开来,因为 loading 元素是不断 re-render 的。
完整代码 →github.com/nanxiaobei/taro-ux-kits/tree/main/blur-loading
▶ 点击查看代码
// 部分核心代码(省略了相关组件)constSTART=40;constEND=100;constuseBlurLoading=({ hasTabBar})=>{const[blur,setBlur]=useState(0);const[dots,setDots]=useState(false);constblurStyle=useMemo(()=>{if(blur<START)returnundefined;return{'--blur':`blur(${Math.floor((blur-START)/3)}px)`};},[blur]);conststartLoading=useCallback((reqFn)=>{setBlur(60);setDots(true);constonEnd=()=>{setTimeout(()=>{setBlur(0);setDots(false);},300);};reqFn().then(shakePhone).finally(onEnd);},[]);constdiffY=useRef(0);constmaxDiffY=useRef(0);consthasLoading=useRef(false);consthasReq=useRef(false);constreqRef=useRef(null);// changeconstonTouchMoveChange=useCallback((absDiffY,onReq)=>{if(absDiffY<START||absDiffY>END+20)return;// 记录 diffYdiffY.current=absDiffY;if(absDiffY>maxDiffY.current)maxDiffY.current=absDiffY;// 记录请求函数if(!reqRef.current)reqRef.current=onReq;// 显示 blurrequestAnimationFrame(()=>setBlur(absDiffY));// 显示 dots 动画if(!hasLoading.current&&absDiffY>END){hasLoading.current=true;setDots(true);shakePhone();return;}// 若未触发请求,停止 dots 动画if(hasLoading.current&&absDiffY<END&&!hasReq.current){hasLoading.current=false;setDots(false);}},[]);// endconstonTouchEnd=useCallback(()=>{if(!reqRef.current)return;// 应触发请求constshouldReq=hasLoading.current&&Math.abs(diffY.current-maxDiffY.current)<5;if(shouldReq){// 发送请求hasReq.current=true;reqRef.current().finally(()=>{setTimeout(()=>{hasReq.current=false;hasLoading.current=false;setDots(false);setBlur(0);diffY.current=0;maxDiffY.current=0;reqRef.current=null;},300);});return;}// 不触发请求setTimeout(()=>{setBlur(0);diffY.current=0;maxDiffY.current=0;},200);},[setBlur,setDots]);constloadingEl=blur>0&&(<BlurLoadingdots={dots}blurStyle={blurStyle}hasTabBar={hasTabBar}/>);return{ loadingEl, startLoading, onTouchMoveChange, onTouchEnd};};
FUTAKE 使用 Swiper 组件,实现了类似抖音的上下滑动浏览。
但随着列表元素不断增加,小程序将变得卡顿,因为需要实现列表数据的动态化。
展示正在浏览的条目以及前后预载入条目,其它条目展示空元素占位即可。
完整代码 →github.com/nanxiaobei/taro-ux-kits/tree/main/use-dynamic-list
▶ 点击查看代码
// React Hooks(省略了工具函数)exportconstuseDynamicList=(list,index,count=5)=>{returnuseMemo(()=>{constlen=list.length;if(len<=count)returnlist;const[before,after]=splitCount(count);letstart=index-before;letend=index+after;if(start<0)start=0;if(end>len-1)end=len-1;constres=[...Array(len)];for(leti=start;i<=end;i++){res[i]=list[i];}returnres;},[index,count,list]);};
FUTAKE 实现了类似 Instagram 的对图片双击即可点赞的效果。
同时增加了「喜欢」展示红色 ❤️,「取消喜欢」展示白色 🤍 的逻辑。
完整代码 →github.com/nanxiaobei/taro-ux-kits/tree/main/double-click-like
▶ 点击查看代码
constLikeWrapper=({ isLiked, likeRequest})=>{constprevTime=useRef(0);const[iconVisible,setIconVisible]=useState(false);const[isRed,setIsRed]=useState(!isLiked);// 双击喜欢constonClick=useCallback(async(event)=>{conststartTime=event.timeStamp;if(startTime-prevTime.current<300){if(iconVisible)return;setIsRed(!isLiked);setIconVisible(true);likeRequest({ isLiked}).finally(()=>{consttimeLeft=550-(Date.now()-startTime);consthideIcon=()=>setIconVisible(false);timeLeft>0 ?setTimeout(hideIcon,timeLeft) :hideIcon();});}prevTime.current=startTime;},[iconVisible,isLiked,likeRequest],);return(<ViewclassName="like-wrapper"onClick={onClick}>{iconVisible&&<LikeIconisRed={isRed}/>}</View>);};
About
📮 Taro 小程序的用户体验优化 × 7
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.

