style设置宽度用vw,运行变成取整的px

本文探讨了在使用CSS的vw单位设置元素宽度时遇到的取整问题,特别是在实际运行环境中,宽度会从vw单位转换为整数像素值,导致布局出现意外变化。通过浏览器的开发者工具手动调整vw值时,问题可以得到解决。最终建议采用百分比单位作为替代方案,以避免vw单位带来的布局不稳定。

style设置宽度用vw,运行变成取整的px

整个崩掉???

如果直接在浏览器f12改又可以生效

 

解决:改用百分比

<template> <div class="full_content"> <div class="header"> <!-- <div class="header_desc">{{ $t("跑步能力") }}</div> --> <div class="header_icon" @click="fullScreenClick"> <el-icon><TopRight /></el-icon> </div> </div> <div class="footer"> <div class="chart1" ref="chartRef" style="width: 100%; height: 100%" ></div> </div> <echartsBox :title="$t('跑步能力')" v-model:visible="dialogVisible"> <template #content> <div class="footer" style="width: 750px; height: 400px"> <div class="chart2" ref="chartDialog" style="width: 100%; height: 90%" ></div> </div> </template> </echartsBox> </div> </template> <script setup> import { ref, onMounted, onUnmounted, computed } from "vue"; import * as echarts from "echarts"; const chartRef = ref(null); let myChart = null; // 全屏按钮触发 const dialogVisible = ref(false); const fullScreenClick = () => { console.log(123); dialogVisible.value = true; }; const props = defineProps({ xAxisData: { type: Array, default: [ "00:00", "02:00", "04:00", "06:00", "08:00", "10:00", "12:00", "14:00", "16:00", "18:00", "20:00", "22:00", ], }, title: { type: String, default() { return "跑步能力"; }, }, }); // 常用清晰区分的颜色(适合折线图) const COLOR_PALETTE = [ "#4895ef", // 蓝 "#eb4d4b", // 红 "#f0932b", // 橙 "#36cbcb", // 青 "#9b59b6", // 紫 "#00b894", // 绿松石 ]; const yAxisData = ref([ { name: "单次跑力", data: [70, 10, 75, 39, 60, 80, 75, 65, 55, 70, 75, 70], }, { name: "跑步指数", data: [55, 40, 50, 55, 50, 60, 50, 30, 55, 81, 50, 55], }, { name: "单次", data: [70, 101, 9, 39, 60, 10, 75, 65, 55, 70, 75, 70], }, { name: "跑步", data: [55, 120, 50, 55, 50, 60, 30, 30, 45, 81, 50, 55], }, ]); const legendData = yAxisData.value.map((item) => { return item.name; }); const seriesWithColor = computed(() => { return yAxisData.value.map((series, index) => ({ ...series, lineColor: COLOR_PALETTE[index % COLOR_PALETTE.length], // 循环使用颜色 })); }); const chartSeries = computed(() => { return seriesWithColor.value.map((series, index) => ({ name: series.name, type: "line", data: series.data, yAxisIndex: index, // 每条线绑定到自己的 Y 轴 showSymbol: false, lineStyle: { color: series.lineColor, width: 2.5, }, itemStyle: { color: series.lineColor, }, })); }); const alignToStep = (value, step = 10) => { return Math.ceil(value / step) * step; }; const chartYAxis = computed(() => { const TICK_INTERVAL = 20; return seriesWithColor.value.map((series, index) => { // 左右交替放置 Y 轴,避免全部挤在一起 const isLeft = index % 2 === 0; const position = isLeft ? "left" : "right"; const rawDataMax = Math.max(...series.data); // 向上取整到 TICK_INTERVAL 的倍数 const niceMax = alignToStep(rawDataMax, TICK_INTERVAL); // 根据 index 计算偏移量,每多一个同侧轴就向外推 30px const offset = Math.floor(index / 2) * 30; return { type: "value", position, offset, // 关键:错开 Y 轴位置 axisLabel: { color: series.lineColor, }, nameTextStyle: { color: series.lineColor, }, splitLine: { lineStyle: { color: "#444", type: "solid", width: 1 }, }, min: 0, max: niceMax, // 必须是 interval 的整数倍 interval: TICK_INTERVAL, // 所有 Y 轴强制相同刻度间隔 }; }); }); // const chartYAxis = computed(() => { // const leftSeries = seriesWithColor.value.filter( // (s) => seriesBinding.value[s.name] === "left" // ); // const rightSeries = seriesWithColor.value.filter( // (s) => seriesBinding.value[s.name] === "right" // ); // // 取主色(第一个 series 的颜色)作为 Y 轴文字颜色 // const leftColor = leftSeries.length > 0 ? leftSeries[0].lineColor : "#7a7b7c"; // const rightColor = // rightSeries.length > 0 ? rightSeries[0].lineColor : "#7a7b7c"; // // 通用取整函数 // const getNiceMax = (data, step = 10) => // Math.ceil(Math.max(...data) / step) * step + step; // return [ // { // type: "value", // position: "left", // axisLabel: { color: leftColor }, // nameTextStyle: { color: leftColor }, // splitLine: { lineStyle: { color: "#444" } }, // min: 0, // max: // leftSeries.length > 0 // ? getNiceMax( // leftSeries.flatMap((s) => s.data), // 10 // ) // : 100, // }, // // 右 Y 轴 // { // type: "value", // position: "right", // axisLabel: { color: rightColor }, // nameTextStyle: { color: rightColor }, // splitLine: { show: false }, // min: 0, // max: // rightSeries.length > 0 // ? getNiceMax( // rightSeries.flatMap((s) => s.data), // 10 // ) // : 100, // }, // ]; // }); // 初始化图表的函数 const initChart = () => { myChart = echarts.init(chartRef.value); const option = { title: { text: props.title, left: "center", textStyle: { color: "#0d7ee7", }, }, xAxis: { type: "category", data: props.xAxisData.length > 0 ? props.xAxisData : xAxisData, axisLine: { lineStyle: { color: "#7a7b7c", }, }, axisLabel: { color: "#7a7b7c", }, }, yAxis: chartYAxis.value, series: chartSeries.value, legend: { data: legendData, top: "10%", right: "8%", icon: "circle", textStyle: { color: "#fff", }, }, tooltip: { trigger: "axis", }, grid: { left: "3%", right: "4%", bottom: "3%", containLabel: true, }, }; myChart.setOption(option); }; // 窗口大小变化时调整图表大小的函数 const handleResize = () => { if (myChart) { myChart.resize(); } }; onMounted(() => { initChart(); window.addEventListener("resize", handleResize); }); onUnmounted(() => { if (myChart) { myChart.dispose(); myChart = null; } window.removeEventListener("resize", handleResize); }); </script> <style scoped lang="scss"> .full_content { position: relative; width: 100vw; height: 40vh; width: 600px; min-height: 400px; background-color: rgb(42, 40, 40); .header { width: 100%; height: 10%; display: flex; justify-content: center; position: relative; font-size: 24px; font-weight: bolder; color: #0d7ee7; align-items: center; padding-top: 3%; .header_icon { margin-left: 85%; position: absolute; top: 18px; width: 30px; height: 30px; font-size: 25px; cursor: pointer; color: #ffffff5e; background-size: contain; z-index: 999; } } .footer { position: absolute; top: 20px; width: 100%; height: 85%; } } </style> 这样还是不行
10-18
<template> <div class="container"> <div ref="container" class="x6-graph"></div> <div class="controls"> <button @click="zoomIn">放大</button> <button @click="zoomOut">缩小</button> <button @click="resetZoom">重置</button> </div> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { Graph, Shape } from '@antv/x6' import { Transform } from '@antv/x6-plugin-transform' const container = ref(null) let graph = null // 初始化画布 const initGraph = () => { graph = new Graph({ container: container.value, width: 800, height: 600, grid: true, mousewheel: { enabled: true, modifiers: 'ctrl' }, interacting: { nodeMovable: true }, background: { color: '#f5f7fa' } }) graph.use(new Transform({ resizing: true, rotating: true })) createEditableOctagon() createFixedScales() graph.on('zoom', updateScaleLabels) } // 创建可编辑八边形 const createEditableOctagon = () => { // 计算正八边形顶点坐标 const points = [] const radius = 50 for (let i = 0; i < 8; i++) { const angle = (i * Math.PI) / 4 points.push({ x: 300 + radius * Math.cos(angle), y: 200 + radius * Math.sin(angle) }) } graph.addNode({ shape: 'polygon', x: 300, y: 200, width: 100, height: 100, attrs: { body: { fill: '#FEC55B', stroke: '#333', strokeWidth: 1, points: points.map(p => [p.x, p.y]) }, label: { text: '八边形', fill: '#333' } }, editable: true, transform: { enabled: true, preserveAspectRatio: false }, selectable: true }) } // 创建固定刻度系统 const createFixedScales = () => { // X轴刻度(顶部) for (let x = 0; x <= graph.width(); x += 40) { // 刻度线 graph.addNode({ id: `x-tick-${x}`, shape: 'rect', x, y: 0, width: 1, height: 5, attrs: { body: { fill: '#666' } }, selectable: false }) // 标签(仅显示关键刻度) if (x % 100 === 0) { graph.addNode({ id: `x-label-${x}`, shape: 'text', x: x + 5, y: 15, attrs: { label: { text: '' }, text: { fontSize: 10, fill: '#666' } }, selectable: false }) } } // Y轴刻度(右侧) for (let y = 0; y <= graph.height(); y += 40) { // 刻度线 graph.addNode({ id: `y-tick-${y}`, shape: 'rect', x: graph.width() - 5, y, width: 5, height: 1, attrs: { body: { fill: '#666' } }, selectable: false }) // 标签(仅显示关键刻度) if (y % 100 === 0) { graph.addNode({ id: `y-label-${y}`, shape: 'text', x: graph.width() - 15, y: y + 5, attrs: { label: { text: '' }, text: { fontSize: 10, fill: '#666' } }, selectable: false }) } } } // 动态更新刻度标签 const updateScaleLabels = () => { const zoom = graph.zoom() const base = Math.pow(10, Math.floor(Math.log10(zoom * 100))) const step = base * (zoom > 5 ? 1 : zoom > 1 ? 2 : 5) // 更新X轴标签 for (let x = 0; x <= graph.width(); x += 40) { if (x % 100 === 0) { const logicalValue = Math.round(x / (40 * step)) * step const node = graph.getCellById(`x-label-${x}`) node.attr('label/text', logicalValue || '') } } // 更新Y轴标签 for (let y = 0; y <= graph.height(); y += 40) { if (y % 100 === 0) { const logicalValue = Math.round(y / (40 * step)) * step const node = graph.getCellById(`y-label-${y}`) node.attr('label/text', logicalValue || '') } } } // 缩放控制 const zoomIn = () => graph.zoom(0.1) const zoomOut = () => graph.zoom(-0.1) const resetZoom = () => graph.zoomTo(1) onMounted(() => { initGraph() }) </script> <style scoped> .container { position: relative; width: 100vw; height: 100vh; } .x6-graph { width: 100%; height: 100%; border: 1px solid #e0e0e0; } .controls { position: absolute; top: 20px; left: 20px; z-index: 1000; } button { margin-right: 8px; padding: 4px 8px; background: #fff; border: 1px solid #ddd; cursor: pointer; } </style>,参考这个代码,这个可编辑多边形假设为八个点连接起来的封闭图形,在拖到这八个点时,多边形重新绘制形状,这个图形可以被拖拽,移动。底层画布可以自由拖动和缩放,且缩放时的X刻度线始终显示在画布的相对y为0的位置,,Y轴刻度线显示在画布的相对右侧位置,刻度线无法选中,给刻度线加上画布像素值的标签,类似1 2 3 4 6这样的,显示在刻度线缩放,一直到画布的宽高值,在缩放时,刻度线上的标签值也会动态变换,放大到最大显示 1,2 ,3这样显示,缩小时显示1 100 200这样
06-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值