vue 实现尺子
实现思路
在Vue中实现尺子功能,可以通过动态生成刻度线和数字标签,结合CSS样式和交互逻辑完成。核心是利用v-for循环渲染刻度线,并通过计算属性动态调整刻度间距和数值显示。
基础实现代码
以下是一个水平尺子的实现示例,包含刻度线和数字标签:
<template>
<div class="ruler-container">
<div class="ruler" ref="ruler">
<div
v-for="(tick, index) in ticks"
:key="index"
class="tick"
:style="{ left: `${tick.position}px`, height: `${tick.height}px` }"
>
<span v-if="tick.isMajor" class="tick-label">{{ tick.value }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
scale: 1, // 缩放比例
startValue: 0, // 起始值
endValue: 100, // 结束值
majorInterval: 10, // 主刻度间隔
minorInterval: 2 // 次刻度间隔
}
},
computed: {
ticks() {
const ticks = [];
const totalTicks = (this.endValue - this.startValue) / this.minorInterval;
for (let i = 0; i <= totalTicks; i++) {
const value = this.startValue + i * this.minorInterval;
const isMajor = value % this.majorInterval === 0;
ticks.push({
value,
position: i * this.minorInterval * 10 * this.scale,
height: isMajor ? 30 : 15,
isMajor
});
}
return ticks;
}
}
}
</script>
<style scoped>
.ruler-container {
overflow-x: auto;
padding-top: 20px;
}
.ruler {
position: relative;
height: 40px;
border-bottom: 1px solid #333;
}
.tick {
position: absolute;
bottom: 0;
width: 1px;
background-color: #333;
}
.tick-label {
position: absolute;
left: -10px;
top: 100%;
font-size: 12px;
}
</style>
垂直尺子实现
若需要垂直尺子,调整样式和计算逻辑:
<template>
<div class="vertical-ruler">
<div
v-for="(tick, index) in ticks"
:key="index"
class="tick"
:style="{ top: `${tick.position}px`, width: `${tick.width}px` }"
>
<span v-if="tick.isMajor" class="tick-label">{{ tick.value }}</span>
</div>
</div>
</template>
<style scoped>
.vertical-ruler {
position: relative;
width: 40px;
border-right: 1px solid #333;
}
.tick {
position: absolute;
right: 0;
height: 1px;
background-color: #333;
}
.tick-label {
position: absolute;
right: 100%;
transform: translateY(-50%);
font-size: 12px;
}
</style>
交互功能增强
添加拖动和缩放功能,需结合事件处理:
methods: {
handleWheel(e) {
e.preventDefault();
this.scale += e.deltaY * -0.01;
this.scale = Math.max(0.5, Math.min(2, this.scale));
},
startDrag(e) {
this.dragStartX = e.clientX;
this.dragStartScroll = this.$refs.ruler.scrollLeft;
document.addEventListener('mousemove', this.onDrag);
document.addEventListener('mouseup', this.stopDrag);
},
onDrag(e) {
const dx = e.clientX - this.dragStartX;
this.$refs.ruler.scrollLeft = this.dragStartScroll - dx;
}
}
动态响应式调整
在mounted中添加窗口大小监听:
mounted() {
window.addEventListener('resize', this.calculateRulerLength);
},
beforeDestroy() {
window.removeEventListener('resize', this.calculateRulerLength);
}
注意事项
- 刻度密度需根据容器宽度动态计算,避免渲染过多DOM节点
- 对于长尺子考虑使用虚拟滚动技术优化性能
- 触摸设备需额外添加触摸事件支持
- 数值显示格式可通过过滤器自定义
以上实现可根据实际需求调整刻度间隔、样式和交互行为。对于专业设计工具级别的尺子,可能需要结合Canvas或SVG实现更高性能的渲染。







