hookehuyr

refactor(animation): 优化SVG容器布局并添加窗口大小监听

调整了SVG容器的布局和样式,使其更适应不同屏幕尺寸。添加了窗口大小变化的监听功能,动态更新SVG的viewBox属性,确保内容始终居中且比例正确。同时优化了按钮的定位和样式,提升了用户体验。
<!--
* @Date: 2025-03-28 09:23:04
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-28 21:28:07
* @LastEditTime: 2025-03-28 21:56:54
* @FilePath: /mlaj/src/views/animation.vue
* @Description: 贝塞尔曲线动画路径组件
*
......@@ -13,7 +13,7 @@
-->
<template>
<div class="animation-container">
<div style="position: fixed; top: 0; right: 0">
<div style="position: fixed; top: 100px; right: 0; z-index: 999;">
<button
class="next-button"
@click="nextStep"
......@@ -22,7 +22,13 @@
下一步
</button>
</div>
<svg width="100%" height="100%" viewBox="0 0 1000 1200" class="animation-svg">
<svg
width="100%"
height="100%"
:viewBox="svgViewBox"
class="animation-svg"
preserveAspectRatio="xMidYMid meet"
>
<!-- 定义箭头标记 -->
<defs>
<marker
......@@ -102,7 +108,7 @@
</template>
<script setup>
import { ref, computed } from "vue";
import { ref, computed, onMounted, onUnmounted } from "vue";
import img_svg1 from "@/assets/1.svg";
import img_svg2 from "@/assets/2.svg";
import img_svg3 from "@/assets/3.svg";
......@@ -273,33 +279,94 @@ const svgObj = [
},
},
];
// 计算SVG容器尺寸
const containerSize = computed(() => {
const container = document.querySelector('.animation-container');
if (!container) return { width: 0, height: 0 };
return {
width: container.clientWidth,
height: container.clientHeight
};
});
// 监听窗口大小变化
const updateContainerSize = () => {
containerSize.value = {
width: document.querySelector('.animation-container')?.clientWidth || 0,
height: document.querySelector('.animation-container')?.clientHeight || 0
};
};
onMounted(() => {
updateContainerSize();
window.addEventListener('resize', updateContainerSize);
});
onUnmounted(() => {
window.removeEventListener('resize', updateContainerSize);
});
// 更新svgViewBox计算属性
const svgViewBox = computed(() => {
const maxX = Math.max(...points.value.map(p => p.x));
const maxY = Math.max(...points.value.map(p => p.y));
const minX = Math.min(...points.value.map(p => p.x));
const minY = Math.min(...points.value.map(p => p.y));
const padding = 100;
// 计算内容的宽高比
const contentWidth = maxX - minX + padding * 2;
const contentHeight = maxY - minY + padding * 2;
const contentRatio = contentWidth / contentHeight;
// 获取容器的宽高比
const containerRatio = containerSize.value.width / containerSize.value.height;
// 根据宽高比调整viewBox
if (containerRatio > contentRatio) {
// 容器更宽,以高度为基准
const adjustedWidth = contentHeight * containerRatio;
const extraPadding = (adjustedWidth - contentWidth) / 2;
return `${minX - padding - extraPadding} ${minY - padding} ${adjustedWidth} ${contentHeight}`;
} else {
// 容器更高,以宽度为基准
const adjustedHeight = containerRatio ? contentWidth / containerRatio : contentHeight;
const extraPadding = isFinite(adjustedHeight) ? (adjustedHeight - contentHeight) / 2 : 0;
return `${minX - padding} ${minY - padding - extraPadding} ${contentWidth} ${adjustedHeight}`;
}
});
</script>
<style scoped>
.animation-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
position: relative;
width: 100%;
height: 100vh;
background: #f5f5f5;
padding: 1.25rem;
padding: 1rem;
box-sizing: border-box;
overflow: hidden;
}
.animation-svg {
max-width: 100%;
max-height: 100vh;
margin: 0 auto;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin: 0;
display: block;
}
@media screen and (max-width: 768px) {
.animation-container {
padding: 0.9375rem;
padding: 0.5rem;
}
.animation-svg {
height: 80vh;
width: 100%;
height: auto;
min-height: 90vh;
}
.next-button {
......