Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 最近的最新的中文字幕在线,日韩精品第二页,久草精品在线观看

          整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          CSS設(shè)置網(wǎng)頁在Safari快速滾動和溫柔的回彈

          CSS設(shè)置網(wǎng)頁在Safari快速滾動和溫柔的回彈

          實現(xiàn)這個效果很簡單,只需要加一行css代碼即可:

          -webkit-overflow-scrolling : touch;

          可用以下網(wǎng)頁測試:

          <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
          <html>
              <head>
                  <meta charset="utf-8" />
                  <title>scroll</title>
                  <style type="text/css">
           .container {
           width : 300px;
           height : 50%;
           -webkit-box-sizing : border-box;
           position : relative;
           overflow-y : auto;
           background-color : cyan;
           -webkit-overflow-scrolling : touch;  /* liuhx:可以把這整行注釋掉對比差別 */
           }
           ul {
           height: 50px;
           }
                  </style>
              </head>
          <body>
              <div align="center">
                  <nav class="container">
           <ul>1</ul>
           <ul>2</ul>
           <ul>3</ul>
           <ul>4</ul>
           <ul>5</ul>
           <ul>6</ul>
           <ul>7</ul>
           <ul>8</ul>
           <ul>9</ul>
           <ul>10</ul>
           <ul>11</ul>
           <ul>12</ul>
           <ul>13</ul>
           <ul>14</ul>
           <ul>15</ul>
           <ul>16</ul>
           <ul>17</ul>
           <ul>18</ul>
           <ul>19</ul>
           <ul>20</ul>
                  </nav>
              </div>
          </body>
          </html>

          評論

          不久看到這樣一個很有趣的效果,它的滾動條是沿著圓角邊緣滾動的,效果如下

          你可以查看原鏈接來體驗一下

          https://codepen.io/jh3y/pen/gOEgxbd

          這是如何實現(xiàn)的呢?

          原效果中由于為了兼容不支持CSS滾動驅(qū)動的瀏覽器,特意用 JS做了兼容,所以看著比較復(fù)雜,其實核心非常簡單,下面我將用最簡短的 CSS 來復(fù)刻這一效果,一起看看吧

          一、SVG 路徑動畫

          從本質(zhì)上來講,其實是一個 SVG 路徑動畫。

          具體如何實現(xiàn)呢?

          首先,我們通過設(shè)計軟件繪制一個這樣的路徑

          注意設(shè)置描邊的大小還有端點的類型,比如下面是round效果

          然后導(dǎo)出SVG,可以得到這樣一段代碼

          <svg viewBox="0 0 31 433" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M4 4C9.96737 4 15.6903 6.37053 19.9099 10.5901C24.1295 14.8097 26.5 20.5326 26.5 26.5V406.5C26.5 412.467 24.1295 418.19 19.9099 422.41C15.6903 426.629 9.96737 429 4 429" stroke="black" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
          </svg>
          

          然后,如何讓這段SVG動起來呢?

          很簡單,現(xiàn)在SVG是一段實線,我們可以通過stroke-dasharray設(shè)置成虛線,比如

          path{
            stroke-dasharray: 80
          }
          

          這樣會得到一個實線和虛線間隔都是80的虛線

          如果希望虛線空白的地方更大一點,該怎么設(shè)置呢?很簡單,繼續(xù)往后加

          path{
            stroke-dasharray: 80 120
          }
          

          效果如下

          所以,這種寫法其實相當(dāng)于把當(dāng)前的值無限重復(fù),示意如下

          當(dāng)然,我們這里不需要設(shè)置的這么復(fù)雜,只需要一小段實線就夠了,所以是實現(xiàn)加上一段足夠長的虛線(超過路徑本身就行),實現(xiàn)如下

          path{
            stroke-dasharray: 80 1000
          }
          

          這樣就得到了一小段實線

          那么,如何讓他動起來呢?很簡單,改變一下偏移就可以,這個可以用stroke-dashoffset來實現(xiàn)

          比如,我們

          @keyframes scroll {
            to {
              stroke-dashoffset: -370
          	}
          }
          path{
            stroke-dasharray: 80 1000;
            animation: scroll 3s alternate-reverse infinite;
          }
          

          效果如下

          是不是有點像呢?

          我們再調(diào)整一下起始偏移量,讓它出去一點

          @keyframes scroll {
            0% { stroke-dashoffset: 75; }
            100% { stroke-dashoffset: -445; }
          }
          

          這樣就更接近我們想要的效果了

          整個運動原理就是這樣了,接著往下看

          二、CSS 滾動驅(qū)動動畫

          接下來需要通過滾動驅(qū)動動畫將容器滾動與CSS動畫「聯(lián)動」起來。

          關(guān)于CSS 滾動驅(qū)動可以參考我之前寫的這篇文章:CSS 滾動驅(qū)動動畫終于正式支持了~

          簡單來講,「CSS 滾動驅(qū)動動畫」指的是將「動畫的執(zhí)行過程由頁面滾動」進行接管,也就是這種情況下,「動畫只會跟隨頁面滾動的變化而變化」,也就是滾動多少,動畫就執(zhí)行多少,「時間不再起作用」

          先簡單布局一下

          <div class="list">
            <div class="item" id="item_1">1</div>
            <div class="item" id="item_2">2</div>
            <div class="item" id="item_3">3</div>
            <div class="item" id="item_4">4</div>
            <div class="item" id="item_5">5</div>
            <div class="item" id="item_6">6</div>
            <div class="item" id="item_7">7</div>
          </div>
          

          美化一下

          然后,我們將默認(rèn)的滾動條隱藏,用我們這個 SVG路徑來代替,由于需要絕對定位,我們再套一層父級

          <div class="wrap">
            <div class="list">
              <div class="item" id="item_1">1</div>
              <div class="item" id="item_2">2</div>
              <div class="item" id="item_3">3</div>
              <div class="item" id="item_4">4</div>
              <div class="item" id="item_5">5</div>
              <div class="item" id="item_6">6</div>
              <div class="item" id="item_7">7</div>
              <!--滾動條-->
              <svg class="scroller" viewBox="0 0 31 433" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path class="scroller_thumb" d="M4 4C9.96737 4 15.6903 6.37053 19.9099 10.5901C24.1295 14.8097 26.5 20.5326 26.5 26.5V406.5C26.5 412.467 24.1295 418.19 19.9099 422.41C15.6903 426.629 9.96737 429 4 429" stroke="black" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
              </svg>
            </div>
          </div>
          

          相關(guān)CSS如下

          .wrap{
            position: relative;
          }
          .scroller {
            position: absolute;
            top: 0;
            bottom: 0;
            right: 0;
            pointer-events: none;
            height: -webkit-fill-available;
            margin: 5px;
          }
          .scroller_thumb{
            stroke: hsl(0 0% 100% / 0.5);
            stroke-dasharray: 80 450;
            stroke-width: 8px;
            animation: scroll both 5s linear;
          }
          

          這樣結(jié)構(gòu)就搭好了,只是滾動條會自動播放

          接下來就是最關(guān)鍵的一步,加上滾動驅(qū)動動畫

          .scroller_thumb{
            animation: scroll both 5s linear;
            animation-timeline: scroll();
          }
          

          但是這樣是不起作用的,直接使用scroll()會自動尋找它的相對父級,也就是.wrap,但實際滾動的其實是.list,所以這種情況下我們需要具名的滾動時間線,實現(xiàn)如下

          .list{
            scroll-timeline: --scroller;
          }
          .scroller_thumb{
            animation: scroll both 5s linear;
            animation-timeline: --scroller;
          }
          

          這樣SVG路徑動畫就能跟隨容器滾動而運動了

          三、CSS 滾動吸附

          原效果中還有一個滾動回彈的效果,當(dāng)滾動到容器邊緣時,會自動回彈到起始位置。

          其實只需要用到 CSS scroll snap 就可以了

          https://developer.mozilla.org/zh-CN/docs/Web/CSS/scroll-snap-type

          實現(xiàn)很簡單,給滾動容器添加scroll-snap-type屬性,表示這是個允許滾動吸附的容器

          .list{
            scroll-snap-type: y mandatory;
          }
          

          然后就指定需要吸附的點了,由于需要回彈的效果,所以滾動容器的首尾需要一個空白的容器,這里直接用兩個偽元素來生成

          .list::before,
          .list::after{
            content: '';
            height: 50px;
            flex-shrink: 0;
          }
          

          效果如下

          然后我們設(shè)置滾動吸附點就行了,設(shè)置第一個元素頂部和最后一個元素底部,其他元素居中就行了

          .item{
            scroll-snap-align: center;
          }
          .item:first-child{
            scroll-snap-align: start;
          }
          /*最后一個元素是 SVG,所以這里用倒數(shù)第二個元素*/
          .item:nth-last-child(2){
            scroll-snap-align: end;
          }
          

          這樣就實現(xiàn)了文章開頭的效果了

          完整代碼可以查看以下鏈接(無任何 JS

          • CSS round scroll (juejin.cn)[1]
          • CSS round scroll (codepen.io)[2]

          四、總結(jié)一下

          總的來說,CSS滾動驅(qū)動在滾動交互上帶來了無限可能,很多以前必須借助 JS來實現(xiàn)的都可以輕易實現(xiàn),下面總結(jié)一下

          1. 從本質(zhì)上來講,右側(cè)的滾動條其實是一個 SVG 路徑動畫
          2. SVG路徑可以通過stroke-dasharray設(shè)置虛實間隔
          3. 當(dāng)虛線間隔足夠長時,超過路徑本身,就能得到一小塊實線
          4. 通過改變stroke-dashoffset偏移能夠?qū)崿F(xiàn)路徑描邊動畫
          5. 借助 CSS滾動驅(qū)動動畫可以將SVG路徑動畫跟隨容器滾動而運動
          6. 滾動回彈效果其實就是CSS scroll snap實現(xiàn)的

          作者:XboxYan

          來源:微信公眾號:前端偵探

          出處:https://mp.weixin.qq.com/s/GaakgWhXm6jpY4PfISNHZQ

          篇會深化View拖拽實例,利用Flutter Animation、插值器以及AnimatedBuilder教大家實現(xiàn)帶動畫的抽屜效果。先來看效果:



          通過構(gòu)思,我們可以設(shè)想到實現(xiàn)抽屜的方式就是用Stack控件將兩個Widget疊加顯示,用GestureDetector監(jiān)聽手勢滑動,動態(tài)移動頂層的Widget,當(dāng)監(jiān)聽到手勢結(jié)束的時候根據(jù)手勢滑動的距離動態(tài)將頂部Widget利用動畫效果滑動到結(jié)束位置即可。

          實現(xiàn)底部Widget

          class DownDrawerWidget extends StatelessWidget {
           @override
           Widget build(BuildContext context) {
           return Container(child: Center(child: Text("底部Widget",),),);
           }
          }
          

          這個Widget太簡單了,就不細(xì)說了。

          實現(xiàn)頂部Widget

          class UpDrawerWidget extends StatelessWidget {
           @override
           Widget build(BuildContext context) {
           return Container(child: Center(child: Text("頂部Widget",),),);
           }
          }
          

          實現(xiàn)方式和底部是一樣的。

          實現(xiàn)可以移動的容器

          上面兩個Widget都是單純用來顯示的Widget,因此繼承了StatelessWidget。接下來我們需要根據(jù)手勢動態(tài)移動頂部的Widget,因此需要繼承StatefulWidget。

          // 頂部Widget
          class HomePageWidget extends StatefulWidget {
           @override
           State<StatefulWidget> createState()=> HomePageState();
          }
          class HomePageState extends State<HomePageWidget>
           with SingleTickerProviderStateMixin {
           @override
           void initState() {...}
           @override
           void dispose() {...}
           @override
           Widget build(BuildContext context) {...}
           void _onViewDragDown(DragDownDetails callback) {...}
           void _onViewDrag(DragUpdateDetails callback) {...}
           void _onViewDragUp(DragEndDetails callback) {...}
          }
          

          初始化狀態(tài)initState()

          這個方法是在Widget初始化的時候系統(tǒng)的回調(diào)函數(shù),我們需要在該函數(shù)中初始化動畫

          AnimationController controller;
          @override
          void initState() {
           // 初始化動畫控制器,這里限定動畫時常為200毫秒
           controller=new AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
           // vsync對象會綁定動畫的定時器到一個可視的widget,所以當(dāng)widget不顯示時,動畫定時器將會暫停,當(dāng)widget再次顯示時,動畫定時器重新恢復(fù)執(zhí)行,這樣就可以避免動畫相關(guān)UI不在當(dāng)前屏幕時消耗資源。
           // 當(dāng)使用vsync: this的時候,State對象必須with SingleTickerProviderStateMixin或TickerProviderStateMixin;TickerProviderStateMixin適用于多AnimationController的情況。
           // 設(shè)置動畫曲線,就是動畫插值器
           // 通過這個鏈接可以了解更多差值器,https://docs.flutter.io/flutter/animation/Curves-class.html,我們這里使用帶回彈效果的bounceOut。
           CurvedAnimation curve=new CurvedAnimation(parent: controller, curve: Curves.bounceOut);
           // 增加動畫監(jiān)聽,當(dāng)手勢結(jié)束的時候通過動態(tài)計算到達(dá)目標(biāo)位置的距離實現(xiàn)動畫效果。curve.value為當(dāng)前動畫的值,取值范圍0~1。
           curve.addListener(() {
           double animValue=curve.value;
           double offset=dragUpDownX - dragDownX;
           double toPosition;
           // 右滑
           if (offset > 0) {
           if (offset > maxDragX / 5) {
           // 打開
           toPosition=maxDragX;
           isOpenState=true;
           } else {
           if (isOpenState) {
           toPosition=maxDragX;
           isOpenState=true;
           } else {
           toPosition=0.0;
           isOpenState=false;
           }
           }
           } else {
           if (offset < (-maxDragX / 2.0)) {
           // 關(guān)
           toPosition=0.0;
           isOpenState=false;
           } else {
           if (isOpenState) {
           toPosition=maxDragX;
           isOpenState=true;
           } else {
           toPosition=0.0;
           isOpenState=false;
           }
           }
           }
           dragOffset=(toPosition - dragUpDownX) * animValue + dragUpDownX;
           // 刷新位置
           setState(() {});
           });
           }
          

          結(jié)束Widget dispose()

          當(dāng)Widget不可用將被回收的時候,系統(tǒng)會回調(diào)dispose()方法,我們在這里回收動畫。

          @override
          void dispose() {
           controller.dispose();
          }
          

          記錄按下的位置

           double dragDownX=0.0;
           void _onViewDragDown(DragDownDetails callback) {
           dragDownX=callback.globalPosition.dx;
           }
          

          拖動的時候刷新View的位置

          /**
           * 最大可拖動位置
           */
           final double maxDragX=230.0;
           double dragOffset=0.0;
           void _onViewDrag(DragUpdateDetails callback) {
           double tmpOffset=callback.globalPosition.dx - dragDownX;
           if (tmpOffset < 0) {
           tmpOffset +=maxDragX;
           }
           // 邊緣檢測
           if (tmpOffset < 0) {
           tmpOffset=0.0;
           } else if (tmpOffset >=maxDragX) {
           tmpOffset=maxDragX;
           }
           // 刷新
           if (dragOffset !=tmpOffset) {
           dragOffset=tmpOffset;
           setState(() {});
           }
           }
          

          離手的時候記錄位置并執(zhí)行動畫

           /**
           * 脫手時候的位置
           */
           double dragUpDownX=0.0;
           void _onViewDragUp(DragEndDetails callback) {
           dragUpDownX=dragOffset;
           // 執(zhí)行動畫,每次都從第0幀開始執(zhí)行
           controller.forward(from: 0.0);
           }
          

          支持移動的Widget

          @override
           Widget build(BuildContext context) {
           return Transform.translate(
           offset: Offset(dragOffset, 0.0),
           child: Container(
           child: GestureDetector(
           onHorizontalDragDown: _onViewDragDown,
           onVerticalDragDown: _onViewDragDown,
           onHorizontalDragUpdate: _onViewDrag,
           onVerticalDragUpdate: _onViewDrag,
           onHorizontalDragEnd: _onViewDragUp,
           onVerticalDragEnd: _onViewDragUp,
           child: Container(
           child: new UpDrawerWidget(),
           ),),),);}
          

          Flutter動畫

          總結(jié)一下,想在Flutter中實現(xiàn)動畫,需要先創(chuàng)建一個AnimationController控制器;如果有特殊的插值要求,再創(chuàng)建一個插值器,調(diào)用controller.forward()方法執(zhí)行動畫,通過addListener()的回調(diào)改變對應(yīng)數(shù)值之后調(diào)用setState(() {})方法刷新位置即可。

          Flutter API還提供AnimatedBuilder用來簡化實現(xiàn)動畫的復(fù)雜性,讓我們不用手動調(diào)用addListener()方法。


          主站蜘蛛池模板: 午夜天堂一区人妻| 女女同性一区二区三区四区| 国产精品毛片一区二区三区| 无码中文人妻在线一区| 亚洲AV无码一区二区三区网址 | 国产高清在线精品一区| 国产福利91精品一区二区三区| 日本伊人精品一区二区三区 | 精品福利一区二区三| 在线观看免费视频一区| 精品国产亚洲一区二区三区| 久久精品一区二区三区资源网| 日本一区二区免费看| 日韩色视频一区二区三区亚洲| 国产精品亚洲高清一区二区| 精品深夜AV无码一区二区| 激情综合丝袜美女一区二区| 亚洲免费一区二区| 在线精品视频一区二区| 久久久不卡国产精品一区二区| 无码一区二区三区| 国产一区二区在线观看麻豆| 久久精品一区二区三区四区| 日本一区二区三区精品国产 | 91精品福利一区二区| 久久国产午夜精品一区二区三区| 亚洲日韩精品一区二区三区| 成人精品一区久久久久| 91在线视频一区| 狠狠综合久久AV一区二区三区| 精品一区二区三区电影| 风流老熟女一区二区三区| 亚洲国产精品一区二区久| 久久精品一区二区东京热| 精品国产一区二区三区久久| 精品免费AV一区二区三区| 国产综合精品一区二区| 亚洲欧美日韩中文字幕一区二区三区 | 国产成人一区二区三区高清| 午夜精品一区二区三区免费视频| 成人国内精品久久久久一区|