国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Vue實現(xiàn)圖片預覽,側邊欄懶加載,不用任何插件,簡單好用

這篇具有很好參考價值的文章主要介紹了Vue實現(xiàn)圖片預覽,側邊欄懶加載,不用任何插件,簡單好用。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

實現(xiàn)樣式

Vue實現(xiàn)圖片預覽,側邊欄懶加載,不用任何插件,簡單好用,vue,組件,vue.js,前端,canvas,pdf

需求

實現(xiàn)PDF上傳預覽,并且不能下載

第一次實現(xiàn):用vue-pdf,將上傳的文件用base64傳給前端展示
問題:

  1. 水印第一次加載有后面又沒有了。
  2. 當上傳大的pdf文件后,前端獲取和渲染又長又慢,甚至不能用

修改實現(xiàn)模式

  1. 前端上傳PDF,后端將PDF轉化成一頁一頁的圖片
  2. 前端根據page去獲取一頁一頁的PDF圖片,類似于百度文庫

實現(xiàn)思路

配合后端實現(xiàn)思路

  1. 獲取全部頁數,先把側邊欄的元素畫出來占個位置
  2. 獲取已經看到的頁數,沒有默認1
  3. 渲染上次看到的頁數,同時側邊欄滾動到相同的index位置,通過監(jiān)聽元素是否進入視口去獲取base64圖片
  4. 已經獲取回來的圖片不再去請求

主要重點難點是側邊欄懶加載、定位等比例展示圖片文章來源地址http://www.zghlxwxcb.cn/news/detail-821538.html

 <div class="pdf-viewer">
   <div class="pdf-main">
     <canvas id="pdf-view"></canvas>
   </div>
   <div class="pdf-list" :class="{ collapse: collapse }">
     <div
       class="pdf-item"
       :class="{ active: currentPage === index }"
       v-for="index in pageTotalNum"
       :key="index"
       @click="changePage(index)"
       :data-index="index"
     >
       <img :src="imgList[index - 1]" alt="" />
     </div>
   </div>
 </div>

