update
This commit is contained in:
parent
a7176f8be6
commit
7246f89bc0
|
@ -43,7 +43,7 @@ export default {
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.mouse-selection {
|
.mouse-selection {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba($themeColor, 0.25);
|
background: rgba(150, 150, 150, 0.25);
|
||||||
z-index: 200;
|
z-index: 200;
|
||||||
|
|
||||||
&.quadrant-1 {
|
&.quadrant-1 {
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { ref, computed, onMounted, onUnmounted, Ref } from 'vue'
|
||||||
|
import { useStore } from 'vuex'
|
||||||
|
import { State } from '@/store/state'
|
||||||
|
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
|
|
||||||
|
export default (canvasRef: Ref<HTMLElement | null>) => {
|
||||||
|
const canvasScale = ref(1)
|
||||||
|
const viewportLeft = ref(0)
|
||||||
|
const viewportTop = ref(0)
|
||||||
|
|
||||||
|
const store = useStore<State>()
|
||||||
|
const editorAreaShowScale = computed(() => store.state.editorAreaShowScale)
|
||||||
|
|
||||||
|
const setViewportSize = () => {
|
||||||
|
if(!canvasRef.value) return
|
||||||
|
const canvasWidth = canvasRef.value.clientWidth
|
||||||
|
const canvasHeight = canvasRef.value.clientHeight
|
||||||
|
|
||||||
|
if(canvasHeight / canvasWidth > VIEWPORT_ASPECT_RATIO) {
|
||||||
|
const viewportActualWidth = canvasWidth * (editorAreaShowScale.value / 100)
|
||||||
|
canvasScale.value = viewportActualWidth / VIEWPORT_SIZE
|
||||||
|
viewportLeft.value = (canvasWidth - viewportActualWidth) / 2
|
||||||
|
viewportTop.value = (canvasHeight - viewportActualWidth * VIEWPORT_ASPECT_RATIO) / 2
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const viewportActualHeight = canvasHeight * (editorAreaShowScale.value / 100)
|
||||||
|
canvasScale.value = viewportActualHeight / (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO)
|
||||||
|
viewportLeft.value = (canvasWidth - viewportActualHeight / VIEWPORT_ASPECT_RATIO) / 2
|
||||||
|
viewportTop.value = (canvasHeight - viewportActualHeight) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver(setViewportSize)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if(canvasRef.value) resizeObserver.observe(canvasRef.value)
|
||||||
|
})
|
||||||
|
onUnmounted(() => {
|
||||||
|
if(canvasRef.value) resizeObserver.unobserve(canvasRef.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
canvasScale,
|
||||||
|
viewportLeft,
|
||||||
|
viewportTop,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
import { ref, reactive, Ref, toRefs } from 'vue'
|
||||||
|
|
||||||
|
export default (e: MouseEvent, viewportRef: Ref<HTMLElement | null>, canvasScale: number) => {
|
||||||
|
const isMouseDown = ref(false)
|
||||||
|
const mouseSelectionState = reactive({
|
||||||
|
isShow: false,
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
quadrant: 4,
|
||||||
|
})
|
||||||
|
const startMousePosition = reactive({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
const minSelectionRange = 5
|
||||||
|
|
||||||
|
if(!viewportRef.value) return
|
||||||
|
|
||||||
|
isMouseDown.value = true
|
||||||
|
const viewportRect = viewportRef.value.getBoundingClientRect()
|
||||||
|
|
||||||
|
startMousePosition.x = e.pageX
|
||||||
|
startMousePosition.y = e.pageY
|
||||||
|
|
||||||
|
mouseSelectionState.top = (startMousePosition.x - viewportRect.y) / canvasScale
|
||||||
|
mouseSelectionState.left = (startMousePosition.y - viewportRect.x) / canvasScale
|
||||||
|
|
||||||
|
const mousemoveListener = (e: MouseEvent) => {
|
||||||
|
if(!isMouseDown.value) return
|
||||||
|
|
||||||
|
const currentPageX = e.pageX
|
||||||
|
const currentPageY = e.pageY
|
||||||
|
|
||||||
|
const offsetWidth = (currentPageX - startMousePosition.x) / canvasScale
|
||||||
|
const offsetHeight = (currentPageY - startMousePosition.y) / canvasScale
|
||||||
|
|
||||||
|
const width = Math.abs(offsetWidth)
|
||||||
|
const height = Math.abs(offsetHeight)
|
||||||
|
|
||||||
|
if(width < minSelectionRange || height < minSelectionRange) return
|
||||||
|
|
||||||
|
let quadrant = 0
|
||||||
|
if(offsetWidth > 0 && offsetHeight > 0) quadrant = 4
|
||||||
|
else if(offsetWidth < 0 && offsetHeight < 0) quadrant = 1
|
||||||
|
else if(offsetWidth > 0 && offsetHeight < 0) quadrant = 2
|
||||||
|
else if(offsetWidth < 0 && offsetHeight > 0) quadrant = 3
|
||||||
|
|
||||||
|
mouseSelectionState.isShow = true
|
||||||
|
mouseSelectionState.quadrant = quadrant
|
||||||
|
mouseSelectionState.width = width
|
||||||
|
mouseSelectionState.height = height
|
||||||
|
}
|
||||||
|
const mouseupListener = () => {
|
||||||
|
isMouseDown.value = false
|
||||||
|
mouseSelectionState.isShow = false
|
||||||
|
|
||||||
|
document.removeEventListener('mousemove', mousemoveListener)
|
||||||
|
document.removeEventListener('mouseup', mouseupListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', mousemoveListener)
|
||||||
|
document.addEventListener('mouseup', mouseupListener)
|
||||||
|
|
||||||
|
return { ...toRefs(mouseSelectionState) }
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
height: viewportStyles.height + 'px',
|
height: viewportStyles.height + 'px',
|
||||||
left: viewportStyles.left + 'px',
|
left: viewportStyles.left + 'px',
|
||||||
top: viewportStyles.top + 'px',
|
top: viewportStyles.top + 'px',
|
||||||
transform: `scale(${viewportStyles.scale})`,
|
transform: `scale(${canvasScale})`,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<MouseSelection
|
<MouseSelection
|
||||||
|
@ -49,6 +49,7 @@ import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
import { getImageDataURL } from '@/utils/image'
|
import { getImageDataURL } from '@/utils/image'
|
||||||
|
|
||||||
import useDropImage from '@/hooks/useDropImage'
|
import useDropImage from '@/hooks/useDropImage'
|
||||||
|
import useSetViewportSize from './hooks/useSetViewportSize'
|
||||||
|
|
||||||
import MouseSelection from './MouseSelection.vue'
|
import MouseSelection from './MouseSelection.vue'
|
||||||
import SlideBackground from './SlideBackground.vue'
|
import SlideBackground from './SlideBackground.vue'
|
||||||
|
@ -62,9 +63,11 @@ export default defineComponent({
|
||||||
AlignmentLine,
|
AlignmentLine,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
const store = useStore<State>()
|
||||||
const viewportRef = ref<HTMLElement | null>(null)
|
const viewportRef = ref<HTMLElement | null>(null)
|
||||||
const isShowGridLines = ref(false)
|
const isShowGridLines = ref(false)
|
||||||
const alignmentLines = ref<AlignmentLineProps[]>([])
|
const alignmentLines = ref<AlignmentLineProps[]>([])
|
||||||
|
const currentSlide = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
const dropImageFile = useDropImage(viewportRef)
|
const dropImageFile = useDropImage(viewportRef)
|
||||||
watch(dropImageFile, () => {
|
watch(dropImageFile, () => {
|
||||||
|
@ -75,51 +78,15 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const viewportStyles = reactive({
|
const canvasRef = ref<HTMLElement | null>(null)
|
||||||
|
const { canvasScale, viewportLeft, viewportTop } = useSetViewportSize(canvasRef)
|
||||||
|
const viewportStyles = computed(() => ({
|
||||||
width: VIEWPORT_SIZE,
|
width: VIEWPORT_SIZE,
|
||||||
height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,
|
height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,
|
||||||
left: 0,
|
left: viewportLeft.value,
|
||||||
top: 0,
|
top: viewportTop.value,
|
||||||
scale: 1,
|
}))
|
||||||
})
|
|
||||||
|
|
||||||
const canvasRef = ref<Element | null>(null)
|
|
||||||
const canvasScale = ref(1)
|
|
||||||
|
|
||||||
const store = useStore<State>()
|
|
||||||
const currentSlide = computed(() => store.getters.currentSlide)
|
|
||||||
|
|
||||||
const editorAreaShowScale = computed(() => store.state.editorAreaShowScale)
|
|
||||||
const setViewportSize = () => {
|
|
||||||
if(!canvasRef.value) return
|
|
||||||
const canvasWidth = canvasRef.value.clientWidth
|
|
||||||
const canvasHeight = canvasRef.value.clientHeight
|
|
||||||
|
|
||||||
if(canvasHeight / canvasWidth > VIEWPORT_ASPECT_RATIO) {
|
|
||||||
const viewportActualWidth = canvasWidth * (editorAreaShowScale.value / 100)
|
|
||||||
canvasScale.value = viewportActualWidth / VIEWPORT_SIZE
|
|
||||||
viewportStyles.scale = canvasScale.value
|
|
||||||
viewportStyles.left = (canvasWidth - viewportActualWidth) / 2
|
|
||||||
viewportStyles.top = (canvasHeight - viewportActualWidth * VIEWPORT_ASPECT_RATIO) / 2
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const viewportActualHeight = canvasHeight * (editorAreaShowScale.value / 100)
|
|
||||||
canvasScale.value = viewportActualHeight / (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO)
|
|
||||||
viewportStyles.scale = canvasScale.value
|
|
||||||
viewportStyles.left = (canvasWidth - viewportActualHeight / VIEWPORT_ASPECT_RATIO) / 2
|
|
||||||
viewportStyles.top = (canvasHeight - viewportActualHeight) / 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const resizeObserver = new ResizeObserver(setViewportSize)
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if(canvasRef.value) resizeObserver.observe(canvasRef.value)
|
|
||||||
})
|
|
||||||
onUnmounted(() => {
|
|
||||||
if(canvasRef.value) resizeObserver.unobserve(canvasRef.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
const mouseSelectionState = reactive({
|
const mouseSelectionState = reactive({
|
||||||
isShow: false,
|
isShow: false,
|
||||||
top: 0,
|
top: 0,
|
||||||
|
@ -205,26 +172,6 @@ export default defineComponent({
|
||||||
text: '粘贴',
|
text: '粘贴',
|
||||||
subText: 'Ctrl + V',
|
subText: 'Ctrl + V',
|
||||||
},
|
},
|
||||||
{ divider: true },
|
|
||||||
{
|
|
||||||
text: '参考线',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
text: '打开',
|
|
||||||
disable: isShowGridLines.value,
|
|
||||||
icon: isShowGridLines.value ? 'icon-check' : '',
|
|
||||||
iconPlacehoder: true,
|
|
||||||
action: () => isShowGridLines.value = true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '关闭',
|
|
||||||
disable: !isShowGridLines.value,
|
|
||||||
icon: !isShowGridLines.value ? 'icon-check' : '',
|
|
||||||
iconPlacehoder: true,
|
|
||||||
action: () => isShowGridLines.value = false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: '清空页面',
|
text: '清空页面',
|
||||||
},
|
},
|
||||||
|
@ -235,6 +182,7 @@ export default defineComponent({
|
||||||
canvasRef,
|
canvasRef,
|
||||||
viewportRef,
|
viewportRef,
|
||||||
viewportStyles,
|
viewportStyles,
|
||||||
|
canvasScale,
|
||||||
mouseSelectionState,
|
mouseSelectionState,
|
||||||
handleClickBlankArea,
|
handleClickBlankArea,
|
||||||
removeEditorAreaFocus,
|
removeEditorAreaFocus,
|
||||||
|
|
Loading…
Reference in New Issue