当前位置: 首页 > news >正文

【sgThumbPreviewTip】自定义组件:缩略图预览组件,移入缩略图等待1秒后出现浮动气泡框显示更大的缩略图或预览播放视频

sgThumbPreviewTip 

<!--缩略图预览组件-->
<template>
  <div :class="$options.name" v-if="visible">
    <!-- 提示框 -->
    <div
      class="float-tip"
      ref="floatTip"
      :style="floatTipData.style"
      :show="floatTipData.show"
      :theme="theme"
    >
      <div class="container" :style="containerData.style">
        <template v-if="form.hasOwnProperty('img')">
          <img ref="img" :src="form.img" @load="loadImg" />
        </template>
        <template v-else-if="form.hasOwnProperty('video')">
          <video
            ref="video"
            autoplay
            loop
            muted
            preload
            playsinline="true"
            webkit-playsinline="true"
            :src="form.video"
            @canplay="loadVideo"
          />
        </template>
        <template v-else-if="form.hasOwnProperty('text')">
          <div v-html="form.text"></div>
        </template>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "sgThumbPreviewTip",
  components: {},
  data() {
    return {
      theme: `default`, //主题
      form: {},
      visible: false,
      floatTipData: {
        show: false,
        style: {},
      },
      containerData: { style: {} },
      maxWidth: 400, //最大宽度
      maxHeight: 400, //最大高度
      padding: 5, //边界
      load: null,
    };
  },
  props: ["value", "data"],
  computed: {},
  watch: {
    value: {
      handler(d) {
        this.visible = d;
      },
      deep: true,
      immediate: true,
    },
    visible(d) {
      if (d) {
        this.g(this.data);
      } else {
        this.floatTipData.show = false;
      }
      this.$emit("input", d);
    },

    data: {
      handler(newValue, oldValue) {
        //console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
        if (Object.keys(newValue || {}).length) {
          this.g(newValue);
        }
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
    floatTipData: {
      handler(newValue, oldValue) {
        //console.log(`深度监听${this.$options.name}:`, newValue, oldValue);
        if (Object.keys(newValue || {}).length) {
          if (newValue.show) {
            this.$emit(`load`, newValue);
            this.load && this.load(newValue);
          }
        }
      },
      deep: true, //深度监听
      immediate: true, //立即执行
    },
  },
  created() {},
  mounted() {},
  beforeDestroy() {},
  methods: {
    g(newValue = this.form) {
      this.form = newValue || {};
      this.$g.convertForm2ComponentParam(`theme`, this);
      this.$g.convertForm2ComponentParam(`load`, this);
      this.$g.convertForm2ComponentParam(`maxWidth`, this);
      this.$g.convertForm2ComponentParam(`maxHeight`, this);
      this.$g.convertForm2ComponentParam(`padding`, this);

      this.$nextTick(() => {
        if (this.$el && this.$el.style) {
          this.$el.style.setProperty("--maxWidth", `${this.maxWidth}px`); //js往css传递局部参数
          this.$el.style.setProperty("--maxHeight", `${this.maxHeight}px`); //js往css传递局部参数
          this.$el.style.setProperty("--padding", `${this.padding}px`); //js往css传递局部参数
        }
      });
      this.mouseFollowFloatTip(this.form.mouseEvent);
    },
    loadImg(d) {
      let img = this.$refs.img;
      this.containerData.style = this.$g.calcScaleWidthHeigth({
        containerWidth: this.maxWidth, //容器宽度
        containerHeight: this.maxHeight, //容器高度
        originWidth: img.naturalWidth, //图片原始宽度
        originHeight: img.naturalHeight, //图片原始高度
      });
      this.floatTipData.show = true;
    },
    loadVideo(d) {
      let video = this.$refs.video;
      this.containerData.style = this.$g.calcScaleWidthHeigth({
        containerWidth: this.maxWidth, //容器宽度
        containerHeight: this.maxHeight, //容器高度
        originWidth: video.videoWidth, //图片原始宽度
        originHeight: video.videoHeight, //图片原始高度
      });
      this.floatTipData.show = true;
    },
    mouseFollowFloatTip(e) {
      if (!e) return;
      this.$nextTick(() => {
        let floatTip = this.$refs.floatTip;
        if (floatTip) {
          // 鼠标跟随tip
          let x = e.clientX,
            y = e.clientY;
          let mouseOffsetX = 20,
            mouseOffsetY = 20;
          let left = x + mouseOffsetX;
          let top = y + mouseOffsetY;
          let floatTipRect = floatTip.getBoundingClientRect();
          //边界判断
          left + floatTipRect.width > innerWidth &&
            (left = innerWidth - floatTipRect.width);
          top + floatTipRect.height > innerHeight &&
            (top = innerHeight - floatTipRect.height);
          this.floatTipData.style = { left: `${left}px`, top: `${top}px` };
          this.text && (this.floatTipData.show = true);
        }
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.sgThumbPreviewTip {
  $maxWidth: var(--maxWidth); //最大宽度
  $maxHeight: var(--maxHeight); //最大高度
  $padding: var(--padding); //边界
  // ----------------------------------------
  position: fixed;
  z-index: 999999;
  left: 0;
  top: 0;
  pointer-events: none;
  // 气泡框样式----------------------------------------
  .float-tip {
    transition: opacity 0.382s, left 0.05s, top 0.05s;
    position: absolute;
    word-wrap: break-word;
    word-break: break-all;
    white-space: break-spaces;
    font-size: 12px;
    pointer-events: none;
    border-radius: 4px;
    background-color: white;
    box-shadow: 0 5px 20px 0 #00000022;
    box-sizing: border-box;
    padding: $padding;
    opacity: 0;
    &[show] {
      opacity: 1;
    }
    .container {
      border-radius: 4px;
      overflow: hidden;
      width: $maxWidth;
      height: $maxHeight;
      max-width: $maxWidth;
      max-height: $maxHeight;
      img,
      video {
        width: 100%;
        height: 100%;
        object-fit: contain;
        object-position: center;
        background: transparent;
      }
    }

    //windows7主题
    &[theme="win7"] {
      border-radius: 8px;
      background: linear-gradient(
        180deg,
        #fafafa1a 0%,
        #ffffff66 30%,
        #46464633 40%,
        #aaaaaa1a 100%
      ) !important;
      box-shadow: 0 0 0 1px #ffffffcc, 0 0 8px 3px #0a0a0acc;
      backdrop-filter: blur(7px) brightness(0.9);
      .container {
        background-color: white;
      }
    }
  }
}
</style>

demo

<template>
  <div :class="$options.name">
    <img
      src="https://www.baidu.com/img/flexible/logo/pc/result.png"
      @mouseover="mouseoverThumb"
      @mousemove="mousemoveThumb"
      @mouseout="mouseoutThumb"
    />
    <!-- 预览缩略图 -->
    <sgThumbPreviewTip ref="sgThumbPreviewTip" />
  </div>
</template>
<script>
import sgThumbPreviewTip from "@/vue/components/admin/sgThumbPreviewTip";
export default {
  components: {
    sgThumbPreviewTip,
  },
  data() {
    return {
      // 全局缩略图气泡框----------------------------------------
      mouseoverThumbTimeout: null, //记录鼠标移入封面的时间
      mousemoveThumbData: null,
      // ----------------------------------------
    };
  },
  props: ["data"],
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  destroyed() {},
  methods: {
    // 移入封面预览气泡框■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    get_sgThumbPreviewTip() {
      return this.$refs.sgThumbPreviewTip;
    },
    showThumbTip({ w = true, d = {} } = {}) {
      let sgThumbPreviewTip = this.get_sgThumbPreviewTip();
      if (sgThumbPreviewTip) {
        sgThumbPreviewTip.g(d);
        sgThumbPreviewTip.visible = true;
      }
    },
    hideThumbTip() {
      let sgThumbPreviewTip = this.get_sgThumbPreviewTip();
      sgThumbPreviewTip.visible = false;
    },

    mouseoverThumb(d) {
      clearTimeout(this.mouseoverThumbTimeout);
      this.mouseoverThumbTimeout = setTimeout(() => {
        this.showThumbTip({ d: this.mousemoveThumbData });
      }, 1000); // 停留时长
    },
    mousemoveThumb(d) {
      let mousemoveThumbData = {
        mouseEvent: d,
        img: `https://www.baidu.com/img/flexible/logo/pc/result@2.png`,
        // theme: `win7`, //主题
      };
      this.mousemoveThumbData = mousemoveThumbData; //传入气泡框的内容
      this.get_sgThumbPreviewTip().visible &&
        this.showThumbTip({ d: this.mousemoveThumbData });
    },
    mouseoutThumb(d) {
      clearTimeout(this.mouseoverThumbTimeout);
      this.hideThumbTip();
    },
  },
};
</script>

引用了【推荐】实现跟随鼠标移动的浮动提示框、浮动气泡框、Tip效果_实现鼠标移动提示框也移动-CSDN博客文章浏览阅读2.9k次,点赞3次,收藏13次。这个示例展示了如何在Vue应用中创建一个跟随鼠标移动的提示框。当鼠标悬停在特定元素上时,提示框会显示该元素内的文本,并在鼠标离开时隐藏。实现包括CSS样式和JavaScript事件监听,用于调整提示框的位置以避免超出窗口边界。 https://blog.csdn.net/qq_37860634/article/details/127115152

相关文章:

  • HTTP协议手写服务器
  • 设计模式之适配器模式(二):STL适配器
  • RISC-V AIA学习3---APLIC 第二部分(APLIC 中断域的内存映射控制区域)
  • 第五章.图论
  • iOS GCD
  • C++ STL常用算法之常用排序算法
  • Vue3+Vite获取原始文版并展示在页面内
  • 030-gprof
  • 群体智能优化算法-算术优化算法(Arithmetic Optimization Algorithm, AOA,含Matlab源代码)
  • 清晰易懂的Trae实现为AI编程从安装到实战开发ToDoList
  • Redis:持久化 RDB快照 AOF日志
  • leetcode每日一题:使所有字符相等的最小成本
  • Java面试黄金宝典24
  • 软考《信息系统运行管理员》- 6.2 信息系统硬件的安全运维
  • Oracle数据库数据编程SQL<2.1 DDL、DCL表、列及约束>
  • 数据仓库 - 转转 - 一面凉经
  • JavaScript基础-navigator 对象
  • git-- github的使用--账户和本地连接
  • Python实现图片文字识别-OCR
  • 【面试八股】:CAS指令
  • 网站美工设计收费/方象科技的企业愿景
  • 嘉兴手机网站开发费用/中国十大公关公司排名
  • 做百度手机网站点击/西安关键词seo
  • 宣城网站推广/十大搜索引擎排行榜
  • 萧山好的做网站的公司/怎么样做一个自己的网站
  • 苏州相城做网站的/seo优化方案