H5橫幅,旗幟飄動動畫

核心思路是將已有的圖片通過背景圖片定位設置在不同的元素上,給元素添加動畫,使之看起來有飄動的感覺。如果米有現有圖片,則使用截圖工具生成圖片。

參考博文:https://my.oschina.net/codingDog/blog/1839097

一、有現成圖片

線上demo:https://my.weblf.cn/alone_page/css_ani/flag2.html

代碼:

<!doctype html>
<html lang="zh-cn">

<head>
  <meta charset="UTF-8">
  <meta name="viewport"
    content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>飄動的旗幟~</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    html,
    body {
      height: 100%;
      width: 100%;
      background-color: lightgrey;
    }

    body {
      text-align: center;
      position: relative;
    }

    ul,li {
      list-style: none;
    }

    .flag_box{
      /* transform: rotate(90deg);
      margin-top: 200px; */
      /* transform: scale(1); */
    }
    #flag {
      position: absolute;
      left: 50%;
      top: 50%;
      animation: flag-reverse ease-in-out infinite;
    }

    #flag>li {
      height: 100%;
      float: left;
      background-image: url('../statics/images/flag2.png');
      background-size: auto 100%;
      animation: flag ease-in-out infinite;
    }
  </style>
</head>

<body>
  <div class="flag_box">
    <ul id="flag"></ul>
  </div>
  <script>
    (function () {
      // 這裏是js代碼
      var flagEle = document.getElementById('flag')
      var image = new Image()
      image.src = '../statics/images/flag2.png'

      var IMG_MAX_WIDTH = 600
      var IMG_MAX_HEIGHT = 600
      var imgHeight
      var imgWidth

      image.onload = function () {
        imgWidth = image.width
        imgHeight = image.height
        var ratio = image.width / image.height
        if (imgWidth > IMG_MAX_WIDTH) {
          imgWidth = IMG_MAX_WIDTH
          imgHeight = imgWidth / ratio
        }
        if (imgHeight > IMG_MAX_HEIGHT) {
          imgHeight = IMG_MAX_HEIGHT
          imgWidth = imgHeight * ratio
        }

        flagEle.style.width = imgWidth + 'px'
        flagEle.style.height = imgHeight + 'px'
        flagEle.style.marginLeft = -imgWidth / 2 + 'px'
        flagEle.style.marginTop = -imgHeight / 2 + 'px'
        console.log('圖片加載完成')

        splitImg(100, 5, 1.5, 3)
      }

      /**
       * 分割圖片
       * @param sliceCount 切片數量
       * @param amplitude 振幅
       * @param period 固定週期個數
       * @param duration 一個週期的時長
       */
      function splitImg(sliceCount, amplitude, period, duration) {
       console.log('切割圖片開始')
        var styleEle = document.createElement('style')
        // styleEle.innerHTML = 'body{background: red}'
        var styleHtmlAry = []
        var sliceCountPerPeriod = Math.floor(sliceCount / period)
        var sliceWidth = imgWidth / sliceCount
        var formula = sliceCountPerPeriod + 'n+'
        var interval = duration * period / sliceCount

        // 添加動畫延時
        for (var i = 0; i < sliceCount + 1; i++) {
          if (i < sliceCountPerPeriod) {
            styleHtmlAry.push('#flag > li:nth-child(' + formula + i + ') { ')
            styleHtmlAry.push('animation-delay: -' + (interval * (sliceCountPerPeriod - i)) + 's;')
            styleHtmlAry.push('}')
          }
          styleHtmlAry.push('#flag > li:nth-child(' + i + ') { background-position: -' + (i * sliceWidth) +
            'px 0; }') // 設置切片背景
        }

        // 添加關鍵幀動畫
        styleHtmlAry.push('@keyframes flag {')
        styleHtmlAry.push('0% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
        styleHtmlAry.push('50% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
        styleHtmlAry.push('100% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
        styleHtmlAry.push('}')

        // 添加反向關鍵幀動畫
        styleHtmlAry.push('@keyframes flag-reverse {')
        styleHtmlAry.push('0% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
        styleHtmlAry.push('50% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
        styleHtmlAry.push('100% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
        styleHtmlAry.push('}')

        // 容器應用flag-reverse動畫
        styleHtmlAry.push('#flag {')
        styleHtmlAry.push('animation-duration: ' + duration + 's;') // 添加週期時長
        styleHtmlAry.push('animation-delay: -' + (interval * sliceCountPerPeriod) + 's;')
        styleHtmlAry.push('}')

        // 切片樣式
        styleHtmlAry.push('#flag > li {')
        styleHtmlAry.push('animation-duration: ' + duration + 's;') // 添加週期時長
        styleHtmlAry.push('width: ' + (imgWidth / sliceCount) + 'px;') // 設置切片寬度
        styleHtmlAry.push('}')

        styleEle.innerHTML = styleHtmlAry.join('')

        // 創建切片元素
        flagEle.innerHTML = new Array(sliceCount + 1).join('<li></li>')

        document.documentElement.appendChild(styleEle)
      }
    })();
  </script>
</body>

</html>

二、自動生成圖片後飄動

線上demo:https://my.weblf.cn/vuecli3_wp4_alone_demo/html2canvas_flag.html

此demo使用vue編寫,調用html2canvas生成圖片:

<template>
  <div id="pageDiv" :style="{'padding-top':isWeiXin || isApps?'0':'3rem'}">

    <!-- 頁面頭部-->
    <header-com :poptitle="'html2canvas截圖'" :type="'doc_title'" v-if="!isWeiXin && !isApps"></header-com>
    <!-- 頁面的主要內容 -->
    <section class="content">
      <div class="box_main" ref="imageToFile">
        <div id="flag1">歡迎光臨 一路順風</div>
      </div>
      <button type="button" class="shot-btn" @click="screenShot">截圖</button>
      <!-- 截圖結果 -->
      <p>截圖結果</p>
      <img id="new_img" :src="img" v-if="img"/>
      <!-- 旗幟飄動 -->
      <div class="flag_box">
        <ul id="flag"></ul>
      </div>
    </section>
  </div>
</template>
<script>
import HeaderCom from "@/components/header"; //頁面頭部
import {changeUrl} from "@/utils/changeUrl"
import html2canvas from 'html2canvas'
export default {
  data() {
    return {
      isWeiXin: TS_WEB.isWeiXin,
      isApps: TS_WEB.isApp,
      config: {
        value: '',
        logo: require('@/statics/images/system/sjbj.jpg')
      },
      img: ""
    };
  },
  components: {
    HeaderCom,
    html2canvas
  },
  methods: {
    changeUrl,
    //生成圖片
    screenShot() {
      html2canvas(this.$refs.imageToFile, {
        width: 80,
        height: 200,
        scale: 1,
      }).then((canvas) => {// 第一個參數是需要生成截圖的元素,第二個是自己需要配置的參數,寬高等
        this.img = canvas.toDataURL('image/png');
        setTimeout(()=>{
          this.img_ini()
        },1000)
      })
    },
    /**
     * 分割圖片
     * @param sliceCount 切片數量
     * @param amplitude 振幅
     * @param period 固定週期個數
     * @param duration 一個週期的時長
     */
    splitImg(sliceCount, amplitude, period, duration,image,flagEle) {
      console.log('切割圖片開始')
      var imgWidth = image.width
      document.getElementById('flag').style.width=imgWidth+'px'
      var imgHeight = image.height
      var styleEle = document.createElement('style')
      // styleEle.innerHTML = 'body{background: red}'
      var styleHtmlAry = []
      var sliceCountPerPeriod = Math.floor(sliceCount / period)
      var sliceWidth = imgWidth / sliceCount
      var formula = sliceCountPerPeriod + 'n+'
      var interval = duration * period / sliceCount

      // 添加動畫延時
      for (var i = 0; i < sliceCount+1; i++) {
        console.log(i)
        if (i < sliceCountPerPeriod) {
          styleHtmlAry.push('#flag > li:nth-child(' + formula + i + ') { ')
          styleHtmlAry.push('animation-delay: -' + (interval * (sliceCountPerPeriod - i)) + 's;')
          styleHtmlAry.push('}')
        }
        styleHtmlAry.push('#flag > li:nth-child(' + i + ') { background-position: -' + (i * sliceWidth) +
          'px 0; }') // 設置切片背景
      }

      // 添加關鍵幀動畫
      styleHtmlAry.push('@keyframes flag {')
      styleHtmlAry.push('0% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
      styleHtmlAry.push('50% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
      styleHtmlAry.push('100% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
      styleHtmlAry.push('}')

      // 添加反向關鍵幀動畫
      styleHtmlAry.push('@keyframes flag-reverse {')
      styleHtmlAry.push('0% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
      styleHtmlAry.push('50% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
      styleHtmlAry.push('100% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
      styleHtmlAry.push('}')

      // 容器應用flag-reverse動畫
      styleHtmlAry.push('#flag {')
      styleHtmlAry.push('animation-duration: ' + duration + 's;') // 添加週期時長
      styleHtmlAry.push('animation-delay: -' + (interval * sliceCountPerPeriod) + 's;')
      styleHtmlAry.push('}')

      // 切片樣式
      styleHtmlAry.push('#flag > li {')
      styleHtmlAry.push('animation-duration: ' + duration + 's;') // 添加週期時長
      styleHtmlAry.push('width: ' + (imgWidth / sliceCount) + 'px;') // 設置切片寬度
      styleHtmlAry.push('}')

      styleEle.innerHTML = styleHtmlAry.join('')

      // 創建切片元素
      flagEle.innerHTML = new Array(sliceCount+1).join(`<li style="background-image:url('${this.img}')"></li>`)

      document.documentElement.appendChild(styleEle)
    },
    //獲取新圖片
    img_ini(){
      var flagEle = document.getElementById('flag')
      var image = new Image()
      image.src = this.img
      let that=this
      image.onload = function () {
        console.log('圖片加載完成')
        that.splitImg(80, 5, 1.5, 3,image,flagEle)
      }
    }
  },
  mounted(){
  },
  created() {
    document.title='html2canvas截圖'
  }
};
</script>
<style>
#flag {
  height: 100%;
  position: absolute;
  animation: flag-reverse ease-in-out infinite;
}

#flag>li {
  height: 100%;
  float: left;
  background-size: auto 100%;
  animation: flag ease-in-out infinite;
}
</style>
<style lang="less" scoped>
// 盒子模型
#pageDiv {
  width: 100%;
  height: 100%;
  padding-top: 0;
  padding-bottom: 0;
  overflow: hidden;
  position: relative;
  box-sizing: border-box;
  .content{
    height: 100%;
    width: 100%;
    overflow: scroll;
    overflow-x: hidden;
    .box_main{
      width: 80px;
      height: 200px;
      #flag1{
        width: 80px;
        height: 200px;
        background: red;
        writing-mode: vertical-lr;
        font-size: 16px;
        line-height: 80px;
        padding-top: 20px;
        box-sizing: border-box;
        color: white;
      }
    }
    #new_img{
      display: block;
      width: 80px;
      height: 250px;
    }
    ul,li {
      list-style: none;
    }
    .flag_box{
      position: absolute;
      right: 50px;
      top: 4rem;
      height: 200px;
      width: 80px;
    }
  }
}
</style>

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章