fix: iframe组件改全屏按钮 可拖拽 成组时可拖拽

This commit is contained in:
huanghao1412 2024-03-25 11:16:22 +08:00
parent 8ec8791740
commit c316b34681
5 changed files with 181 additions and 9 deletions

View File

@ -15,6 +15,9 @@
></n-input-number>
</setting-item>
</setting-item-box>
<SettingItemBox name="提示" alone>
<n-text>双击全屏按钮可以全屏全屏按钮可以拖拽</n-text>
</SettingItemBox>
</collapse-item>
</template>

View File

@ -9,6 +9,6 @@ export const IframeConfig: ConfigType = {
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.INFORMATIONS,
chartFrame: ChartFrameEnum.COMMON,
chartFrame: ChartFrameEnum.STATIC,
image: 'iframe.png'
}

View File

@ -1,20 +1,42 @@
<template>
<div :style="getStyle(borderRadius)">
<iframe :src="src" :width="w" :height="h" allowfullscreen style="border-width: 0"></iframe>
<div :style="getStyle(borderRadius)" style="position: relative;">
<iframe ref="iframe" :style="iframeStyle" :src="src" :width="w" :height="h" allowfullscreen sandbox="allow-forms allow-scripts allow-same-origin allow-popups" style="border-width: 0"></iframe>
<n-button
ref="myBtn"
@mousedown="startDrag"
@mousemove="handleDrag"
@mouseup="endDrag"
@mouseout="endDrag"
@dblclick="clickBtn"
class="myBtn"
:style="{left: `${dragObj.x}px`, top: `${dragObj.y}px`}"
>
{{!isScreen ? '全屏' : '退出全屏'}}
</n-button>
</div>
</template>
<script setup lang="ts">
import { PropType, shallowReactive, watch, toRefs, ref, computed } from 'vue'
import { PropType, shallowReactive, watch, toRefs, ref, reactive, onMounted, onUnmounted, computed } from 'vue'
import { useChartDataFetch } from '@/hooks'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import {debounce} from 'lodash'
import {postMessageToParent} from "@/utils";
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
},
isGroup: {
type: Boolean
},
groupAttr: {
type: Object,
default() {
return {}
}
}
})
@ -25,6 +47,89 @@ const { borderRadius } = toRefs(props.chartConfig.option)
// dataset: ''
// })
let scale = ref({
x: 1,
y: 1
})
let handleResize = () => {
if(!document.querySelector('.go-preview-scale')) return
let scaleValue = (document.querySelector('.go-preview-scale') as HTMLElement).style.transform
const regex = /scale\((\d+(\.\d+)?), (\d+(\.\d+)?)\)/;
const matches = scaleValue.match(regex);
if (matches) {
scale.value.x = parseFloat(matches[1]);
scale.value.y = parseFloat(matches[3]);
}
}
onMounted(() => {
window.addEventListener('resize', handleResize)
window.dispatchEvent(new Event('resize'))
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
})
const emit = defineEmits(['fullScreen'])
const isScreen = ref(false)
const iframeStyle = ref({})
const iframe: any = ref(null)
const clickBtn = () => {
isScreen.value = !isScreen.value
if(isScreen.value) {
postMessageToParent({type: 'fullScreen'})
emit('fullScreen')
iframeStyle.value = { position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', zIndex: 999999 }
}
else {
postMessageToParent({type: 'fullScreen'})
emit('fullScreen')
iframeStyle.value = {}
}
}
let dragObj = reactive({
isDraging: false,
offsetX: 0,
offsetY: 0,
x: w.value - 80,
y: 20,
})
const myBtn = ref(null)
const startDrag = (e: MouseEvent) => {
dragObj.offsetX = e.offsetX * scale.value.x
dragObj.offsetY = e.offsetY * scale.value.y
dragObj.isDraging = true
}
const parentAttr = computed(() => {
if(props.isGroup) {
let obj = JSON.parse(JSON.stringify(props.groupAttr))
obj.x += props.chartConfig.attr.x
obj.y += props.chartConfig.attr.y
return obj
}
else return props.chartConfig.attr
})
const handleDrag = (e: MouseEvent) => {
if(!dragObj.isDraging) return
let parentOffsetLeft = parentAttr.value.x * scale.value.x
let parentOffsetTop = parentAttr.value.y * scale.value.y
if(!isScreen.value) {
dragObj.x = (e.clientX - dragObj.offsetX - parentOffsetLeft) / scale.value.x
dragObj.y = (e.clientY - dragObj.offsetY - parentOffsetTop) / scale.value.y
}
else {
dragObj.x = (e.clientX - dragObj.offsetX) / scale.value.x
dragObj.y = (e.clientY - dragObj.offsetY) / scale.value.y
}
}
const endDrag = () => {
dragObj.isDraging = false
}
let src = ref('')
const setValue = debounce((v: string) => {
src.value = v
@ -62,3 +167,15 @@ const getStyle = (radius: number) => {
// option.dataset = newData
// })
</script>
<style lang="scss">
.myBtn{
position: fixed;
left: 20px;
top: 20px;
z-index: 9999999;
span, div{
pointer-events: none;
}
}
</style>

View File

@ -4,6 +4,7 @@
:style="{
...getSizeStyle(groupData.attr),
...getFilterStyle(groupData.styles),
...fullScreenStyle
}"
>
<div
@ -16,7 +17,8 @@
...getStatusStyle(item.status),
...getPreviewConfigStyle(item.preview),
...getBlendModeStyle(item.styles) as any,
zIndex: zIndexMap[item.id] ? zIndexMap[item.id] : ''
zIndex: zIndexMap[item.id] ? zIndexMap[item.id] : '',
...fullScreenStyle
}"
>
<component
@ -28,17 +30,21 @@
:style="{
...getSizeStyle(item.attr),
...getFilterStyle(item.styles),
...getTransformStyle(item.styles)
...getTransformStyle(item.styles),
...fullScreenStyle
}"
:isGroup="true"
:groupAttr="groupData.attr"
v-on="useLifeHandler(item)"
@changeZIndex="(z: number | string | undefined) => changeZIndex(item.id, z)"
@fullScreen="fullScreen"
></component>
</div>
</div>
</template>
<script setup lang="ts">
import {PropType, ref, Ref} from 'vue'
import {PropType, ref, Ref, onMounted} from 'vue'
import { CreateComponentGroupType } from '@/packages/index.d'
import { animationsClass, getFilterStyle, getTransformStyle, getBlendModeStyle } from '@/utils'
import { getSizeStyle, getComponentAttrStyle, getStatusStyle, getPreviewConfigStyle } from '../../utils'
@ -63,7 +69,7 @@ const props = defineProps({
}
})
const emit = defineEmits(['changeZIndex'])
const emit = defineEmits(['changeZIndex', 'fullScreen'])
// zindex
const zIndexMap: Ref<{ [k: string] : number | string | undefined }> = ref({})
@ -71,6 +77,30 @@ const changeZIndex = (id: string, z: number | string | undefined) => {
zIndexMap.value[id] = z
emit('changeZIndex', z)
}
const fullScreen = () => {
emit('fullScreen')
_fullScreen()
}
let ifFullScreen = ref(false)
let fullScreenStyle = ref({})
// iframe
const _fullScreen = () => {
if(!ifFullScreen.value) {
ifFullScreen.value = true
fullScreenStyle.value = {
width: '100%',
height: '100%',
left: 0,
top: 0,
}
}
else {
ifFullScreen.value = false
fullScreenStyle.value = {}
}
}
</script>
<style lang="scss" scoped>

