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>
.mouse-selection {
position: absolute;
background-color: rgba($themeColor, 0.25);
background: rgba(150, 150, 150, 0.25);
z-index: 200;
&.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',
left: viewportStyles.left + 'px',
top: viewportStyles.top + 'px',
transform: `scale(${viewportStyles.scale})`,
transform: `scale(${canvasScale})`,
}"
>
<MouseSelection
@ -49,6 +49,7 @@ import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
import { getImageDataURL } from '@/utils/image'
import useDropImage from '@/hooks/useDropImage'
import useSetViewportSize from './hooks/useSetViewportSize'
import MouseSelection from './MouseSelection.vue'
import SlideBackground from './SlideBackground.vue'
@ -62,9 +63,11 @@ export default defineComponent({
AlignmentLine,
},
setup() {
const store = useStore<State>()
const viewportRef = ref<HTMLElement | null>(null)
const isShowGridLines = ref(false)
const alignmentLines = ref<AlignmentLineProps[]>([])
const currentSlide = computed(() => store.getters.currentSlide)
const dropImageFile = useDropImage(viewportRef)
watch(dropImageFile, () => {
@ -75,50 +78,14 @@ export default defineComponent({
}
})
const viewportStyles = reactive({
const canvasRef = ref<HTMLElement | null>(null)
const { canvasScale, viewportLeft, viewportTop } = useSetViewportSize(canvasRef)
const viewportStyles = computed(() => ({
width: VIEWPORT_SIZE,
height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,
left: 0,
top: 0,
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)
})
left: viewportLeft.value,
top: viewportTop.value,
}))
const mouseSelectionState = reactive({
isShow: false,
@ -205,26 +172,6 @@ export default defineComponent({
text: '粘贴',
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: '清空页面',
},
@ -235,6 +182,7 @@ export default defineComponent({
canvasRef,
viewportRef,
viewportStyles,
canvasScale,
mouseSelectionState,
handleClickBlankArea,
removeEditorAreaFocus,