关于使用Vue3DraggableResizable组件实现拖拉拽功能内嵌3D模型iframe,出现功能混乱问题 解决思路~

1,203 阅读3分钟

前情提要:最近公司项目业务需求==>能实现在内嵌iframe标签上悬浮一个视频窗口,方便用户观看。
ps:需求过去很久了,最近有时间更新下帖子

1、需求思路

1.1、业务需求初步实现思路很简单,在iframe盒子上定位一个video标签就ok。

1.2、实现的时候因为要实现视频盒子拖拉拽功能,所以采用插件Vue3DraggableResizable,使用也比较简单,开箱即用,

2、下载依赖

npm install --save vue-draggable-resizable

3、vue组件使用

drag.vue

<template>
  <Vue3DraggableResizable :initW="300" :initH="170" v-model:x="x" v-model:y="y" v-model:w="w" v-model:h="h"
    v-model:active="active" :draggable="true" :resizable="true" @activated="print('activated')"
    @deactivated="print('deactivated')" @drag-start="print('drag-start')"
    @resize-start="print('resize-start')" @dragging="print('dragging')" @resizing="print('resizing')"
    @drag-end="print('drag-end')" @resize-end="print('resize-end')">
    <video style="height: 100%; width: 100%" :src="videoUrl" autoplay loop muted controls></video>
  </Vue3DraggableResizable>
</template>

<script setup>
import { ref, } from 'vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//default styles
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'

const x = ref(1150)
const y = ref(510)
const w = ref(100)
const h = ref(100)
const active = ref(false)

function print(val) {
  console.log(val)
}


defineProps({
  videoUrl: {
    type: String,
    default: () => "https://media.w3.org/2010/05/sintel/trailer.mp4"
  },
})

</script>
<style></style>

4、问题

需求:在iframe上悬浮一个视频。
实现层面:在iframe的盒子内,加一个video的盒子定位到需求的位置,video盒子支持拖拉拽位置、放大缩小功能。
ps:上述代码基本已经实现功能,在觉得不会出问题的时候bug来了

bug描述:因为iframe中的内容是3d模型,内部有许多功能可以操作模型旋转、爆炸等等...., 在拖拽video盒子的时候鼠标在iframe盒子上会出现错乱的问题,拖拽video功能失效。ps:查询文档、个人理解应该是,因为video盒子实在iframe盒子上层,你的mouseenter事件在移出video盒子时,刚好进入iframe盒子导致浏览器不知道是执行那个事件,导致Vue3DraggableResizable的功能失效。

5、解决思路

在video标签缩放的时候,不是因为鼠标移入到iframe盒子会出现功能失效的问题吗?
简单粗暴:在移动缩放的时候弄个透明div盒子把iframe盒子遮住就OK了

父组件

<div class="cover-main-left-model">
  <iframe
    ref="iframe"
    frameborder="0"
    width="100%"
    height="100%"
    style="width: 100%; height: 100%"
    class="iframe"
    :key="argument"
    :src="argument">
  </iframe>
  <!--遮罩-->
  <div v-show="isResizing" style="width: 100%;height: 100%;position: absolute;top: 0;left: 0;"></div>
  <Drag 
    v-if="processData.processResourceUrl" 
    :videoUrl="processData.processResourceUrl" 
    style="z-index: 999;" 
    @changeisResizing="changeisResizing"/>
</div>
<script setup lang='ts'>
import { ref } from 'vue';
const isResizing = ref(false)
 // 改变透明盒子显隐藏来确保拖拉拽功能正常
function changeisResizing(value: boolean){
  isResizing.value = value
}
</script>
        

drag.vue

<template>
  <Vue3DraggableResizable :initW="300" :initH="170" v-model:x="x" v-model:y="y" v-model:w="w" v-model:h="h"
    v-model:active="active" :draggable="true" :resizable="true" @activated="print('activated')"
    @deactivated="print('deactivated')" @drag-start="print('drag-start')"
    @resize-start="print('resize-start'), handleChange(true)" @dragging="print('dragging')" @resizing="print('resizing')"
    @drag-end="print('drag-end')" @resize-end="print('resize-end'), handleChange(false)">
    <video style="height: 100%; width: 100%" :src="videoUrl" autoplay loop muted controls></video>
  </Vue3DraggableResizable>
</template>

<script setup>
import { defineComponent, ref, } from 'vue'
import Vue3DraggableResizable from 'vue3-draggable-resizable'
//default styles
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'

const x = ref(1150)
const y = ref(510)
const w = ref(100)
const h = ref(100)
const active = ref(false)

function print(val) {
  console.log(val)
}

const emits = defineEmits(["changeisResizing"]);

defineProps({
  videoUrl: {
    type: String,
    default: () => "https://media.w3.org/2010/05/sintel/trailer.mp4"
  },
})


// 触发父组件事件
function handleChange(value) {
  emits("changeisResizing", value);
}
</script>
<style></style>

只是个人见解,提供一个解决思路,也有别的解决方案欢迎探讨~~~