vue2前端使用图片展现视频,无法销毁请求

实现思路,使用canvas绘制图像,然后使用动画帧刷新页面

javascript 复制代码
<template>
  <canvas ref="imageCanvas" :style="canvasStyle"></canvas>
</template>

<script>
export default {
  props: {
    info: {
      type: Object,
      default: () => ({ url: '', index: '' }),
    },
  },
  data() {
    return {
      currentImage: null,
      isFullScreen: false,
      canvas: null,
      ctx: null,
      canvasStyle: {
        height: '100%',
        width: '100%',
        cursor: 'pointer',
        transition: 'transform 0.3s ease-in-out',
      },
      animationFrameId: null,
    };
  },
  mounted() {
    this.initCanvas();
    this.startAnimation();
    this.addEventListeners();
  },
  watch: {
    'info.url'(newVal) {
      if (newVal) {
        this.loadImage();
      }
    },
  },
  beforeDestroy() {
    this.stopAnimation();
    this.destroyCanvas();
    this.destroyImage();
    this.removeEventListeners();
  },
  methods: {
    initCanvas() {
      this.canvas = this.$refs.imageCanvas;
      this.ctx = this.canvas.getContext('2d');
    },
    loadImage() {
      if (!this.info || !this.info.url) return;

      this.currentImage = new Image();
      this.currentImage.onload = () => {
        this.drawCanvas();
      };
      this.currentImage.src = this.info.url;
    },
    drawCanvas() {
      if (this.currentImage) {
        this.canvas.width = this.currentImage.width;
        this.canvas.height = this.currentImage.height;
        this.ctx.drawImage(this.currentImage, 0, 0, this.canvas.width, this.canvas.height);
      }
    },
    startAnimation() {
      const animate = () => {
        this.loadImage();
        this.animationFrameId = requestAnimationFrame(animate);
      };
      this.animationFrameId = requestAnimationFrame(animate);
    },
    stopAnimation() {
      if (this.animationFrameId) {
        cancelAnimationFrame(this.animationFrameId);
        this.animationFrameId = null;
      }
    },
    addEventListeners() {
      if (this.canvas) {
        this.canvas.addEventListener('dblclick', this.toggleFullscreen);
      }
      document.addEventListener('fullscreenchange', this.handleFullscreenChange);
    },
    removeEventListeners() {
      if (this.canvas) {
        this.canvas.removeEventListener('dblclick', this.toggleFullscreen);
      }
      document.removeEventListener('fullscreenchange', this.handleFullscreenChange);
    },
    toggleFullscreen() {
      if (!this.isFullScreen) {
        if (this.canvas.requestFullscreen) {
          this.canvas.requestFullscreen();
        } else if (this.canvas.mozRequestFullScreen) {
          this.canvas.mozRequestFullScreen();
        } else if (this.canvas.webkitRequestFullscreen) {
          this.canvas.webkitRequestFullscreen();
        } else if (this.canvas.msRequestFullscreen) {
          this.canvas.msRequestFullscreen();
        }
      } else {
        if (document.exitFullscreen) {
          document.exitFullscreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        } else if (document.webkitExitFullscreen) {
          document.webkitExitFullscreen();
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen();
        }
      }
    },
    handleFullscreenChange() {
      this.isFullScreen = !this.isFullScreen;
      if (this.isFullScreen) {
        this.canvasStyle = {
          position: 'fixed',
          top: '0',
          left: '0',
          width: '100vw',
          height: '100vh',
          backgroundColor: 'rgba(0, 0, 0, 0.9)',
          cursor: 'default',
          objectFit: 'contain',
          objectPosition: 'center',
          transition: 'transform 0.3s ease-in-out',
          zIndex: 9999,
        };
        document.body.style.overflow = 'hidden';
      } else {
        this.canvasStyle = {
          height: '100%',
          width: '100%',
          cursor: 'pointer',
          transition: 'transform 0.3s ease-in-out',
        };
        document.body.style.overflow = 'auto';
      }
    },
    destroyCanvas() {
      if (this.canvas) {
        this.canvas.width = 0;
        this.canvas.height = 0;
        this.ctx = null;
        this.canvas = null;
      }
    },
    destroyImage() {
      if (this.currentImage) {
        this.currentImage.onload = null;
        this.currentImage.onerror = null;
        this.currentImage.src = '';
        this.currentImage = null;
      }
    },
  },
};
</script>

<style scoped>
/* 可以根据需要添加 scoped 样式 */
</style>
相关推荐
i听风逝夜6 分钟前
Web 3D地球实时统计访问来源
前端·后端
iMonster10 分钟前
React 组件的组合模式之道 (Composition Pattern)
前端
呐呐呐呐呢18 分钟前
antd渐变色边框按钮
前端
元直数字电路验证37 分钟前
Jakarta EE Web 聊天室技术梳理
前端
wadesir40 分钟前
Nginx配置文件CPU优化(从零开始提升Web服务器性能)
服务器·前端·nginx
牧码岛41 分钟前
Web前端之canvas实现图片融合与清晰度介绍、合并
前端·javascript·css·html·web·canvas·web前端
灵犀坠43 分钟前
前端面试八股复习心得
开发语言·前端·javascript
9***Y4844 分钟前
前端动画性能优化
前端
网络点点滴1 小时前
Vue3嵌套路由
前端·javascript·vue.js
牧码岛1 小时前
Web前端之Vue+Element打印时输入值没有及时更新dom的问题
前端·javascript·html·web·web前端