Skip to content

Commit

Permalink
fix: 缩放交互中心点逻辑优化
Browse files Browse the repository at this point in the history
  • Loading branch information
StreakingMan committed Jan 25, 2024
1 parent 79215ec commit cc71772
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 38 deletions.
15 changes: 13 additions & 2 deletions src/classes/Runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,21 @@ export class Runtime {
public bottomDrawer = ref(false);
// 辅助网格显示
public showGrid = ref(true);
// 缩放值和缩放中心
// 缩放值相关
public scale = reactive({
// 实时缩放值
value: 1,
position: { x: 0, y: 0 },
// 在进行缩放操作时,记录缩放前的一些信息
cache: {
// 缩放中标记
scaling: false,
// 鼠标相对于画布的百分比
mousePaperPercent: { x: 0, y: 0 },
// 鼠标位置
mousePosition: { x: 0, y: 0 },
// 容器滚动位置
containerScroll: { left: 0, top: 0 },
},
});
// 激活元素集合
public activeMaterialSet = ref<Set<Material<any>['id']>>(new Set());
Expand Down
14 changes: 7 additions & 7 deletions src/components/core/Paper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const paperRef = ref<HTMLDivElement | null>(null);
const isEdit = inject(paperModeInjectionKey, PaperMode.Edit) === PaperMode.Edit;
// paper边界信息记录
// paper bounding 信息实时更新
const { x, y, width, height } = useElementBounding(paperRef);
watch(
() => ({
Expand All @@ -26,19 +26,19 @@ watch(
}),
() => {
runtime.paper.bounds = {
x: x.value,
y: y.value,
width: width.value,
height: height.value,
x: Math.ceil(x.value),
y: Math.ceil(y.value),
width: Math.ceil(width.value),
height: Math.ceil(height.value) * paper.pageCount,
};
},
);
// 缩放的是否不知道为啥宽高没有响应,主动根据缩放值计算下
// 缩放的时候不知道为啥宽高没有根据,主动根据缩放值计算下
watch(
() => runtime.scale.value,
(v) => {
runtime.paper.bounds.width = Math.ceil(paper.w * v);
runtime.paper.bounds.height = Math.ceil(paper.h * v);
runtime.paper.bounds.height = Math.ceil(paper.h * v) * paper.pageCount;
},
);
Expand Down
70 changes: 41 additions & 29 deletions src/components/core/Sketch.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue';
import { computed, nextTick, onMounted, onUnmounted, ref, watchEffect } from 'vue';
import useMouseDragDynamic, { type MouseEvtInfo } from '@/composables/useMouseDragDynamic';
import { usePaper, useRuntime } from '@/composables/useApp';
import { useActiveElement, useDebounceFn, useMagicKeys, useWindowSize } from '@vueuse/core';
Expand Down Expand Up @@ -84,32 +84,28 @@ useMouseDragDynamic({
bindElementRef: wrapperRef,
});
// 以鼠标为中心进行缩放
// 计算依据:缩放前后,鼠标位置与页面的相对百分比位置不变
// const mousePaperPercentX = computed(() => {
// return (runtime.scale.position.x - runtime.paper.bounds.x) / runtime.paper.bounds.width;
// });
// const mousePaperPercentY = computed(() => {
// return (runtime.scale.position.y - runtime.paper.bounds.y) / runtime.paper.bounds.height;
// });
// watch(
// () => ({
// mppx: mousePaperPercentX.value,
// mppy: mousePaperPercentY.value,
// scale: runtime.scale.value,
// }),
// (newInfo, oldInfo) => {
// // 单位偏移
// const unitOffsetX = paperInstance.w * (newInfo.mppx - oldInfo.mppx);
// const unitOffsetY = paperInstance.h * (newInfo.mppy - oldInfo.mppy);
// // 真实偏移
// const offsetX = unitOffsetX / newInfo.scale;
// const offsetY = unitOffsetY / newInfo.scale;
// // 补偿容器滚动
// wrapperRef.value.scrollLeft -= offsetX;
// wrapperRef.value.scrollTop -= offsetY;
// },
// );
// 补偿缩放中心点的偏移
watchEffect(() => {
if (!runtime.scale.cache.scaling) return;
// 缩放中心起始点当前在屏幕的位置
const lastCenterNowX =
runtime.paper.bounds.x +
runtime.scale.cache.mousePaperPercent.x * runtime.paper.bounds.width;
const lastCenterNowY =
runtime.paper.bounds.y +
runtime.scale.cache.mousePaperPercent.y * runtime.paper.bounds.height;
// 缩放中心点偏移量
const offsetX = lastCenterNowX - runtime.scale.cache.mousePosition.x;
const offsetY = lastCenterNowY - runtime.scale.cache.mousePosition.y;
// 滚动
wrapperRef.value?.scrollTo({
left: runtime.scale.cache.containerScroll.left + offsetX,
top: runtime.scale.cache.containerScroll.top + offsetY,
});
});
// 监听鼠标滚轮事件
useWindowMouseWheel({
onWheel: (wheelDelta, { x, y }, e) => {
if (!e.ctrlKey) {
Expand All @@ -123,12 +119,28 @@ useWindowMouseWheel({
const scaleValue = runtime.scale.value + wheelDelta;
// 缩放范围0.1~5
if (SCALE_RANGE[0] < scaleValue && scaleValue < SCALE_RANGE[1]) {
runtime.scale.position.x = x;
runtime.scale.position.y = y;
runtime.scale.value += wheelDelta;
if (!runtime.scale.cache.scaling) {
runtime.scale.cache.scaling = true;
// 记录开始时鼠标位置
runtime.scale.cache.mousePosition.x = x;
runtime.scale.cache.mousePosition.y = y;
// 记录开始时鼠标相对于paper的百分比位置
runtime.scale.cache.mousePaperPercent.x =
(x - runtime.paper.bounds.x) / runtime.paper.bounds.width;
runtime.scale.cache.mousePaperPercent.y =
(y - runtime.paper.bounds.y) / runtime.paper.bounds.height;
// 记录容器滚动条的位置
runtime.scale.cache.containerScroll.left = wrapperRef.value?.scrollLeft || 0;
runtime.scale.cache.containerScroll.top = wrapperRef.value?.scrollTop || 0;
}
}
handleScrollStop();
},
});
const handleScrollStop = useDebounceFn(() => {
runtime.scale.cache.scaling = false;
}, 300);
// 光标样式
const cursor = computed(() => {
Expand Down

1 comment on commit cc71772

@vercel
Copy link

@vercel vercel bot commented on cc71772 Jan 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.