<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      節日禮物待簽收,開箱國慶頭像

      ?? 點擊這里 獲取國慶頭像。通過 Vue3 + Vant(組件庫) + Vite 構建。

      應用的流程

      在做之前,先思考它的流程:

      1. 上傳頭像
      2. 選擇頭像模板
      3. 保存新頭像

      進入應用放出節日祝福與簡單的使用介紹。

      image

      開始僅顯示一個上傳頭像按鈕。這樣做的好處是,直接固定第一步操作。如果將模板和保存按鈕顯示出來需要增加代碼做一些判斷。如果開始就將頭像模板與保存按鈕顯示,可能讓人無從下手。

      image

      上傳頭像后直接將模板與保存按鈕顯示出來。在代碼中默認選中今年最流行的模板,直接點擊保存按鈕將下載這個頭像。開屏也進行了選擇模板的提示,如果點擊一個頭像模板,將進行切換,通過點擊保存按鈕保存它。

      image

      最后,點擊保存顯示煙花動畫。

      image

      代碼實現

      頭像上傳

      <div
        class="uploader-wrap"
        :style="{ marginTop: fileList.length === 0 ? '220px' : '80px' }"
      >
        <Uploader
          v-model="fileList"
          preview-size="120px"
          class="uploader"
          :deletable="true"
          :max-count="1"
          :after-read="afterRead"
          :before-delete="handleDelete"
        />
      </div>
      

      開始,僅顯示一個上傳按鈕,但希望它出現在屏幕靠中間位置,便于點擊。通過 vue 樣式綁定即可。

      .uploader-wrap {
        display: flex;
        justify-content: center;
        transition: 0.3s margin;
      }
      

      在樣式代碼中給它添加 transition(過渡效果)。

      const fileList = ref([])
      const base64 = ref('')
      
      const afterRead = file => buildBase64(file.file)
      
      const buildBase64 = file => {
        const reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = () => {
          base64.value = reader.result
        }
      }
      
      const handleDelete = () => {
        base64.value = ''
        fileList.value = []
      }
      

      在 JS 中,通過 afterRead 獲取上傳的文件,并將它轉化為 Base64 編碼,以便在后面將它在頭像模板中再次顯示。通過 handleDelete 將 響應屬性 base64 與 fileList 的值清空。由于上傳按鈕位置通過 vue 樣式綁定,當 fileList 為空時,上傳按鈕會再次回到屏幕靠中間位置。

      模板列表

      <div class="preview-list">
        <div
          class="preview-item"
          v-if="fileList.length !== 0"
          v-for="(num, index) in 6"
          :id="`item-${num}`"
          :key="index"
          @click="handleSelect"
        >
          <img
            class="preview-item__img"
            :src="base64"
            alt="avatar"
            v-show="base64 !== ''"
          />
          <img
            class="preview-item__modification"
            :src="getImageUrl(num)"
            alt="avatar"
          />
        </div>
      </div>
      

      通過 v-if 控制列表顯示。給每個列表項一個唯一的 id,以便區分它們。

      .preview-list {
        display: grid;
        grid-template-rows: repeat(2, 1fr);
        grid-template-columns: repeat(3, 1fr);
        row-gap: 14px;
        column-gap: 8px;
        margin: 40px 0 60px;
      
        .preview-item {
          justify-self: center;
          // ...
          img {
            display: block;
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 100%;
          }
        }
      }
      
      

      在樣式中,直接通過 grid 生成一個兩行三列的布局。由于給圖片的設定寬度小于網格寬度,通過 justify-self: center 使每個項水平居中。通過定位將兩個 img 重疊顯示。如果使用兩個 div,并分別給它們添加背景圖片(Base64)配合 Vue3 CSS 樣式變量注入將非常香,但生成 canvas 后將變得模糊。

      const getImageUrl = name => new URL(`./assets/${name}.png`, import.meta.url).href
      const selectedId = ref('item-1')
      
      const handleSelect = e => {
        selectedId.value = e.currentTarget.id
        Toast.success('選擇成功')
      }
      

      在 JS 中,由于 vue 無法在動態綁定 src 至本地文件,在 webpack 中使用 require 動態引入文件即可。 在 vite 中,通過 vite 特有的 import.meta.url 來獲取。原因是,可以通過動態綁定到 "/src/assets/ ${name}.png" 來顯示出頭像模板,但這在生產環境中無法被加載(資產被打包到 dist 或其他目錄下,assets 不在 src 下了)。如果是 src 靜態的,直接通過綁定 "./assets/${name}.png" 即可, 開發環境輸出到瀏覽器時,被編譯為 "/src/assets/name.png",在生產環境也能被正確顯示,另外也可以通過將靜態頭像模板圖片放到根目錄下的 public 來解決,在 vite build 時,public 會被復制到輸出文件夾(ourDir)下。

      保存頭像

      <Button
        v-if="fileList.length !== 0"
        :loading="downloading"
        @click="handleSave"
        type="primary"
        loading-text="保存中..."
        block
        color="#FA9935"
        >保存</Button
      >
      

      template 中,使用 vant 組件庫加載按鈕,通過點擊觸發 handleSave 函數保存頭像。

      const downloading = ref(false)
      
      const handleSave = () => {
        if (fileList.value.length === 0) {
          Toast.fail('請先上傳頭像')
          return
        }
      
        downloading.value = true
      
        html2canvas(document.querySelector(`#${selectedId.value}`), {
          scale: 4,
          allowTaint: true,
          dpi: window.devicePixelRatio * 2,
        }).then(canvas => {
          saveAs(canvas.toDataURL(), 'image.jpg')
          downloading.value = false
          Toast.success('保存成功')
          showFireworks.value = true
      
          setTimeout(() => {
            showFireworks.value = false
          }, 3000)
        })
      }
      

      handleSave 函數中,開始將 downloading 的值更新為 true,按鈕這時為 loading 狀態。通過 html2canvas.js 將選中的頭像模板轉為 canvas,在結果中通過 canvas.toDataURL() 獲取 canvas dataUrl,在通過 file-saver 將頭像保存。通過 HTML a[download] 與 download.js 都不能很好的處理移動端兼容問題。最后,就是顯示煙花彩蛋了,在煙花動畫播放完畢再將它關閉。

      煙花效果與開屏提示

      以上就是主要代碼了,下面分別是煙花效果與開屏提示組件的代碼片段,如果你對它們感興趣可以通過點擊展開查看它們。

      Blessing.vue
      <script setup>
      import { ref } from 'vue'
      const show = ref(true)
      </script>
      
      <template>
        <van-dialog
          v-model:show="show"
          title="Hi,國慶節快樂"
          theme="round-button"
          confirmButtonText="好"
        >
          <div class="blessing">
            <ol>
              <li>?? 上傳頭像</li>
              <li>?? 選擇一個模板</li>
              <li>?? 保存新頭像</li>
            </ol>
            <p>——來自 <a href="http://www.rzrgm.cn/guangzan/">@guangzan</a></p>
          </div>
        </van-dialog>
      </template>
      
      <style lang="scss">
      .blessing {
        padding: 20px;
        h4 {
          margin-bottom: 16px;
        }
        p {
          margin: 4px 0;
          font-size: 12px;
          color: #666;
          text-align: right;
        }
        ol {
          margin-left: 20px;
          list-style: auto;
          li {
            margin-bottom: 4px;
          }
        }
        a {
          color: #b8251b;
        }
      }
      </style>
      
      Congratulate.vue
      <template>
        <div class="container">
          <div class="wrapper">
            <div class="confetti-201"></div>
            <div class="confetti-200"></div>
            <div class="confetti-199"></div>
            <div class="confetti-198"></div>
            <div class="confetti-197"></div>
            <div class="confetti-196"></div>
            <div class="confetti-195"></div>
            <div class="confetti-194"></div>
            <div class="confetti-193"></div>
            <div class="confetti-192"></div>
            <div class="confetti-191"></div>
            <div class="confetti-190"></div>
            <div class="confetti-189"></div>
            <div class="confetti-188"></div>
            <div class="confetti-187"></div>
            <div class="confetti-186"></div>
            <div class="confetti-185"></div>
            <div class="confetti-184"></div>
            <div class="confetti-183"></div>
            <div class="confetti-182"></div>
            <div class="confetti-181"></div>
            <div class="confetti-180"></div>
            <div class="confetti-179"></div>
            <div class="confetti-178"></div>
            <div class="confetti-177"></div>
            <div class="confetti-176"></div>
            <div class="confetti-175"></div>
            <div class="confetti-174"></div>
            <div class="confetti-173"></div>
            <div class="confetti-172"></div>
            <div class="confetti-171"></div>
            <div class="confetti-170"></div>
            <div class="confetti-169"></div>
            <div class="confetti-168"></div>
            <div class="confetti-167"></div>
            <div class="confetti-166"></div>
            <div class="confetti-165"></div>
            <div class="confetti-164"></div>
            <div class="confetti-163"></div>
            <div class="confetti-162"></div>
            <div class="confetti-161"></div>
            <div class="confetti-160"></div>
            <div class="confetti-159"></div>
            <div class="confetti-158"></div>
            <div class="confetti-157"></div>
            <div class="confetti-156"></div>
            <div class="confetti-155"></div>
            <div class="confetti-154"></div>
            <div class="confetti-153"></div>
            <div class="confetti-152"></div>
            <div class="confetti-151"></div>
            <div class="confetti-150"></div>
            <div class="confetti-149"></div>
            <div class="confetti-148"></div>
            <div class="confetti-147"></div>
            <div class="confetti-146"></div>
            <div class="confetti-145"></div>
            <div class="confetti-144"></div>
            <div class="confetti-143"></div>
            <div class="confetti-142"></div>
            <div class="confetti-141"></div>
            <div class="confetti-140"></div>
            <div class="confetti-139"></div>
            <div class="confetti-138"></div>
            <div class="confetti-137"></div>
            <div class="confetti-136"></div>
            <div class="confetti-135"></div>
            <div class="confetti-134"></div>
            <div class="confetti-133"></div>
            <div class="confetti-132"></div>
            <div class="confetti-131"></div>
            <div class="confetti-130"></div>
            <div class="confetti-129"></div>
            <div class="confetti-128"></div>
            <div class="confetti-127"></div>
            <div class="confetti-126"></div>
            <div class="confetti-125"></div>
            <div class="confetti-124"></div>
            <div class="confetti-123"></div>
            <div class="confetti-122"></div>
            <div class="confetti-121"></div>
            <div class="confetti-120"></div>
            <div class="confetti-119"></div>
            <div class="confetti-118"></div>
            <div class="confetti-117"></div>
            <div class="confetti-116"></div>
            <div class="confetti-115"></div>
            <div class="confetti-114"></div>
            <div class="confetti-113"></div>
            <div class="confetti-112"></div>
            <div class="confetti-111"></div>
            <div class="confetti-110"></div>
            <div class="confetti-109"></div>
            <div class="confetti-108"></div>
            <div class="confetti-107"></div>
            <div class="confetti-106"></div>
            <div class="confetti-105"></div>
            <div class="confetti-104"></div>
            <div class="confetti-103"></div>
            <div class="confetti-102"></div>
            <div class="confetti-101"></div>
            <div class="confetti-100"></div>
            <div class="confetti-99"></div>
            <div class="confetti-98"></div>
            <div class="confetti-97"></div>
            <div class="confetti-96"></div>
            <div class="confetti-95"></div>
            <div class="confetti-94"></div>
            <div class="confetti-93"></div>
            <div class="confetti-92"></div>
            <div class="confetti-91"></div>
            <div class="confetti-90"></div>
            <div class="confetti-89"></div>
            <div class="confetti-88"></div>
            <div class="confetti-87"></div>
            <div class="confetti-86"></div>
            <div class="confetti-85"></div>
            <div class="confetti-84"></div>
            <div class="confetti-83"></div>
            <div class="confetti-82"></div>
            <div class="confetti-81"></div>
            <div class="confetti-80"></div>
            <div class="confetti-79"></div>
            <div class="confetti-78"></div>
            <div class="confetti-77"></div>
            <div class="confetti-76"></div>
            <div class="confetti-75"></div>
            <div class="confetti-74"></div>
            <div class="confetti-73"></div>
            <div class="confetti-72"></div>
            <div class="confetti-71"></div>
            <div class="confetti-70"></div>
            <div class="confetti-69"></div>
            <div class="confetti-68"></div>
            <div class="confetti-67"></div>
            <div class="confetti-66"></div>
            <div class="confetti-65"></div>
            <div class="confetti-64"></div>
            <div class="confetti-63"></div>
            <div class="confetti-62"></div>
            <div class="confetti-61"></div>
            <div class="confetti-60"></div>
            <div class="confetti-59"></div>
            <div class="confetti-58"></div>
            <div class="confetti-57"></div>
            <div class="confetti-56"></div>
            <div class="confetti-55"></div>
            <div class="confetti-54"></div>
            <div class="confetti-53"></div>
            <div class="confetti-52"></div>
            <div class="confetti-51"></div>
            <div class="confetti-50"></div>
            <div class="confetti-49"></div>
            <div class="confetti-48"></div>
            <div class="confetti-47"></div>
            <div class="confetti-46"></div>
            <div class="confetti-45"></div>
            <div class="confetti-44"></div>
            <div class="confetti-43"></div>
            <div class="confetti-42"></div>
            <div class="confetti-41"></div>
            <div class="confetti-40"></div>
            <div class="confetti-39"></div>
            <div class="confetti-38"></div>
            <div class="confetti-37"></div>
            <div class="confetti-36"></div>
            <div class="confetti-35"></div>
            <div class="confetti-34"></div>
            <div class="confetti-33"></div>
            <div class="confetti-32"></div>
            <div class="confetti-31"></div>
            <div class="confetti-30"></div>
            <div class="confetti-29"></div>
            <div class="confetti-28"></div>
            <div class="confetti-27"></div>
            <div class="confetti-26"></div>
            <div class="confetti-25"></div>
            <div class="confetti-24"></div>
            <div class="confetti-23"></div>
            <div class="confetti-22"></div>
            <div class="confetti-21"></div>
            <div class="confetti-20"></div>
            <div class="confetti-19"></div>
            <div class="confetti-18"></div>
            <div class="confetti-17"></div>
            <div class="confetti-16"></div>
            <div class="confetti-15"></div>
            <div class="confetti-14"></div>
            <div class="confetti-13"></div>
            <div class="confetti-12"></div>
            <div class="confetti-11"></div>
            <div class="confetti-10"></div>
            <div class="confetti-9"></div>
            <div class="confetti-8"></div>
            <div class="confetti-7"></div>
            <div class="confetti-6"></div>
            <div class="confetti-5"></div>
            <div class="confetti-4"></div>
            <div class="confetti-3"></div>
            <div class="confetti-2"></div>
            <div class="confetti-1"></div>
            <div class="confetti-0"></div>
          </div>
        </div>
      </template>
      
      <style scoped lang="scss">
      .container {
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        left: 0;
        overflow: hidden;
      }
      .wrapper {
        position: relative;
        height: 100vh;
        display: flex;
        flex-wrap: wrap;
      }
      
      .logo {
        display: flex;
        justify-content: center;
        margin: auto;
      }
      
      [class|='confetti'] {
        position: absolute;
      }
      
      $colors: (#d13447, #ffbf00, #263672);
      
      @for $i from 0 through 200 {
        $w: random(8);
        $l: random(100);
        .confetti-#{$i} {
          width: #{$w}px;
          height: #{$w * 0.4}px;
          background-color: nth($colors, random(3));
          top: -10%;
          left: unquote($l + '%');
          opacity: random() + 0.5;
          transform: rotate(#{random() * 360}deg);
          animation: drop-#{$i} unquote(4 + random() + 's') unquote(random() + 's');
        }
      
        @keyframes drop-#{$i} {
          100% {
            top: 110%;
            left: unquote($l + random(15) + '%');
          }
        }
      }
      </style>
      

      鏈接

      posted @ 2021-10-01 17:02  guangzan  閱讀(534)  評論(6)    收藏  舉報
      主站蜘蛛池模板: 天堂V亚洲国产V第一次| 国产偷国产偷亚洲高清午夜| 亚洲国产成人精品无码一区二区 | 高青县| 国产精品成人午夜久久| 2019亚洲午夜无码天堂| 午夜精品久久久久久99热| 午夜男女爽爽影院免费视频下载| 少妇被躁爽到高潮无码文| 亚洲天堂男人的天堂在线| 在线a级毛片无码免费真人| 国产精品无码av天天爽播放器 | 亚洲精品动漫免费二区| 视频一区二区不中文字幕| 日韩精品亚洲专在线电影| 易门县| 日韩深夜福利视频在线观看 | 国产高清在线精品一区| 国产成人一区二区不卡| 美女一区二区三区在线观看视频| 亚洲AV美女在线播放啊| 亚洲一区二区精品动漫| 男女激情一区二区三区| 国产亚洲无日韩乱码| 日本中文字幕有码在线视频| 日韩精品毛片一区到三区| 国产成人高清亚洲综合| 国内精品免费久久久久电影院97| 18禁黄无遮挡网站免费| 午夜激情福利在线免费看| 中国老太婆video| 国产成人精品av| 日本一级午夜福利免费区| 六月丁香婷婷色狠狠久久| 四虎国产精品永久入口| 日日麻批免费40分钟无码| 精品国产迷系列在线观看| 熟女系列丰满熟妇AV| 成人午夜视频一区二区无码| 男人的天堂va在线无码| 视频一区二区三区自拍偷拍|