This commit is contained in:
pipipi-pikachu 2020-12-16 23:10:40 +08:00
parent a7176f8be6
commit 7246f89bc0
4 changed files with 127 additions and 64 deletions

View File

@ -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 {

View File

@ -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,
}
}

View File

@ -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) }
}

View File

@ -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,