网格线优化
This commit is contained in:
parent
a22463fa9c
commit
c77dfb4c5a
|
@ -1,39 +1,69 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<SvgWrapper class="grid-lines">
|
||||||
class="grid-lines"
|
<path
|
||||||
:style="style"
|
:style="{
|
||||||
></div>
|
transform: `scale(${canvasScale})`,
|
||||||
|
}"
|
||||||
|
:d="path"
|
||||||
|
fill="none"
|
||||||
|
:stroke="gridColor"
|
||||||
|
stroke-width="0.3"
|
||||||
|
shape-rendering="crispEdges"
|
||||||
|
stroke-dasharray="5"
|
||||||
|
></path>
|
||||||
|
</SvgWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, computed } from 'vue'
|
import { defineComponent, computed, Ref } from 'vue'
|
||||||
|
import { useStore } from 'vuex'
|
||||||
|
import tinycolor from 'tinycolor2'
|
||||||
|
import { State } from '@/store'
|
||||||
|
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||||
|
import { SlideBackground } from '@/types/slides'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'grid-lines',
|
name: 'grid-lines',
|
||||||
props: {
|
|
||||||
gridSize: {
|
|
||||||
type: Number,
|
|
||||||
default: 20,
|
|
||||||
},
|
|
||||||
gridColor: {
|
|
||||||
type: String,
|
|
||||||
default: 'rgba(100, 100, 100, 0.1)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const style = computed(() => {
|
const store = useStore<State>()
|
||||||
const gridSize = props.gridSize + 'px'
|
const canvasScale = computed(() => store.state.canvasScale)
|
||||||
const gridSpacing = props.gridSize - 1 + 'px'
|
const background: Ref<SlideBackground | undefined> = computed(() => store.getters.currentSlide.background)
|
||||||
const gridColor = props.gridColor
|
|
||||||
|
|
||||||
return {
|
const gridColor = computed(() => {
|
||||||
backgroundImage: `linear-gradient(transparent ${gridSpacing}, ${gridColor} ${gridSpacing}, ${gridColor} ${gridSize}), linear-gradient(90deg, transparent ${gridSpacing}, ${gridColor} ${gridSpacing}, ${gridColor} ${gridSize})`,
|
if(!background.value || background.value.type === 'image') return 'rgba(100, 100, 100, 0.5)'
|
||||||
backgroundSize: `${gridSize} ${gridSize}`,
|
const color = background.value.value
|
||||||
|
const rgba = tinycolor(color).toRgb()
|
||||||
|
const newRgba = {
|
||||||
|
r: rgba.r > 128 ? rgba.r - 128 : rgba.r + 127,
|
||||||
|
g: rgba.g > 128 ? rgba.g - 128 : rgba.g + 127,
|
||||||
|
b: rgba.b > 128 ? rgba.b - 128 : rgba.b + 127,
|
||||||
|
a: 0.5
|
||||||
}
|
}
|
||||||
|
return `rgba(${[newRgba.r, newRgba.g, newRgba.b, newRgba.a].join(',')})`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const gridSize = 50
|
||||||
|
|
||||||
|
const getPath = () => {
|
||||||
|
const maxX = VIEWPORT_SIZE
|
||||||
|
const maxY = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO
|
||||||
|
|
||||||
|
let path = ''
|
||||||
|
for(let i = 0; i <= Math.floor(maxY / gridSize); i++) {
|
||||||
|
path += `M0 ${i * gridSize}, L${maxX} ${i * gridSize}`
|
||||||
|
}
|
||||||
|
for(let i = 0; i <= Math.floor(maxX / gridSize); i++) {
|
||||||
|
path += `M${i * gridSize} 0, L${i * gridSize} ${maxY}`
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
style,
|
canvasScale,
|
||||||
|
gridColor,
|
||||||
|
width: VIEWPORT_SIZE,
|
||||||
|
height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,
|
||||||
|
path: getPath(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -41,11 +71,13 @@ export default defineComponent({
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.grid-lines {
|
.grid-lines {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background-position: 0 0;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -3,10 +3,7 @@
|
||||||
class="slide-background"
|
class="slide-background"
|
||||||
:style="backgroundStyle"
|
:style="backgroundStyle"
|
||||||
>
|
>
|
||||||
<template v-if="showGridLines">
|
<GridLines v-if="showGridLines" />
|
||||||
<GridLines />
|
|
||||||
<GridLines :gridSize="100" gridColor="rgba(100, 100, 100, 0.35)" />
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ export default (
|
||||||
const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))
|
const originElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value))
|
||||||
const originActiveElementList = originElementList.filter(el => activeElementIdList.value.includes(el.id))
|
const originActiveElementList = originElementList.filter(el => activeElementIdList.value.includes(el.id))
|
||||||
|
|
||||||
const sorptionRange = 3
|
const sorptionRange = 5
|
||||||
const elOriginLeft = element.left
|
const elOriginLeft = element.left
|
||||||
const elOriginTop = element.top
|
const elOriginTop = element.top
|
||||||
const elOriginWidth = element.width
|
const elOriginWidth = element.width
|
||||||
|
@ -211,25 +211,19 @@ export default (
|
||||||
const min = Math.min(...range, targetMinX, targetMaxX)
|
const min = Math.min(...range, targetMinX, targetMaxX)
|
||||||
const max = Math.max(...range, targetMinX, targetMaxX)
|
const max = Math.max(...range, targetMinX, targetMaxX)
|
||||||
|
|
||||||
if(Math.abs(targetMinY - value) < sorptionRange) {
|
if(Math.abs(targetMinY - value) < sorptionRange && !isHorizontalAdsorbed) {
|
||||||
if(!isHorizontalAdsorbed) {
|
targetTop = targetTop - (targetMinY - value)
|
||||||
targetTop = targetTop - (targetMinY - value)
|
isHorizontalAdsorbed = true
|
||||||
isHorizontalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
|
_alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
|
||||||
}
|
}
|
||||||
if(Math.abs(targetMaxY - value) < sorptionRange) {
|
if(Math.abs(targetMaxY - value) < sorptionRange && !isHorizontalAdsorbed) {
|
||||||
if(!isHorizontalAdsorbed) {
|
targetTop = targetTop - (targetMaxY - value)
|
||||||
targetTop = targetTop - (targetMaxY - value)
|
isHorizontalAdsorbed = true
|
||||||
isHorizontalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
|
_alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
|
||||||
}
|
}
|
||||||
if(Math.abs(targetCenterY - value) < sorptionRange) {
|
if(Math.abs(targetCenterY - value) < sorptionRange && !isHorizontalAdsorbed) {
|
||||||
if(!isHorizontalAdsorbed) {
|
targetTop = targetTop - (targetCenterY - value)
|
||||||
targetTop = targetTop - (targetCenterY - value)
|
isHorizontalAdsorbed = true
|
||||||
isHorizontalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
|
_alignmentLines.push({type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,25 +232,19 @@ export default (
|
||||||
const min = Math.min(...range, targetMinY, targetMaxY)
|
const min = Math.min(...range, targetMinY, targetMaxY)
|
||||||
const max = Math.max(...range, targetMinY, targetMaxY)
|
const max = Math.max(...range, targetMinY, targetMaxY)
|
||||||
|
|
||||||
if(Math.abs(targetMinX - value) < sorptionRange) {
|
if(Math.abs(targetMinX - value) < sorptionRange && !isVerticalAdsorbed) {
|
||||||
if(!isVerticalAdsorbed) {
|
targetLeft = targetLeft - (targetMinX - value)
|
||||||
targetLeft = targetLeft - (targetMinX - value)
|
isVerticalAdsorbed = true
|
||||||
isVerticalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
|
_alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
|
||||||
}
|
}
|
||||||
if(Math.abs(targetMaxX - value) < sorptionRange) {
|
if(Math.abs(targetMaxX - value) < sorptionRange && !isVerticalAdsorbed) {
|
||||||
if(!isVerticalAdsorbed) {
|
targetLeft = targetLeft - (targetMaxX - value)
|
||||||
targetLeft = targetLeft - (targetMaxX - value)
|
isVerticalAdsorbed = true
|
||||||
isVerticalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
|
_alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
|
||||||
}
|
}
|
||||||
if(Math.abs(targetCenterX - value) < sorptionRange) {
|
if(Math.abs(targetCenterX - value) < sorptionRange && !isVerticalAdsorbed) {
|
||||||
if(!isVerticalAdsorbed) {
|
targetLeft = targetLeft - (targetCenterX - value)
|
||||||
targetLeft = targetLeft - (targetCenterX - value)
|
isVerticalAdsorbed = true
|
||||||
isVerticalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
|
_alignmentLines.push({type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default (elementList: Ref<PPTElement[]>) => {
|
||||||
const dragLineElement = (e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => {
|
const dragLineElement = (e: MouseEvent, element: PPTLineElement, command: OperateLineHandler) => {
|
||||||
let isMouseDown = true
|
let isMouseDown = true
|
||||||
|
|
||||||
const sorptionRange = 10
|
const sorptionRange = 8
|
||||||
|
|
||||||
const startPageX = e.pageX
|
const startPageX = e.pageX
|
||||||
const startPageY = e.pageY
|
const startPageY = e.pageY
|
||||||
|
|
|
@ -175,7 +175,7 @@ export default (
|
||||||
|
|
||||||
// 对齐吸附方法
|
// 对齐吸附方法
|
||||||
const alignedAdsorption = (currentX: number | null, currentY: number | null) => {
|
const alignedAdsorption = (currentX: number | null, currentY: number | null) => {
|
||||||
const sorptionRange = 3
|
const sorptionRange = 5
|
||||||
|
|
||||||
const _alignmentLines: AlignmentLineProps[] = []
|
const _alignmentLines: AlignmentLineProps[] = []
|
||||||
let isVerticalAdsorbed = false
|
let isVerticalAdsorbed = false
|
||||||
|
@ -188,11 +188,9 @@ export default (
|
||||||
const min = Math.min(...range, currentX || 0)
|
const min = Math.min(...range, currentX || 0)
|
||||||
const max = Math.max(...range, currentX || 0)
|
const max = Math.max(...range, currentX || 0)
|
||||||
|
|
||||||
if(Math.abs(currentY - value) < sorptionRange) {
|
if(Math.abs(currentY - value) < sorptionRange && !isHorizontalAdsorbed) {
|
||||||
if(!isHorizontalAdsorbed) {
|
correctionVal.offsetY = currentY - value
|
||||||
correctionVal.offsetY = currentY - value
|
isHorizontalAdsorbed = true
|
||||||
isHorizontalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({ type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100 })
|
_alignmentLines.push({ type: 'horizontal', axis: {x: min - 50, y: value}, length: max - min + 100 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,11 +201,9 @@ export default (
|
||||||
const min = Math.min(...range, (currentY || 0))
|
const min = Math.min(...range, (currentY || 0))
|
||||||
const max = Math.max(...range, (currentY || 0))
|
const max = Math.max(...range, (currentY || 0))
|
||||||
|
|
||||||
if(Math.abs(currentX - value) < sorptionRange) {
|
if(Math.abs(currentX - value) < sorptionRange && !isVerticalAdsorbed) {
|
||||||
if(!isVerticalAdsorbed) {
|
correctionVal.offsetX = currentX - value
|
||||||
correctionVal.offsetX = currentX - value
|
isVerticalAdsorbed = true
|
||||||
isVerticalAdsorbed = true
|
|
||||||
}
|
|
||||||
_alignmentLines.push({ type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100 })
|
_alignmentLines.push({ type: 'vertical', axis: {x: value, y: min - 50}, length: max - min + 100 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue