diff --git a/dist/custom-tab-bar/index.js b/dist/custom-tab-bar/index.js index 9325712..5086f31 100644 --- a/dist/custom-tab-bar/index.js +++ b/dist/custom-tab-bar/index.js @@ -1 +1 @@ -"use strict";(wx["webpackJsonp"]=wx["webpackJsonp"]||[]).push([[777],{653:function(e,n,t){var a=t(7842),c=t(5544),i=t(118),s=t(758),o=t.n(s),r=t(6540),u=t(1457),f=t(9703),g=t(6606),h=t(8199),l=t(4848),v=[{pagePath:"/pages/index/index",label:"\u9996\u9875",icon:(0,h.uq)("/icon/\u9996\u9875.svg"),iconActive:(0,h.uq)("/icon/\u9996\u9875-fill.svg")},{pagePath:"/pages/shop/index",label:"\u5546\u54c1",icon:(0,h.uq)("/icon/\u5546\u54c1.svg"),iconActive:(0,h.uq)("/icon/\u5546\u54c1-fill.svg")},{pagePath:"/pages/designList/index",label:"\u8bbe\u8ba1\u6e05\u5355",icon:(0,h.uq)("/icon/\u8c03\u8272\u76d8.svg"),iconActive:(0,h.uq)("/icon/\u8c03\u8272\u76d8-fill.svg")},{pagePath:"/pages/orders/index",label:"\u8ba2\u5355",icon:(0,h.uq)("/icon/\u5305\u88f9.svg"),iconActive:(0,h.uq)("/icon/\u5305\u88f9-fill.svg")},{pagePath:"/pages/profile/index",label:"\u6211\u7684",icon:(0,h.uq)("/icon/\u4e2a\u4eba.svg"),iconActive:(0,h.uq)("/icon/\u4e2a\u4eba-fill.svg")}];function p(e){var n=v.findIndex(function(n){return e.endsWith(n.pagePath)});return v[n>=0?n:0].pagePath}function b(){var e=o().getCurrentInstance().router,n=e&&e.path?e.path:"pages/index/index";return p(n)}function m(){var e=(0,r.useState)((0,u.eW)((0,u.O4)())),n=(0,c.A)(e,2),t=n[0],a=n[1],s=(0,r.useState)(b),h=(0,c.A)(s,2),m=h[0],d=h[1];(0,r.useEffect)(function(){var e=function(e){return a(e)};return o().eventCenter.on(f.Wo,e),function(){o().eventCenter.off(f.Wo,e)}},[]),(0,r.useEffect)(function(){var e=function(e){!e||"dark"!==e.theme&&"light"!==e.theme||((0,u.Rq)(e.theme),"auto"===(0,u.O4)()&&a(e.theme))},n=o();return n.onThemeChange&&n.onThemeChange(e),function(){n.offThemeChange&&n.offThemeChange(e)}},[]),(0,r.useEffect)(function(){var e=function(e){var n=o().getCurrentInstance().router,t=n&&n.path?n.path:"pages/index/index";d(p(e||t))};return o().eventCenter.on("tabBarChange",e),function(){o().eventCenter.off("tabBarChange",e)}},[]),(0,r.useEffect)(function(){(0,g.G)(t)},[t]);var x=function(e){d(p(e)),o().switchTab({url:e}),o().eventCenter.trigger("tabBarChange",e)};return(0,l.jsxs)(i.Ss,{className:"tab-bar-root theme-".concat(t),children:[(0,l.jsx)(i.Ss,{className:"tab-bar-gradient"}),(0,l.jsxs)(i.Ss,{className:"custom-tab-bar theme-".concat(t),children:[(0,l.jsx)(i.Ss,{className:"tab-bar-caustic"}),(0,l.jsx)(i.Ss,{className:"tab-bar-rim"}),v.map(function(e){var n=e.pagePath===m;return(0,l.jsxs)(i.Ss,{className:"tab-item ".concat(n?"active":""),onTap:function(){return x(e.pagePath)},children:[n&&(0,l.jsx)(i.Ss,{className:"tab-indicator"}),(0,l.jsx)(i._V,{className:"tab-icon-img ".concat(n?"active":""),src:n?e.iconActive:e.icon,mode:"aspectFit"}),(0,l.jsx)(i.EY,{className:"tab-label",children:e.label})]},e.pagePath)})]})]})}Component((0,a.createComponentConfig)(m,"custom-tab-bar/index"))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[907,96,76],function(){return n(653)});e.O()}]); \ No newline at end of file +"use strict";(wx["webpackJsonp"]=wx["webpackJsonp"]||[]).push([[777],{7914:function(n,e,t){var a=t(7842),c=t(5544),i=t(118),r=t(758),u=t.n(r),o=t(6540),s=t(1457),l=t(9703),f=t(6606),h=t(8199);function g(n,e,t){return Number.isFinite(n)?Math.min(t,Math.max(e,n)):e}function v(n,e){return g(n,0,Math.max(0,e))}function m(n,e,t){if(!Number.isFinite(n)||!Number.isFinite(e)||e<=0||t<=0)return 0;var a=v(n,e)/e;return g(Math.floor(a*t),0,t-1)}function p(n){var e=n/750;return{left:36*e,width:Math.max(0,n-72*e)}}var d=t(4848),b=[{pagePath:"/pages/index/index",label:"\u9996\u9875",icon:(0,h.uq)("/icon/\u9996\u9875.svg"),iconActive:(0,h.uq)("/icon/\u9996\u9875-fill.svg")},{pagePath:"/pages/shop/index",label:"\u5546\u54c1",icon:(0,h.uq)("/icon/\u5546\u54c1.svg"),iconActive:(0,h.uq)("/icon/\u5546\u54c1-fill.svg")},{pagePath:"/pages/designList/index",label:"\u8bbe\u8ba1\u6e05\u5355",icon:(0,h.uq)("/icon/\u8c03\u8272\u76d8.svg"),iconActive:(0,h.uq)("/icon/\u8c03\u8272\u76d8-fill.svg")},{pagePath:"/pages/orders/index",label:"\u8ba2\u5355",icon:(0,h.uq)("/icon/\u5305\u88f9.svg"),iconActive:(0,h.uq)("/icon/\u5305\u88f9-fill.svg")},{pagePath:"/pages/profile/index",label:"\u6211\u7684",icon:(0,h.uq)("/icon/\u4e2a\u4eba.svg"),iconActive:(0,h.uq)("/icon/\u4e2a\u4eba-fill.svg")}],x=100/b.length;function C(n){var e=b.findIndex(function(e){return n.endsWith(e.pagePath)});return b[e>=0?e:0].pagePath}function S(){var n=u().getCurrentInstance().router,e=n&&n.path?n.path:"pages/index/index";return C(e)}function N(){var n=(0,o.useState)((0,s.eW)((0,s.O4)())),e=(0,c.A)(n,2),t=e[0],a=e[1],r=(0,o.useState)(S),h=(0,c.A)(r,2),g=h[0],N=h[1],P=(0,o.useState)(null),q=(0,c.A)(P,2),w=q[0],j=q[1],A=(0,o.useRef)(null),T=(0,o.useRef)(null);(0,o.useEffect)(function(){var n=function(n){return a(n)};return u().eventCenter.on(l.Wo,n),function(){u().eventCenter.off(l.Wo,n)}},[]),(0,o.useEffect)(function(){var n=function(n){!n||"dark"!==n.theme&&"light"!==n.theme||((0,s.Rq)(n.theme),"auto"===(0,s.O4)()&&a(n.theme))},e=u();return e.onThemeChange&&e.onThemeChange(n),function(){e.offThemeChange&&e.offThemeChange(n)}},[]),(0,o.useEffect)(function(){var n=function(n){var e=u().getCurrentInstance().router,t=e&&e.path?e.path:"pages/index/index";N(C(n||t))};return u().eventCenter.on("tabBarChange",n),function(){u().eventCenter.off("tabBarChange",n)}},[]),(0,o.useEffect)(function(){(0,f.G)(t)},[t]);var M=function(n){N(C(n)),u().switchTab({url:n}),u().eventCenter.trigger("tabBarChange",n)},E=function(n){var e=n.touches&&n.touches[0];if(e){var t=p(u().getSystemInfoSync().windowWidth);T.current=t;var a=v(e.clientX-t.left,t.width);A.current=a,j(a)}},I=function(n){if(null!==A.current){var e=T.current,t=n.touches&&n.touches[0];if(e&&t){var a=v(t.clientX-e.left,e.width);A.current=a,j(a)}}},W=function(){var n=T.current,e=A.current;if(n&&null!==e){var t=m(e,n.width,b.length),a=b[t];a&&a.pagePath!==g&&M(a.pagePath)}T.current=null,A.current=null,j(null)},F=function(){T.current=null,A.current=null,j(null)},O=Math.max(0,b.findIndex(function(n){return n.pagePath===g}));return(0,d.jsxs)(i.Ss,{className:"tab-bar-root theme-".concat(t),children:[(0,d.jsx)(i.Ss,{className:"tab-bar-gradient"}),(0,d.jsxs)(i.Ss,{className:"custom-tab-bar theme-".concat(t),onTouchStart:E,onTouchMove:I,onTouchEnd:W,onTouchCancel:F,catchMove:!0,children:[(0,d.jsx)(i.Ss,{className:"tab-bar-caustic"}),(0,d.jsx)(i.Ss,{className:"tab-bar-rim"}),(0,d.jsx)(i.Ss,{className:"tab-indicator ".concat(null!==w?"dragging":""),style:{left:null===w?"calc(".concat((O+.5)*x,"%)"):"".concat(w,"px")}}),b.map(function(n){var e=n.pagePath===g;return(0,d.jsxs)(i.Ss,{className:"tab-item ".concat(e?"active":""),children:[(0,d.jsx)(i._V,{className:"tab-icon-img ".concat(e?"active":""),src:e?n.iconActive:n.icon,mode:"aspectFit"}),(0,d.jsx)(i.EY,{className:"tab-label",children:n.label})]},n.pagePath)})]})]})}Component((0,a.createComponentConfig)(N,"custom-tab-bar/index"))}},function(n){var e=function(e){return n(n.s=e)};n.O(0,[907,96,76],function(){return e(7914)});n.O()}]); \ No newline at end of file diff --git a/dist/custom-tab-bar/index.wxss b/dist/custom-tab-bar/index.wxss index 4277300..7da6a96 100644 --- a/dist/custom-tab-bar/index.wxss +++ b/dist/custom-tab-bar/index.wxss @@ -1 +1 @@ -.tab-bar-root{bottom:0;height:160rpx;left:0;pointer-events:none;position:fixed;right:0;z-index:999}.tab-bar-gradient{bottom:0;height:100%;left:0;position:absolute;right:0}.tab-bar-root.theme-light .tab-bar-gradient{background:-webkit-gradient(linear,left bottom,left top,from(hsla(38,44%,96%,.5)),color-stop(50%,hsla(38,44%,96%,.1)),color-stop(86%,hsla(38,44%,96%,0)));background:-webkit-linear-gradient(bottom,hsla(38,44%,96%,.5),hsla(38,44%,96%,.1) 50%,hsla(38,44%,96%,0) 86%);background:linear-gradient(0deg,hsla(38,44%,96%,.5) 0,hsla(38,44%,96%,.1) 50%,hsla(38,44%,96%,0) 86%)}.tab-bar-root.theme-dark .tab-bar-gradient{background:-webkit-gradient(linear,left bottom,left top,from(rgba(25,25,25,.5)),color-stop(50%,rgba(25,25,25,.1)),color-stop(86%,rgba(25,25,25,0)));background:-webkit-linear-gradient(bottom,rgba(25,25,25,.5),rgba(25,25,25,.1) 50%,rgba(25,25,25,0) 86%);background:linear-gradient(0deg,rgba(25,25,25,.5) 0,rgba(25,25,25,.1) 50%,rgba(25,25,25,0) 86%)}.custom-tab-bar{-ms-flex-pack:distribute;-ms-flex-align:center;-webkit-align-items:center;align-items:center;backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);-webkit-backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);background:hsla(0,0%,100%,.32);border:1rpx solid hsla(0,0%,100%,.14);border-radius:64rpx;bottom:36rpx;-webkit-box-shadow:0 24rpx 60rpx rgba(20,14,10,.22),0 4rpx 12rpx rgba(0,0,0,.08),inset 0 2rpx 0 hsla(0,0%,100%,.35);box-shadow:0 24rpx 60rpx rgba(20,14,10,.22),0 4rpx 12rpx rgba(0,0,0,.08),inset 0 2rpx 0 hsla(0,0%,100%,.35);-webkit-box-sizing:border-box;box-sizing:border-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:116rpx;-webkit-justify-content:space-around;justify-content:space-around;left:36rpx;overflow:hidden;pointer-events:auto;position:absolute;right:36rpx;z-index:1000}.custom-tab-bar.theme-dark{backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);-webkit-backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);background:rgba(25,25,25,.32);border-color:hsla(0,0%,100%,.1);-webkit-box-shadow:0 24rpx 60rpx rgba(0,0,0,.55),0 4rpx 12rpx rgba(0,0,0,.3),inset 0 2rpx 0 hsla(0,0%,100%,.12);box-shadow:0 24rpx 60rpx rgba(0,0,0,.55),0 4rpx 12rpx rgba(0,0,0,.3),inset 0 2rpx 0 hsla(0,0%,100%,.12)}.tab-bar-caustic{background:-webkit-gradient(linear,left top,left bottom,from(hsla(0,0%,100%,.32)),to(hsla(0,0%,100%,0)));background:-webkit-linear-gradient(top,hsla(0,0%,100%,.32),hsla(0,0%,100%,0));background:linear-gradient(180deg,hsla(0,0%,100%,.32),hsla(0,0%,100%,0));border-radius:64rpx 64rpx 0 0;-webkit-box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.55);box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.55);height:56rpx;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:2}.custom-tab-bar.theme-dark .tab-bar-caustic{background:-webkit-gradient(linear,left top,left bottom,from(hsla(0,0%,100%,.12)),to(hsla(0,0%,100%,0)));background:-webkit-linear-gradient(top,hsla(0,0%,100%,.12),hsla(0,0%,100%,0));background:linear-gradient(180deg,hsla(0,0%,100%,.12),hsla(0,0%,100%,0));-webkit-box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.22);box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.22)}.tab-bar-rim{background:-webkit-linear-gradient(315deg,hsla(0,0%,100%,.6),hsla(0,0%,100%,.18) 32%,hsla(0,0%,100%,.03) 68%,hsla(0,0%,100%,.24));background:linear-gradient(135deg,hsla(0,0%,100%,.6),hsla(0,0%,100%,.18) 32%,hsla(0,0%,100%,.03) 68%,hsla(0,0%,100%,.24));border-radius:inherit;bottom:0;left:0;-webkit-mask:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff)) content-box,-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff));-webkit-mask:-webkit-linear-gradient(#fff 0 0) content-box,-webkit-linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;padding:1rpx;pointer-events:none;position:absolute;right:0;top:0;z-index:3}.custom-tab-bar.theme-dark .tab-bar-rim{background:-webkit-linear-gradient(315deg,hsla(0,0%,100%,.34),hsla(0,0%,100%,.12) 32%,hsla(0,0%,100%,.02) 68%,hsla(0,0%,100%,.16));background:linear-gradient(135deg,hsla(0,0%,100%,.34),hsla(0,0%,100%,.12) 32%,hsla(0,0%,100%,.02) 68%,hsla(0,0%,100%,.16))}.tab-item{-ms-flex-align:center;-ms-flex-pack:center;-webkit-align-items:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-justify-content:center;justify-content:center;max-width:160rpx;padding:0 12rpx;position:relative;z-index:10}.tab-indicator{background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.1)),to(rgba(0,0,0,.16)));background:-webkit-linear-gradient(top,rgba(0,0,0,.1),rgba(0,0,0,.16));background:linear-gradient(180deg,rgba(0,0,0,.1),rgba(0,0,0,.16));border:1rpx solid hsla(0,0%,100%,.25);border-radius:50rpx;bottom:6rpx;-webkit-box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.35),inset 0 -2rpx 4rpx rgba(0,0,0,.06),0 4rpx 10rpx rgba(0,0,0,.08);box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.35),inset 0 -2rpx 4rpx rgba(0,0,0,.06),0 4rpx 10rpx rgba(0,0,0,.08);height:100rpx;left:50%;position:absolute;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:120rpx}.custom-tab-bar.theme-dark .tab-indicator{background:-webkit-gradient(linear,left top,left bottom,from(hsla(0,0%,100%,.08)),to(hsla(0,0%,100%,.16)));background:-webkit-linear-gradient(top,hsla(0,0%,100%,.08),hsla(0,0%,100%,.16));background:linear-gradient(180deg,hsla(0,0%,100%,.08),hsla(0,0%,100%,.16));border-color:hsla(0,0%,100%,.18);-webkit-box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.12),inset 0 -2rpx 4rpx rgba(0,0,0,.3),0 4rpx 10rpx rgba(0,0,0,.2);box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.12),inset 0 -2rpx 4rpx rgba(0,0,0,.3),0 4rpx 10rpx rgba(0,0,0,.2)}.tab-icon-img{height:40rpx;margin-bottom:2rpx;opacity:.8;position:relative;-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s;width:40rpx;z-index:1}.tab-item.active .tab-icon-img{opacity:1;-webkit-transform:scale(1.08);-ms-transform:scale(1.08);transform:scale(1.08)}.tab-label{color:#8a7e76;font-size:20rpx;font-weight:700;line-height:22rpx;position:relative;-webkit-transition:color .2s;transition:color .2s;z-index:1}.custom-tab-bar.theme-dark .tab-label{color:#b3a79c}.tab-item.active .tab-label{color:#d96c6a}.custom-tab-bar.theme-dark .tab-item.active .tab-label{color:#f09198} \ No newline at end of file +.tab-bar-root{bottom:0;height:160rpx;left:0;pointer-events:none;position:fixed;right:0;z-index:999}.tab-bar-gradient{bottom:0;height:100%;left:0;position:absolute;right:0}.tab-bar-root.theme-light .tab-bar-gradient{background:-webkit-gradient(linear,left bottom,left top,from(hsla(38,44%,96%,.5)),color-stop(50%,hsla(38,44%,96%,.1)),color-stop(86%,hsla(38,44%,96%,0)));background:-webkit-linear-gradient(bottom,hsla(38,44%,96%,.5),hsla(38,44%,96%,.1) 50%,hsla(38,44%,96%,0) 86%);background:linear-gradient(0deg,hsla(38,44%,96%,.5) 0,hsla(38,44%,96%,.1) 50%,hsla(38,44%,96%,0) 86%)}.tab-bar-root.theme-dark .tab-bar-gradient{background:-webkit-gradient(linear,left bottom,left top,from(rgba(25,25,25,.5)),color-stop(50%,rgba(25,25,25,.1)),color-stop(86%,rgba(25,25,25,0)));background:-webkit-linear-gradient(bottom,rgba(25,25,25,.5),rgba(25,25,25,.1) 50%,rgba(25,25,25,0) 86%);background:linear-gradient(0deg,rgba(25,25,25,.5) 0,rgba(25,25,25,.1) 50%,rgba(25,25,25,0) 86%)}.custom-tab-bar{-ms-flex-pack:distribute;-ms-flex-align:center;-webkit-align-items:center;align-items:center;backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);-webkit-backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);background:hsla(0,0%,100%,.24);border:1rpx solid hsla(0,0%,100%,.14);border-radius:64rpx;bottom:36rpx;-webkit-box-shadow:0 24rpx 60rpx rgba(20,14,10,.22),0 4rpx 12rpx rgba(0,0,0,.08),inset 0 2rpx 0 hsla(0,0%,100%,.35);box-shadow:0 24rpx 60rpx rgba(20,14,10,.22),0 4rpx 12rpx rgba(0,0,0,.08),inset 0 2rpx 0 hsla(0,0%,100%,.35);-webkit-box-sizing:border-box;box-sizing:border-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:116rpx;-webkit-justify-content:space-around;justify-content:space-around;left:36rpx;overflow:hidden;pointer-events:auto;position:absolute;right:36rpx;z-index:1000}.custom-tab-bar.theme-dark{backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);-webkit-backdrop-filter:blur(32rpx) saturate(1.7) brightness(1.05);background:rgba(25,25,25,.24);border-color:hsla(0,0%,100%,.1);-webkit-box-shadow:0 24rpx 60rpx rgba(0,0,0,.55),0 4rpx 12rpx rgba(0,0,0,.3),inset 0 2rpx 0 hsla(0,0%,100%,.12);box-shadow:0 24rpx 60rpx rgba(0,0,0,.55),0 4rpx 12rpx rgba(0,0,0,.3),inset 0 2rpx 0 hsla(0,0%,100%,.12)}.tab-bar-caustic{background:-webkit-gradient(linear,left top,left bottom,from(hsla(0,0%,100%,.32)),to(hsla(0,0%,100%,0)));background:-webkit-linear-gradient(top,hsla(0,0%,100%,.32),hsla(0,0%,100%,0));background:linear-gradient(180deg,hsla(0,0%,100%,.32),hsla(0,0%,100%,0));border-radius:64rpx 64rpx 0 0;-webkit-box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.55);box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.55);height:56rpx;left:0;pointer-events:none;position:absolute;right:0;top:0;z-index:2}.custom-tab-bar.theme-dark .tab-bar-caustic{background:-webkit-gradient(linear,left top,left bottom,from(hsla(0,0%,100%,.12)),to(hsla(0,0%,100%,0)));background:-webkit-linear-gradient(top,hsla(0,0%,100%,.12),hsla(0,0%,100%,0));background:linear-gradient(180deg,hsla(0,0%,100%,.12),hsla(0,0%,100%,0));-webkit-box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.22);box-shadow:inset 0 1rpx 0 hsla(0,0%,100%,.22)}.tab-bar-rim{background:-webkit-linear-gradient(315deg,hsla(0,0%,100%,.6),hsla(0,0%,100%,.18) 32%,hsla(0,0%,100%,.03) 68%,hsla(0,0%,100%,.24));background:linear-gradient(135deg,hsla(0,0%,100%,.6),hsla(0,0%,100%,.18) 32%,hsla(0,0%,100%,.03) 68%,hsla(0,0%,100%,.24));border-radius:inherit;bottom:0;left:0;-webkit-mask:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff)) content-box,-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff));-webkit-mask:-webkit-linear-gradient(#fff 0 0) content-box,-webkit-linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;padding:1rpx;pointer-events:none;position:absolute;right:0;top:0;z-index:3}.custom-tab-bar.theme-dark .tab-bar-rim{background:-webkit-linear-gradient(315deg,hsla(0,0%,100%,.34),hsla(0,0%,100%,.12) 32%,hsla(0,0%,100%,.02) 68%,hsla(0,0%,100%,.16));background:linear-gradient(135deg,hsla(0,0%,100%,.34),hsla(0,0%,100%,.12) 32%,hsla(0,0%,100%,.02) 68%,hsla(0,0%,100%,.16))}.tab-item{-ms-flex-align:center;-ms-flex-pack:center;-webkit-align-items:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:100%;-webkit-justify-content:center;justify-content:center;max-width:160rpx;padding:0 12rpx;position:relative;z-index:10}.tab-indicator{background:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.1)),to(rgba(0,0,0,.16)));background:-webkit-linear-gradient(top,rgba(0,0,0,.1),rgba(0,0,0,.16));background:linear-gradient(180deg,rgba(0,0,0,.1),rgba(0,0,0,.16));border:1rpx solid hsla(0,0%,100%,.25);border-radius:50rpx;bottom:6rpx;-webkit-box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.35),inset 0 -2rpx 4rpx rgba(0,0,0,.06),0 4rpx 10rpx rgba(0,0,0,.08);box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.35),inset 0 -2rpx 4rpx rgba(0,0,0,.06),0 4rpx 10rpx rgba(0,0,0,.08);height:100rpx;pointer-events:none;position:absolute;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);-webkit-transition:left .25s ease;transition:left .25s ease;width:120rpx;z-index:4}.custom-tab-bar.theme-dark .tab-indicator{background:-webkit-gradient(linear,left top,left bottom,from(hsla(0,0%,100%,.08)),to(hsla(0,0%,100%,.16)));background:-webkit-linear-gradient(top,hsla(0,0%,100%,.08),hsla(0,0%,100%,.16));background:linear-gradient(180deg,hsla(0,0%,100%,.08),hsla(0,0%,100%,.16));border-color:hsla(0,0%,100%,.18);-webkit-box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.12),inset 0 -2rpx 4rpx rgba(0,0,0,.3),0 4rpx 10rpx rgba(0,0,0,.2);box-shadow:inset 0 2rpx 4rpx hsla(0,0%,100%,.12),inset 0 -2rpx 4rpx rgba(0,0,0,.3),0 4rpx 10rpx rgba(0,0,0,.2)}.tab-indicator.dragging{-webkit-transition:none;transition:none}.tab-icon-img{height:40rpx;margin-bottom:2rpx;opacity:.8;position:relative;-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s;width:40rpx;z-index:1}.tab-item.active .tab-icon-img{opacity:1;-webkit-transform:scale(1.08);-ms-transform:scale(1.08);transform:scale(1.08)}.tab-label{color:#8a7e76;font-size:20rpx;font-weight:700;line-height:22rpx;position:relative;-webkit-transition:color .2s;transition:color .2s;z-index:1}.custom-tab-bar.theme-dark .tab-label{color:#b3a79c}.tab-item.active .tab-label{color:#d96c6a}.custom-tab-bar.theme-dark .tab-item.active .tab-label{color:#f09198} \ No newline at end of file diff --git a/src/custom-tab-bar/index.scss b/src/custom-tab-bar/index.scss index 5f36f06..5664525 100644 --- a/src/custom-tab-bar/index.scss +++ b/src/custom-tab-bar/index.scss @@ -33,7 +33,7 @@ height: 116rpx; box-sizing: border-box; overflow: hidden; - background: rgba(255, 255, 255, 0.32); + background: rgba(255, 255, 255, 0.24); backdrop-filter: blur(32px) saturate(1.7) brightness(1.05); -webkit-backdrop-filter: blur(32px) saturate(1.7) brightness(1.05); display: flex; @@ -50,7 +50,7 @@ /* 自定义组件样式隔离:两套主题配色在组件内自包含,不依赖全局 app.wxss */ .custom-tab-bar.theme-dark { - background: rgba(25, 25, 25, 0.32); + background: rgba(25, 25, 25, 0.24); backdrop-filter: blur(32px) saturate(1.7) brightness(1.05); -webkit-backdrop-filter: blur(32px) saturate(1.7) brightness(1.05); border-color: rgba(255, 255, 255, 0.1); @@ -127,12 +127,14 @@ .tab-indicator { position: absolute; - left: 50%; transform: translateX(-50%); bottom: 6rpx; width: 120rpx; height: 100rpx; border-radius: 50rpx; + pointer-events: none; + z-index: 4; + transition: left 0.25s ease; background: linear-gradient(180deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.16)); border: 1rpx solid rgba(255, 255, 255, 0.25); box-shadow: @@ -150,6 +152,10 @@ 0 4rpx 10rpx rgba(0, 0, 0, 0.2); } +.tab-indicator.dragging { + transition: none; +} + .tab-icon-img { position: relative; z-index: 1; diff --git a/src/custom-tab-bar/index.tsx b/src/custom-tab-bar/index.tsx index b059d98..238ba44 100644 --- a/src/custom-tab-bar/index.tsx +++ b/src/custom-tab-bar/index.tsx @@ -1,10 +1,11 @@ import { View, Text, Image } from '@tarojs/components' import Taro from '@tarojs/taro' -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { getTheme, resolveTheme, setDetectedSystemTheme } from '../utils/store' import { THEME_CHANGE_EVENT } from '../context/ThemeContext' import { applyPageBackground } from '../utils/themeBackground' import { assetUrl } from '../utils/asset' +import { clampDragX, getTabBarFrame, tabIndexAtX } from './tabBarGeometry' import './index.scss' const TABS = [ @@ -15,6 +16,8 @@ const TABS = [ { pagePath: '/pages/profile/index', label: '我的', icon: assetUrl('/icon/个人.svg'), iconActive: assetUrl('/icon/个人-fill.svg') } ] +const TAB_CENTER_STEP = 100 / TABS.length + function matchTab(path: string): string { const idx = TABS.findIndex((t) => path.endsWith(t.pagePath)) return TABS[idx >= 0 ? idx : 0].pagePath @@ -36,6 +39,9 @@ export default function CustomTabBar() { // 微信自定义 tabBar 不会自动感知 page 路由变化,用 state 保持选中态响应式 const [activeTab, setActiveTab] = useState(currentTabPath) + const [dragX, setDragX] = useState(null) + const dragXRef = useRef(null) + const barFrameRef = useRef<{ left: number; width: number } | null>(null) useEffect(() => { const handler = (t: 'light' | 'dark') => setResolvedTheme(t) @@ -91,21 +97,68 @@ export default function CustomTabBar() { Taro.eventCenter.trigger('tabBarChange', url) } + const startDrag = (e: any) => { + const touch = e.touches && e.touches[0] + if (!touch) return + const frame = getTabBarFrame(Taro.getSystemInfoSync().windowWidth) + barFrameRef.current = frame + const nextX = clampDragX(touch.clientX - frame.left, frame.width) + dragXRef.current = nextX + setDragX(nextX) + } + + const moveDrag = (e: any) => { + if (dragXRef.current === null) return + const frame = barFrameRef.current + const touch = e.touches && e.touches[0] + if (!frame || !touch) return + const nextX = clampDragX(touch.clientX - frame.left, frame.width) + dragXRef.current = nextX + setDragX(nextX) + } + + const endDrag = () => { + const frame = barFrameRef.current + const x = dragXRef.current + if (frame && x !== null) { + const idx = tabIndexAtX(x, frame.width, TABS.length) + const target = TABS[idx] + if (target && target.pagePath !== activeTab) switchTab(target.pagePath) + } + barFrameRef.current = null + dragXRef.current = null + setDragX(null) + } + + const cancelDrag = () => { + barFrameRef.current = null + dragXRef.current = null + setDragX(null) + } + + const activeIndex = Math.max(0, TABS.findIndex((t) => t.pagePath === activeTab)) + return ( - + + {TABS.map((tab) => { const isActive = tab.pagePath === activeTab return ( - switchTab(tab.pagePath)} - > - {isActive && } + {tab.label} diff --git a/src/custom-tab-bar/tabBarGeometry.js b/src/custom-tab-bar/tabBarGeometry.js new file mode 100644 index 0000000..fb35e3a --- /dev/null +++ b/src/custom-tab-bar/tabBarGeometry.js @@ -0,0 +1,21 @@ +export function clamp(value, min, max) { + if (!Number.isFinite(value)) return min + return Math.min(max, Math.max(min, value)) +} + +export function clampDragX(x, barWidth) { + return clamp(x, 0, Math.max(0, barWidth)) +} + +export function tabIndexAtX(x, barWidth, tabCount) { + if (!Number.isFinite(x) || !Number.isFinite(barWidth) || barWidth <= 0 || tabCount <= 0) { + return 0 + } + const ratio = clampDragX(x, barWidth) / barWidth + return clamp(Math.floor(ratio * tabCount), 0, tabCount - 1) +} + +export function getTabBarFrame(windowWidth) { + const rpx = windowWidth / 750 + return { left: 36 * rpx, width: Math.max(0, windowWidth - 72 * rpx) } +} diff --git a/tools/custom-tab-bar.test.mjs b/tools/custom-tab-bar.test.mjs new file mode 100644 index 0000000..bdf5c7b --- /dev/null +++ b/tools/custom-tab-bar.test.mjs @@ -0,0 +1,24 @@ +import test from 'node:test' +import assert from 'node:assert/strict' +import { clampDragX, getTabBarFrame, tabIndexAtX } from '../src/custom-tab-bar/tabBarGeometry.js' + +test('maps a drag x to the tab under the finger', () => { + assert.equal(tabIndexAtX(10, 100, 5), 0) + assert.equal(tabIndexAtX(30, 100, 5), 1) + assert.equal(tabIndexAtX(50, 100, 5), 2) + assert.equal(tabIndexAtX(70, 100, 5), 3) + assert.equal(tabIndexAtX(90, 100, 5), 4) +}) + +test('clamps drag positions outside the bar', () => { + assert.equal(tabIndexAtX(-10, 100, 5), 0) + assert.equal(tabIndexAtX(200, 100, 5), 4) + assert.equal(clampDragX(-5, 100), 0) + assert.equal(clampDragX(120, 100), 100) + assert.equal(clampDragX(Number.NaN, 100), 0) +}) + +test('derives the floating bar frame from window width', () => { + assert.deepEqual(getTabBarFrame(375), { left: 18, width: 339 }) + assert.deepEqual(getTabBarFrame(750), { left: 36, width: 678 }) +}) diff --git a/tools/liquid-glass.test.mjs b/tools/liquid-glass.test.mjs index 00a54c6..634a1ca 100644 --- a/tools/liquid-glass.test.mjs +++ b/tools/liquid-glass.test.mjs @@ -15,8 +15,8 @@ test('custom tab bar renders the liquid-glass overlay layers', () => { test('custom tab bar uses bright glass material and the silver rim', () => { const css = read('src/custom-tab-bar/index.scss') - assert.match(css, /background: rgba\(255, 255, 255, 0\.32\)/) - assert.match(css, /background: rgba\(25, 25, 25, 0\.32\)/) + assert.match(css, /background: rgba\(255, 255, 255, 0\.24\)/) + assert.match(css, /background: rgba\(25, 25, 25, 0\.24\)/) assert.match(css, /backdrop-filter: blur\(32px\) saturate\(1\.7\) brightness\(1\.05\)/) assert.match(css, /-webkit-backdrop-filter: blur\(32px\) saturate\(1\.7\) brightness\(1\.05\)/) assert.match(css, /mask-composite: exclude/)