View File

@ -11,7 +11,8 @@
...getPreviewConfigStyle(item.preview),
...getBlendModeStyle(item.styles) as any,
...getSizeStyle(item.attr),
zIndex: zIndexMap[item.id] ? zIndexMap[item.id] : ''
zIndex: zIndexMap[item.id] ? zIndexMap[item.id] : '',
...fullScreenStyle,
}"
>
<!-- 分组 -->
@ -22,6 +23,7 @@
:themeSetting="themeSetting"
:themeColor="themeColor"
@changeZIndex="z => changeZIndex(item.id, z)"
@fullScreen="fullScreen"
></preview-render-group>
<!-- 单组件 -->
@ -38,6 +40,7 @@
}"
v-on="bindEvent(item)"
@changeZIndex="(z: number | string | undefined) => changeZIndex(item.id, z)"
@fullScreen="fullScreen"
></component>
<!-- v-on="useLifeHandler(item)"-->
</div>
@ -86,6 +89,25 @@ const changeZIndex = (id: string, z: number | string | undefined) => {
zIndexMap.value[id] = z
}
let ifFullScreen = ref(false)
let fullScreenStyle = ref({})
// iframe
const fullScreen = () => {
if(!ifFullScreen.value) {
ifFullScreen.value = true
fullScreenStyle.value = {
left: 0,
top: 0,
width: '100%',
height: '100%'
}
}
else {
ifFullScreen.value = false
fullScreenStyle.value = {}
}
}
//
clearMittDataPondMap()
onMounted(() => {