网格线优化

This commit is contained in:
pipipi-pikachu 2021-01-19 23:21:26 +08:00
parent a22463fa9c
commit c77dfb4c5a
5 changed files with 85 additions and 72 deletions

View File

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

View File

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

View File

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

View File

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

View File

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