整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          3行css實現循環動畫,順便說說瀏覽器兼容性

          3行css實現循環動畫,順便說說瀏覽器兼容性

          前端開發來說,通過動畫來提升交互效果是很常見的。在很早以前,做web動畫主要通過javascript或者jquery或者flash這樣的手段,非常麻煩,自打有了ccs3,做動畫就太方便了,只需幾行css代碼就可以搞定。

          這里我們就演示一個常見的循環滾動效果,任務是這樣:先準備一個圖片,平鋪到頁面上充滿整個屏幕,然后就讓畫面一直向上循環滾動,形成無邊無際的感覺。

          雖然可以從網上搜到一些類似的代碼,但是魚龍混雜,無關緊要的代碼非常多,不夠純粹。如果要弄明白動畫的原理,只有自己動手做一遍才能真正消化吃透。所以我們來一步步原創這個代碼,排除所有不必要的基礎樣式,只說要點,3個步驟你就可以完全掌握其精髓!

          第一步:布局

          首先,滾動的圖片需要放在一個容器里,一行html代碼即可完成:

          第二步:把圖片放進容器

          css中body的邊界設為0,把容器設高度100%以充滿屏幕,再調用背景圖pic.png

          第三部:讓畫面動起來

          咱不做標題黨,循環滾動靠的就是3行css動起來的。

          先是1行 -webkit-animation屬性:4個參數分別表示:動畫名稱scroll,1秒時長,移動速度為線性的,無限循環。

          然后是對應的關鍵幀 @-webkit-keyframes 屬性,這是自己定義的動畫規則,只需寫2行規則即可:

          原理:動畫就是畫從一個地方動到另一個地方。對普通滾動效果來說,有起點和終點這兩個節點的位置就夠了。所以我們用0%和100%分別表示起點和終點,指定2個背景圖的xy位置坐標即可。圖片會在規定時間內從起點移動到終點,并循環下去,數值是負表示是向上移動。320px正好是圖片的高度,這樣循環的時候是無縫銜接的。

          好了,最終完整的代碼如下,是不是很精練呢?保存成 index.html 即可

          代碼寫完了,還要記得在當前目錄要有pic.png這個圖片哦,我隨便畫了幾筆,絕無觀賞性,建議自己找個好看點的圖片來代替。

          現在用瀏覽器打開index.html即可看到效果,比較魔性的地方在于,如果你盯著看久了,關閉窗口以后會出現幻覺,仿佛整個顯示器都在向上飛,哈哈!

          最后我們來說說瀏覽器兼容性問題:

          大家可能注意到了,前面那2個古怪的 -webkit-animation, @-webkit-keyframes 這里的-webkit-其實是一個前綴,animation和@keyframes才是CSS的標準屬性。

          當加上-webkit-后,就形成了一個針對特殊瀏覽器的專有屬性,表示用在谷歌的chrome和蘋果的safari瀏覽器上。此外還有-moz前綴代表針對firefox瀏覽器的私有屬性。

          所以我們在用到css3的一些特性的時候,經常使用一大堆的重復性的代碼,比如我們今天的這個代碼,有人會寫成這個樣子:

          一個簡單的動畫就要寫這么多冗余的代碼,為的只是支持一些舊的瀏覽器,有必要嗎?為什么在這個例子中我們僅僅采用了-webkit-而沒有使用其它專有屬性呢?

          因為現在已經是2019年了!谷歌蘋果的瀏覽器是主流,占據了絕大部分,而其它小眾瀏覽器也大多能夠兼容他們,在版本上,大部分人安裝瀏覽器是直接下載新版本安裝使用,而非找出家里陳年的老軟盤、老光盤去安裝,家中的老電腦也早已升級不知多少回了,所以也幾乎沒有機會使用低版本的瀏覽器了!

          至于微軟的IE,就更別提了,IE9以前不支持動畫的,只能用js或者jquery來寫動畫,直到IE10才支持css動畫,隨后IE被放棄,主推Edge,搞了幾天越來越頭大干脆也放棄,現在直接使用chrome內核了,所以針對ie的兼容性除非有特殊要求已經無需考慮。

          你在網上能看到的范例代碼,如果有寫成那么復雜臃腫的,估計也都是3-5年前發的老文,或者抄來抄去不做思考的搬磚工留下的“初學者”筆記。

          我們不仿測試一下幾款主流瀏覽器的情況看看,結論:

          測試結果表明,-webkit-的寫法在4款不同內核的瀏覽器上都能正常使用,所以我們的代碼因此能得以簡化。

          當然,這個例子也有局限性,比如你看,只有蘋果safari不支持標準寫法,萬一將來他改邪歸正了呢?畢竟標準寫法才是眾望所歸不是?使用針對個別瀏覽器的私有屬性寫法,雖可用但畢竟有些怪怪的,將來怎么樣還很難說呢。這樣看來,如果使用古老的處理辦法,重復N次為每個專屬瀏覽器各寫一份代碼,除了辣眼睛也真沒什么錯。

          瀏覽器的兼容問題涉及面實在是非常廣,三言兩語還真說不完,以后會專門來講。

          詳細介紹如何使用 HTML 和 CSS 創建文本與圖片的無限滾動動畫效果。網頁內容包含兩個部分,一個是標簽組滾動,另一個是圖片組滾動,其中動畫的效果主要表現為標簽和圖片一直橫向的水平滾動,并且元素會無縫銜接從而實現無限循環,并且首尾兩端有漸變蒙層效果,以造成出現和消失的過渡。


          HTML 結構

          首先,HTML 代碼部分包含了5個.scroll元素,這個數量取決于你網頁有幾個無限滾動區域。每個scroll元素都放了兩個div(d1和d2)用于創建滾動容器,其中每個div元素都具有相同的內容元素,用于展示滾動內容。本案例的主要內容就是標簽組span和圖片組img。

          <!DOCTYPE html>
          <html lang="en">
          
          <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Infinite Scrolling Animation</title>
          
            <link rel="stylesheet" href="./css/index.css">
          </head>
          
          <body>
            <div class="scroll" style="--t: 20s">
              <div>
                <span>HTML</span>
                <span>CSS</span>
                <span>JavaScript</span>
                <span>Vue</span>
                <span>React</span>
                <span>Figma</span>
                <span>Photoshop</span>
              </div>
          
              <div>
                <span>HTML</span>
                <span>CSS</span>
                <span>JavaScript</span>
                <span>Vue</span>
                <span>React</span>
                <span>Figma</span>
                <span>Photoshop</span>
              </div>
            </div>
          
            <div class="scroll" style="--t: 30s">
              <!-- 同上 -->
            </div>
          
            <div class="scroll" style="--t: 10s">
              <!-- 同上 -->
            </div>
          
            <div class="scroll" style="--t: 35s">
              <!-- 同上 -->
            </div>
          
            <div class="scroll img-box" style="--t: 25s">
              <div>
                <img src="./images/img_01.jpg" alt="image">
                <img src="./images/img_02.jpg" alt="image">
                <img src="./images/img_03.jpg" alt="image">
                <img src="./images/img_04.jpg" alt="image">
                <img src="./images/img_05.jpg" alt="image">
                <img src="./images/img_06.jpg" alt="image">
                <img src="./images/img_07.jpg" alt="image">
                <img src="./images/img_08.jpg" alt="image">
                <img src="./images/img_09.jpg" alt="image">
              </div>
          
              <div>
                <!-- 同上 -->
              </div>
            </div>
          </body>
          
          </html>

          標簽組和圖片組里的兩個div要寬度保持一致,也就是說d1和d2里的每個標簽span要對應相同,否則兩個div就會出現滾動覆蓋或距離過大。 還有就是每個scroll標簽的自定義變量--t的值不一樣(又快又慢),要想滾動效果統一的話時間調整一樣就可以了。

          CSS 樣式

          接下來,看 CSS 部分設置了一些基本的全局樣式,有重置樣式、內容水平垂直居中布局、背景字體顏色等不做過多贅述。

          /* @import url('https://fonts.googleapis.com/css?family=Poppins:400,600,700,800&display=swap'); */
          @import './google-fonts.css';
          
          * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Poppins', sans-serif;
          }
          
          body {
            min-height: 100vh;
            background-color: #222;
            color: #fff;
          
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;  
          }
          
          /* ... */

          滾動容器scroll有一個固定寬度,然后對于溢出的內容隱藏不可見,以及使用 mask-image 創建了一個線性漸變遮罩,給內容帶來滾動時的淡出淡入視覺效果。

          • span元素標簽的樣式設置了內聯塊級元素的展示方式,以及一些邊距、邊框、字母間距和文本轉換。此外,當鼠標懸停時,還設置了背景顏色的變化。
          • img圖片的樣式設置了最大寬度和灰度濾鏡,當鼠標懸停在圖片上時,濾鏡會被移除,呈現出原始彩色圖片。 兩者都提供了一種交互反饋的效果。
          
          .scroll {
            display: flex;
            width: 700px;
            overflow: hidden;
            mask-image: linear-gradient(90deg, transparent, #fff 20%, #fff 80%, transparent);
            -webkit-mask-image: linear-gradient(90deg, transparent, #fff 20%, #fff 80%, transparent);
          }
          
          .scroll > div span {
            display: inline-block;
            margin: 10px;
            padding: 5px 10px;
            background-color: #333;
            border-radius: 5px;
          
            letter-spacing: 0.2em;
            text-transform: uppercase;
          
            cursor: pointer;
            transition: background-color 0.5s;
          }
          .scroll > div span:hover {
            background-color: #4caf50;
          }
          
          .img-box img {
            max-width: 150px;
            filter: grayscale(1);
            
            cursor: pointer;
            transition: filter 0.5s;
          }
          .img-box img:hover {
            filter: grayscale(0);
          }
          
          /* ... */

          技術實現

          接著就是每個滾動容器內包裹兩個一樣的div元素,用于創建無縫銜接,下面分別簡稱為d1和d2。通過 white-space: nowrap 屬性確保 div 內的內容不換行,從而使得內容能夠水平滾動。

          主要通過兩個不同的關鍵幀動畫@keyframes關鍵幀和過渡animation屬性控制兩個滾動區域實現的滾動效果。讓元素以無限循環和線性動畫的方式在.scroll滾動容器內移動。拿本案列的img-box元素闡釋一下動畫執行過程:

          • 首先,它定義的CSS變量是--t: 25s。里面兩個div元素都應用了25s勻速無限循環動畫。
          • 然后,在d1中應用了延遲25s * -1=-25s,animate動畫從 transform: translateX(100%) 開始,將元素初始位置設置在容器的右側外部。在動畫結束時,元素移動到了容器的左側外部,即 transform: translateX(-100%)。
          • 最后,在d2中應用了延遲25s / -2=-12.5s,animate2動畫從 transform: translateX(0) 開始,將元素初始位置設置在容器的右側外部。在動畫結束時,元素移動到了容器的左側更遠的位置,即 transform: translateX(-200%)。滾動的距離是比第一個d1滾動區域更遠的,這樣可以實現錯開的滾動效果。
          
          .scroll > div {
            white-space: nowrap;
            animation: animate var(--t) linear infinite;
            animation-delay: calc(var(--t) * -1);
          }
          @keyframes animate {
            0% {
              transform: translateX(100%);
            }
          
            100% {
              transform: translateX(-100%);
            }
          }
          
          .scroll > div:nth-child(2) {
            animation: animate2 var(--t) linear infinite;
            animation-delay: calc(var(--t) / -2);
          }
          @keyframes animate2 {
            0% {
              transform: translateX(0);
            }
          
            100% {
              transform: translateX(-200%);
            }
          }
          
          
          
          @media screen and (max-width: 768px) {
            .scroll {
              width: 90vw;
            }
          
            .scroll > div span {
              background-color: #4caf50;
            }
          
            .img-box img {
              width: 33vw;
              filter: grayscale(0);
            }
          }

          由于animate延遲小于animate2,所以動畫a2先執行,從右向左持續滾動到x: -200%,當滾動到-100%時也就是當前可見區域,此時a1開始執行動畫 1 ,從右向左持續滾動到x: -100%,當滾動到100%時也就是當前可見區域,a2已經到-200%了,接著看a1繼續滾動到-100%,a2繼續從0到-200%,如此循環往復。

          最后

          通過本篇文章相信能夠幫助你更好地使用CSS來創建一個文本與圖片無限滾動動畫,從而理解掌握和應用這個效果。通過 transform 屬性的變化實現了水平滾動效果,使得 div 內的內容能夠在容器內水平滾動,呈現出無限循環的連接效果。豐富了網頁增添加了動態和交互性。


          「絕無僅有」CSS打造吸睛的文本與圖片無限滾動動畫
          原文鏈接:https://juejin.cn/post/7306442463765544971

          現目標:

          1. 可以一次選取多個圖片上傳;
          2. 上傳的圖片可以拖動排序;
          3. 點擊圖片提示刪除彈窗,確認后刪除該圖片;
          4. 點擊上傳按鈕圖標,即可瀏覽圖片,隱藏選擇文件的文本框;
          5. 選擇圖片以后自動上傳;
          6. 拖拽排序的時候使用transition-group,實現動畫效果;

          圖1 多圖上傳效果


          1、html代碼

          <tr class=''>
          <td width="90" align="right">相關多圖</td>
          <td >
          <div class='yllist yllist_x_duotu'>
          <dl>
          <!--存放上傳的圖片-->
          <transition-group name="list">
          <dd   v-for="(item,index) in listData " draggable="true" :key="item" 
          	@click="del(index)" 
          	@mouseover="showzz(1,index)"  
          	@mouseleave="showzz(0,index)" 
          	@dragstart="drag($event,index)" 
          	@drop="drop($event,index)"
          	@dragover='allowDrop($event)'
          	>
              <img :src="item.picpath">
              <div class='zzz none'  :class="{'nonone':item.shs==1}">
              <div class='zzimg '><i class="fa fa-trash-o" aria-hidden="true"></i></div>
          	</div>
          </dd>
          <!--結束-->
          </transition-group>
          <dd  @click="upbtn"  class='btnclass'><i class="fa fa-camera-retro" aria-hidden="true"></i>
          <input type='file' id='multiple' accept="image/*"   multiple="multiple" style='display:none' @change="autoup"  name="ss">
          </dd>
          </dl>
          <div class='clear'></div>
          <div>
          <span class='itemms'>說明:可以拖動改變順序</span>
          </div>
          </div>
          </td>
          </tr>

          說明:

          @click="del(index)" 點擊刪除圖片 index為數組的索引 點擊的是第幾個圖片

          @mouseover="showzz(1,index)" 鼠標放到上邊 出現遮罩層 垃圾桶

          @mouseleave="showzz(0,index)" 鼠標離開 遮罩層消失

          @dragstart="drag($event,index)" 以下三個 用于拖拽排序

          @drop="drop($event,index)"

          @dragover='allowDrop($event)'

          draggable="true" 設置為true 可以拖動

          :key="item" 這里的key 要注意不能等于 index,要不然沒有動畫效果

          img src的屬性 是 :src="item.picpath" 不能是src={{item.picpath}}

          <div class='zzz none' :class="{'nonone':item.shs==1}"> 設置遮罩層 shs=1的時候顯示

          上傳的選擇框設置為display:none隱藏

          transition-group用法:

          <transition-group name="list"> 實現拖拽的動畫效果 后邊的name可以隨意寫 ,但是要和css的.list-move {transition: transform 0.3s;} 【上邊自定義的name,我這里是list】-move 設置該css 動畫的時間

          2、js代碼

          new Vue({
              el: '#app',
              data(){
          		  tagslist:[
          		    '網站開發',//存放的標簽
          			  '網站建設'
          		  ],
          		  tagsdt:"",  //綁定的標簽文本框
          		  tagindex:"",//刪除標簽的序號(索引)
          		  listData: [
          				  /*
          			      {'picpath':'/public/upload/image/20211107/1.jpg',shs:0}
          			      
          				  shs   顯示遮罩層 ,垃圾桶刪除標志,0  不顯示   1顯示
          				  */
          		  ],
                file:"file",      //用于切換 file  text  實現同一個圖片可以連續上傳
          		  tis:'',           //提示內容
          		  showzzc:0,         //彈出框的顯示,隱藏 。0 隱藏  1顯示
          		  showts:0,          //1 彈出提示操作框  2 彈出提示確認框 
          		  lisindex:"",      //記錄圖片的索引
          		  datameth:""       //根據這里的參數操作不同的方法
          		 }
              },
              methods:{
          	  tags:function(){
          		  if(this.tagsdt){
          		      this.tagslist.push(this.tagsdt); 
          		  }
          		  this.tagsdt="";
          	  },
          	  deltag:function(f){
          		  this.showzzc=1;
          		  this.showts=1;
          		  this.tagindex=f;
          		  this.datameth='tag';
          	  },
          	  hidetc:function(){
          		  this.showzzc=0;
          	  },
           	   del:function(key){
          			this.showzzc=1;
          			this.showts=1;
          			this.lisindex=key;
          			this.datameth="delpic";
          			//this.listData.splice(key, 1);
          		},
          	  isdelc:function(){
          			if(this.datameth=="delpic"){
          		        this.listData.splice(this.lisindex, 1); 
          			}
          			if(this.datameth=="tag"){
          		        this.tagslist.splice(this.tagindex, 1); 
          			}
          			this.showzzc=0;
          	  }, 
            	showzz:function(meth,key){
          			//console.log(this.listData[key].shs);
          			if(!this.listData[key].shs){
          			    this.$set(this.listData[key],'shs',0);
          			}
          			this.listData[key].shs=meth;
          	  }, 
          	  upbtn:function(){
          		  document.getElementById("multiple").click();
          	  },
          	  autoup:function(){
          		  let that=this;
                that.file="text";  //切換text  file
          		  let ups=document.getElementById( "multiple");
          		  let formdata=new FormData();
          		  if(ups.files[0]){
          			  if(ups.files.length>4){
          				  this.showzzc=1;
          				  this.showts=2;
          				  this.tis="一次最多可以選擇4張圖片上傳!";
                    that.file="file";
          				  return false;
          			  }
                  for(m=0;m<=ups.files.length-1;m++){
          			      formdata.append("file", ups.files[m]);
          			      axios.post("/api/uppic", formdata)
          					  .then(function (response) {
          					    if(response.data.error=='0000'){
          							    that.listData.push(response.data.pic);
                            that.file="file";//重新切換為file
          							  //console.log(JSON.stringify(that.listData));
          						  }else{
          							  that.showzzc=1;
          							  that.showts=2;
          							  that.tis=response.data.msg;
                          that.file="file";
          							  return false;
          						  }
          					  })
          					  .catch(function (error) {
          						  console.log(error);
          					  });
                    }
          			    console.log(ups.outerHTML);
          		  }  
              }
          })

          注意:上傳圖片以后一定要that.file="file",切換回file,不然會出現只能上傳一次,下次選擇當前圖片不能上傳的情況。

          1. 去掉js中的for循環和html的multiple="multiple"選擇多個圖片,就是單圖的上傳;
          2. 因為刪除彈出提示的地方有2個,實際可能更多,在點擊確認的時候不知道操作哪個刪除,所以點刪除圖片或者是點刪除信息標簽的時候,向datameth賦不同的值,這樣我們點擊彈窗的確認,讀取datameth的值,使用if判斷,就可以知道要刪除圖片還是刪除標簽;
          3. 上傳圖片,刪除圖片用到的彈窗,在前邊十七章有說明;

          上邊的上傳是選取多個然后for循環逐個上傳的,也可以file使用數組file[]批量提交,如下:

          for(m=0;m<=ups.files.length-1;m++){
          			      formdata.append("file[]", ups.files[m]);
          }
          axios.post("/api/uppic", formdata)

          但是這樣做的話,后臺使用

          foreach($_FILES as $k=>$v){
          }

          得到的$v['name']就是數組,需要我們再次for循環,得到單個的圖片信息,返回以后的信息因為是數組,push只能一次追加一個,就只能再次循環,感覺很麻煩還不如開始就循環,一個一個的上傳。

          3、信息標簽html

          <tr class=''>
          <td width="90" align="right">信息標簽</td>
          <td>
          <div class="layui-input-inline tagslist" >
              <span class='tagspan' v-for="(tag,key) in tagslist"   :key="key" @click="deltag(key)">{{tag}}</span>
          </div>
          <input type="text"  class='inpMain' id='tags' style='width:150px;'  @blur="tags" v-model="tagsdt" /> <span class='itemms'>點擊標簽可以刪除</span>
           <span class='itemms'></span>
          </td>
          </tr>

          輸入文本框綁定tagsdt,當我們鼠標離開該文本框的時候,通過blur使用tags方法讀取綁定的tagsdt,可以獲得輸入的內容,這里需要判斷是否為空,如果不為空再push進數組:this.tagslist.push(this.tagsdt);

          4、php后端代碼

          foreach($_FILES as $k=>$v){
                 $v['name'],$v['size'],$v['tem_name']
            就是圖片的基本信息,使用move_uploaded_file移動到指定文件夾
            			$imags['picpath']=$path;
          				$imags['shs']=0;
          }
          exit(json_encode(array('error'=>'0000','pic'=>$imags),JSON_UNESCAPED_UNICODE));

          move_uploaded_file用法:

          當前文件:$v["tmp_name"],

          目標文件:ROOT_PATH.$images_dir.$newname

          move_uploaded_file($v["tmp_name"], ROOT_PATH.$images_dir.$newname);

          再次強調上傳圖片,要驗證圖片的安全性,防止圖片木馬!


          主站蜘蛛池模板: 亚洲AV成人精品日韩一区| 亚洲一区二区三区久久| 精品一区二区三区东京热| 国精产品999一区二区三区有限| 在线一区二区观看| 中文字幕一区二区日产乱码| 国产精品第一区第27页| 国产精品一区二区久久| 国产一区二区视频在线播放| 日韩亚洲AV无码一区二区不卡| 一区二区三区无码高清视频| 亚洲一区精彩视频| 亚洲成在人天堂一区二区| 综合久久一区二区三区 | 精品国产香蕉伊思人在线在线亚洲一区二区 | 亚洲一区二区三区香蕉| 海角国精产品一区一区三区糖心| 2020天堂中文字幕一区在线观| 国产丝袜视频一区二区三区| 无码日韩人妻AV一区免费l| 国精产品一区一区三区有限在线| 日本一区二区三区不卡视频中文字幕| 日韩一区二区免费视频| 成人毛片一区二区| 日韩免费一区二区三区在线播放| 亚洲中文字幕丝袜制服一区 | asmr国产一区在线| 狠狠综合久久av一区二区| 国产一区二区三区韩国女主播| 97久久精品午夜一区二区| 亚洲AV成人精品日韩一区18p| 青青青国产精品一区二区| 国产视频一区二区在线播放| 一区二区三区四区在线视频| 国内偷窥一区二区三区视频| aⅴ一区二区三区无卡无码| 精品国产日韩一区三区| 国产丝袜一区二区三区在线观看| 亚洲一区中文字幕在线观看| 久久久av波多野一区二区| 国产一区二区三区在线观看精品|