<script>
let observer = null;
export default {
  name: "PDFView",
  data() {
    return {
      currentPage: 1, //當前頁數
      pageTotalNum: 1, //總頁數
      imgList: [], //base64圖片列表
      updateTimer: null
    };
  },
  watch: {
    /**
     * @description 監(jiān)聽當前頁變化 滾動列表到頂部
     */
    currentPage() {
      this.$nextTick(() => {
        const activeEl = document.querySelector(".pdf-list .active");
        if (activeEl) {
          document.querySelector(".pdf-list").scrollTo({
            top: activeEl.offsetTop - 20,
            behavior: "smooth",
          });
          // 解決進來會請求當前頁數 前面所有圖片
          setTimeout(() => {
            if (observer) {
              observer.disconnect();
            }
            this.isEnter();
          }, 500);
        }
        // 切換頁面 將查看區(qū)域滾動到最上面
        const mainEl = document.querySelector(".pdf-main");
        mainEl.scrollTo({
          top: 0,
        });
      });
    },
  },
  mounted() {
    this.getPageTotal();
  },
  beforeDestroy() {
    if (observer) {
      observer.disconnect();
    }
  },
  methods: {
    /**
     * @description 獲取pdf總頁數
     */
    getPageTotal() {
      const params = {
        id: this.$route.query.id,
      };
      apiGetViewPdfPageTotal(params).then((response) => {
        this.pageTotalNum = response.data;
        this.updateStudy(true);
      });
    },
    /**
     * @description 切換當前頁
     */
    changePage(index) {
      this.currentPage = index;
      this.updateStudy();
      if (this.imgList[index - 1]) {
        this.drawImage(this.imgList[index - 1]);
      } else {
        this.getPdf();
      }
    },
    /**
     * @description 上一頁
     */
    prePage() {
      let page = this.currentPage;
      if (page !== 1) {
        page = page > 1 ? page - 1 : this.pageTotalNum;
        this.currentPage = page;
        this.updateStudy();
        if (this.imgList[page - 1]) {
          this.drawImage(this.imgList[page - 1]);
        } else {
          this.getPdf();
        }
      }
    },
    /**
     * @description 下一頁
     */
    nextPage() {
      let page = this.currentPage;
      if (page !== this.pageTotalNum) {
        page = page < this.pageTotalNum ? page + 1 : 1;
        this.currentPage = page;
        this.updateStudy();
        if (this.imgList[page - 1]) {
          this.drawImage(this.imgList[page - 1]);
        } else {
          this.getPdf();
        }
      }
    },
    /**
     * @description 更新學習 flag=true第一次進入
     */
    updateStudy(flag = false) {
      const params = {
        courseId: this.$route.query.id,
        pageRate: this.currentPage,
        flag,
        totalPageRate: this.pageTotalNum,
      };
      apiUpdateStudy(params)
        .then((response) => {
          this.currentPage = response.data.pageRate;
          if (flag) {
            this.updateTimer = setInterval(() => {
              this.updateStudy();
            }, 1000 * 10);
          }
          if (flag) {
            this.getPdf();
            // 解決第一頁進來不請求的問題,一頁大概能展示4-5張
            if (this.currentPage < 5) {
              this.isEnter();
            }
          }
        })
    },
    /**
     * @description 查看資料
     */
    getPdf() {
      const params = {
        id: this.$route.query.id,
        page: this.currentPage,
      };
      apiGetPdf(params).then((response) => {
        let base64 = "data:image/png;base64," + response.data;
        this.drawImage(base64);
      });
    },
    /**
     * @description 將base64圖片 畫到canvas上
     */
    drawImage(base64) {
      const canvas = document.getElementById("pdf-view");
      const context = canvas.getContext("2d");
      const image = new Image();
      image.src = base64;
      image.onload = () => {
        const proportion = image.width / image.height;
        // 獲取style設置width:100% 的canvas寬度
        const canvasWidth = canvas.offsetWidth;
        // 圖片寬度與canvas寬度比例
        const canvasWidthProportion = image.width / canvasWidth;
        // canvas寬度設置為寬度
        canvas.width = image.width;
        // 根據圖片比例和寬度比例計算出canvas高度
        canvas.height = (canvasWidth / proportion) * canvasWidthProportion;
        context.drawImage(image, 0, 0);
      };
    },
    /**
     * @description 監(jiān)聽元素進入視口
     */
    isEnter() {
      observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          const target = entry.target;
          const index = target.dataset.index;
          if (entry.isIntersecting) {
            if (!this.imgList[index - 1]) {
              this.getImgList(index);
            }
          } else {
            // console.log("元素離開視口", index);
          }
        });
      });
      this.$nextTick(() => {
      //將所有側邊欄的元素進行監(jiān)聽
        const els = document.querySelectorAll(".pdf-item");
        Array.from(els).forEach((el) => {
          observer.observe(el);
        });
      });
    },
    /**
     * @description 滾動獲取圖片
     */
    getImgList(index) {
      const params = {
        id: this.$route.query.id,
        page: index,
      };
      apiGetPdf(params).then((response) => {
        let base64 = "data:image/png;base64," + response.data;
        this.imgList[index - 1] = base64;
        // 解決請求回來頁面沒更新的問題
        this.$forceUpdate();
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.pdf-container {
  width: 100%;
  height: 100%;
  color: #999;
}
.pdf-viewer {
  width: 100%;
  height: calc(100vh - 50px - 30px - 60px - 6px);
  position: relative;
  display: flex;
}
.pdf-list {
  width: 240px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 20px;
  background: #000;
  box-sizing: border-box;
  // transition: all 0.3s ease-in-out;
  border-left: 1px solid #999;
  &::-webkit-scrollbar {
    width: 0px;
  }
  .pdf-item {
    height: 183px;
    min-height: 183px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    overflow: hidden;
    &:hover {
      ::v-deep img {
        transition: all 0.5s ease-in-out;
        transform: scale(1.1);
      }
    }
    &.active {
      box-shadow: 0px 0px 0px 4px #e6a23c;
    }
    &:not(:last-child) {
      margin-bottom: 10px;
    }
    img {
      pointer-events: none;
      width: 100%;
      // height: 100%;
    }
  }
  &.collapse {
    width: 0;
    padding: 0;
  }
}
.pdf-main {
  flex: 1;
  // width: 100%;
  // height: 100%;
  overflow-y: auto;
  background: #000;
  position: relative;
  padding: 10px 0;
  &::-webkit-scrollbar {
    width: 0px;
  }
}
.handle-btn {
  background: #000;
  display: flex;
  font-size: 12px;
  position: relative;
  height: 60px;
  padding: 0 6px;
  border-bottom: 1px solid #999;
  .right {
    width: 240px;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    font-size: 32px;
  }
  .main {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 32px;
    margin-left: 250px;
    .pagination {
      display: flex;
      align-items: center;
      margin: 0 10px;
      .pagination-info {
        font-size: 14px;
        margin: 0 8px;
      }
    }
    .zoom {
      display: flex;
      align-items: center;
      margin: 0 10px;
      .scale {
        font-size: 14px;
        margin: 0 8px;
      }
    }
  }
  .tips {
    color: #e6a23c;
    font-size: 12px;
  }
  .start-test {
    display: flex;
    align-items: center;
  }
  .time {
    position: absolute;
    left: 6px;
    top: 50%;
    transform: translateY(-50%);
    > span {
      display: inline-block;
      margin-left: 10px;
    }
  }
}
i {
  cursor: pointer;
  &:hover {
    color: #fff;
  }
}
#pdf-view {
  width: 100%;
  // height: 100%;
  padding: 10px;
}
</style>

到了這里,關于Vue實現(xiàn)圖片預覽,側邊欄懶加載,不用任何插件,簡單好用的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包