| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- <template>
- <div ref="previewRootRef" class="mt-preview-root">
- <el-scrollbar
- ref="elScrollbarRef"
- class="w-1/1 h-1/1"
- max-height="100vh"
- @scroll="onScroll">
- <div
- class="canvasStage">
- <div
- ref="canvasAreaRef"
- :class="`canvasArea ${mtPreviewProps.canDrag ? 'cursor-grab' : ''} `"
- @mousedown="onMouseDown"
- @wheel="onMouseWheel">
- <render-core
- v-model:done-json="done_json"
- :canvas-cfg="canvas_cfg"
- :grid-cfg="grid_cfg"
- :show-ghost-dom="false"
- :canvas-dom="canvasAreaRef"
- :global-lock="false"
- :preivew-mode="true"
- :show-popover="mtPreviewProps.showPopover" />
- </div>
- </div>
- <drag-canvas
- ref="dragCanvasRef"
- :scale-ratio="canvas_cfg.scale"
- @drag-canvas-mouse-down="dragCanvasMouseDown"
- @drag-canvas-mouse-move="dragCanvasMouseMove"
- @drag-canvas-mouse-up="dragCanvasMouseUp" />
- </el-scrollbar>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
- import RenderCore from '@/components/mt-edit/components/render-core/index.vue'
- import type { IExportJson } from '../mt-edit/components/types'
- import { useExportJsonToDoneJson } from '../mt-edit/composables'
- import type { IDoneJson } from '../mt-edit/store/types'
- import { getItemAttr, previewCompareVal, setItemAttr } from '../mt-edit/utils'
- import { ElScrollbar, ElMessage, ElMessageBox } from 'element-plus'
- import DragCanvas from '@/components/mt-edit/components/drag-canvas/index.vue'
- type MtPreviewProps = {
- exportJson?: IExportJson
- canZoom?: boolean
- canDrag?: boolean
- showPopover?: boolean
- fitScreen?: boolean
- }
- const mtPreviewProps = withDefaults(defineProps<MtPreviewProps>(), {
- canDrag: true,
- canZoom: true,
- showPopover: false,
- fitScreen: true
- })
- const emits = defineEmits(['onEventCallBack'])
- const previewRootRef = ref<HTMLElement>()
- const canvasAreaRef = ref()
- const canvas_cfg = ref({
- width: 1920,
- height: 1080,
- scale: 1,
- color: '',
- img: '',
- guide: true,
- adsorp: true,
- adsorp_diff: 3,
- transform_origin: {
- x: 0,
- y: 0
- },
- drag_offset: {
- x: 0,
- y: 0
- }
- })
- const grid_cfg = ref({
- enabled: true,
- align: true,
- size: 10
- })
- const done_json = ref<IDoneJson[]>([])
- const elScrollbarRef = ref<InstanceType<typeof ElScrollbar>>()
- const dragCanvasRef = ref<InstanceType<typeof DragCanvas>>()
- let resizeObserver: ResizeObserver | undefined
- const canvas_stage_width = computed(() => canvas_cfg.value.width * canvas_cfg.value.scale)
- const canvas_stage_height = computed(() => canvas_cfg.value.height * canvas_cfg.value.scale)
- const scroll_info = reactive({
- begin_left: 0,
- begin_top: 0,
- left: 0,
- top: 0
- })
- const onScroll = ({ scrollLeft, scrollTop }: { scrollLeft: number; scrollTop: number }) => {
- scroll_info.left = scrollLeft
- scroll_info.top = scrollTop
- }
- const onMouseDown = (e: MouseEvent) => {
- if (mtPreviewProps.canDrag) {
- dragCanvasRef.value?.onMouseDown(e)
- }
- }
- const dragCanvasMouseDown = () => {
- scroll_info.begin_left = scroll_info.left
- scroll_info.begin_top = scroll_info.top
- }
- const dragCanvasMouseMove = (move_x: number, move_y: number) => {
- let new_left = scroll_info.begin_left - move_x
- let new_top = scroll_info.begin_top - move_y
- elScrollbarRef.value?.setScrollLeft(new_left)
- elScrollbarRef.value?.setScrollTop(new_top)
- }
- /**
- * 画布拖动结束事件
- */
- const dragCanvasMouseUp = () => {}
- const fitCanvasToScreen = () => {
- if (!mtPreviewProps.fitScreen) {
- return
- }
- const rootRect = previewRootRef.value?.getBoundingClientRect()
- if (!rootRect?.width || !rootRect?.height || !canvas_cfg.value.width || !canvas_cfg.value.height) {
- return
- }
- const scale = Math.min(rootRect.width / canvas_cfg.value.width, rootRect.height / canvas_cfg.value.height)
- canvas_cfg.value.scale = Number(Math.max(scale, 0.01).toFixed(4))
- }
- const fitCanvasToScreenAfterRender = async () => {
- await nextTick()
- fitCanvasToScreen()
- }
- const setItemAttrByID = (id: string, key: string, val: any) => {
- return setItemAttr(id, key, val, done_json.value)
- }
- const setItemAttrs = (info: { id: string; key: string; val: any }[]) => {
- info.forEach((f) => {
- setItemAttr(f.id, f.key, f.val, done_json.value)
- })
- }
- const getItemAttrByID = (id: string, key: string, val: any) => {
- return getItemAttr(id, key, done_json.value)
- }
- const onMouseWheel = (e: any) => {
- if (e.ctrlKey && mtPreviewProps.canZoom) {
- e.preventDefault()
- e.stopPropagation()
- if (e.deltaY > 0) {
- canvas_cfg.value.scale = (canvas_cfg.value.scale * 10 - 1) / 10
- } else if (e.deltaY < 0) {
- canvas_cfg.value.scale = (canvas_cfg.value.scale * 10 + 1) / 10
- }
- }
- }
- const setItemAttrByIDAsync = (id: string, key: string, val: any) => {
- // 通过改变属性的事件去设置值时 需要转换成宏任务 不然多个事件判断会有问题
- setTimeout(() => {
- setItemAttrByID(id, key, val)
- }, 0)
- }
- ;(window as any).$mtElMessage = ElMessage
- ;(window as any).$mtElMessageBox = ElMessageBox
- ;(window as any).$setItemAttrByID = (id: string, key: string, val: any) =>
- setItemAttrByIDAsync(id, key, val)
- ;(window as any).$getItemAttrByID = getItemAttrByID
- ;(window as any).$previewCompareVal = previewCompareVal
- ;(window as any).$mtEventCallBack = (type: string, item_id: string, ...args: any[]) =>
- emits('onEventCallBack', type, item_id, ...args)
- onMounted(() => {
- if (mtPreviewProps.exportJson) {
- const { canvasCfg, gridCfg, importDoneJson } = useExportJsonToDoneJson(
- mtPreviewProps.exportJson
- )
- canvas_cfg.value = canvasCfg
- grid_cfg.value = gridCfg
- done_json.value = importDoneJson
- fitCanvasToScreenAfterRender()
- }
- if (previewRootRef.value) {
- resizeObserver = new ResizeObserver(() => {
- fitCanvasToScreen()
- })
- resizeObserver.observe(previewRootRef.value)
- }
- })
- onBeforeUnmount(() => {
- resizeObserver?.disconnect()
- })
- const setImportJson = (exportJson: IExportJson) => {
- const { canvasCfg, gridCfg, importDoneJson } = useExportJsonToDoneJson(exportJson)
- canvas_cfg.value = canvasCfg
- grid_cfg.value = gridCfg
- done_json.value = importDoneJson
- fitCanvasToScreenAfterRender()
- return true
- }
- defineExpose({
- setItemAttrByID,
- setImportJson,
- setItemAttrs
- })
- </script>
- <style scoped>
- .mt-preview-root {
- width: 100vw;
- height: 100vh;
- overflow: hidden;
- background-color: v-bind('canvas_cfg.color || "#fff"');
- }
- .mt-preview-root :deep(.el-scrollbar__view) {
- min-width: 100%;
- min-height: 100vh;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .canvasStage {
- position: relative;
- width: v-bind('canvas_stage_width + "px"');
- height: v-bind('canvas_stage_height + "px"');
- flex: 0 0 auto;
- }
- .canvasArea {
- position: absolute;
- left: 0;
- top: 0;
- width: v-bind('canvas_cfg.width + "px"');
- height: v-bind('canvas_cfg.height + "px"');
- background-color: v-bind('canvas_cfg.color');
- background-image: v-bind('"url("+canvas_cfg.img+")"');
- transform: v-bind('`scale(${canvas_cfg.scale})`');
- transform-origin: left top;
- }
- </style>
|