当前位置:首页 > VUE

vue实现手动标尺模块

2026-02-20 16:29:04VUE

实现思路

手动标尺模块的核心在于绘制刻度线、数字标签以及实现交互逻辑(如拖动、缩放)。Vue 的响应式特性和计算属性非常适合动态调整标尺的显示范围和样式。

基础结构设计

使用 Vue 单文件组件(SFC)组织代码,模板部分负责渲染标尺的 DOM 结构,样式部分使用 CSS 实现刻度线和标签的布局,逻辑部分处理用户交互和数据计算。

<template>
  <div class="ruler-container" ref="rulerRef">
    <div class="ruler" :style="rulerStyle">
      <div 
        v-for="tick in visibleTicks" 
        :key="tick.value" 
        class="tick" 
        :class="{ 'major-tick': tick.isMajor }"
        :style="getTickStyle(tick)">
        <span v-if="tick.isMajor" class="tick-label">{{ tick.label }}</span>
      </div>
    </div>
  </div>
</template>

刻度计算逻辑

通过计算属性动态生成可见刻度数据,根据当前缩放比例和偏移量过滤非显示区域的刻度。

vue实现手动标尺模块

export default {
  props: {
    scale: { type: Number, default: 1 },
    offset: { type: Number, default: 0 },
    width: { type: Number, default: 1000 }
  },
  computed: {
    visibleTicks() {
      const ticks = [];
      const start = Math.floor(this.offset / 10) * 10;
      const end = start + this.width / this.scale + 20;

      for (let i = start; i <= end; i += 10) {
        ticks.push({
          value: i,
          isMajor: i % 100 === 0,
          label: i.toString()
        });
      }
      return ticks;
    },
    rulerStyle() {
      return {
        transform: `translateX(${-this.offset}px) scaleX(${this.scale})`
      };
    }
  },
  methods: {
    getTickStyle(tick) {
      return {
        left: `${tick.value}px`
      };
    }
  }
}

样式实现

使用绝对定位布局刻度线,通过 CSS 区分主次刻度线样式。

.ruler-container {
  position: relative;
  overflow: hidden;
  height: 30px;
  background: #f5f5f5;
}

.ruler {
  position: absolute;
  height: 100%;
  transform-origin: left center;
}

.tick {
  position: absolute;
  bottom: 0;
  width: 1px;
  height: 10px;
  background: #999;
}

.major-tick {
  height: 15px;
  background: #333;
}

.tick-label {
  position: absolute;
  transform: translateX(-50%);
  font-size: 12px;
}

交互功能扩展

添加鼠标事件处理逻辑实现拖动和缩放功能,通过 Vue 的自定义事件机制通知父组件状态变化。

vue实现手动标尺模块

export default {
  data() {
    return {
      isDragging: false,
      startX: 0,
      startOffset: 0
    }
  },
  methods: {
    handleMouseDown(e) {
      this.isDragging = true;
      this.startX = e.clientX;
      this.startOffset = this.offset;
      document.addEventListener('mousemove', this.handleMouseMove);
      document.addEventListener('mouseup', this.handleMouseUp);
    },
    handleMouseMove(e) {
      if (!this.isDragging) return;
      const delta = e.clientX - this.startX;
      this.$emit('update:offset', this.startOffset - delta);
    },
    handleMouseUp() {
      this.isDragging = false;
      document.removeEventListener('mousemove', this.handleMouseMove);
      document.removeEventListener('mouseup', this.handleMouseUp);
    }
  },
  mounted() {
    this.$refs.rulerRef.addEventListener('mousedown', this.handleMouseDown);
  },
  beforeDestroy() {
    this.$refs.rulerRef.removeEventListener('mousedown', this.handleMouseDown);
  }
}

缩放控制

添加滚轮事件监听实现缩放功能,限制缩放范围避免过度缩放。

export default {
  methods: {
    handleWheel(e) {
      e.preventDefault();
      const delta = e.deltaY > 0 ? -0.1 : 0.1;
      const newScale = Math.min(Math.max(this.scale + delta, 0.1), 10);
      this.$emit('update:scale', newScale);
    }
  },
  mounted() {
    this.$refs.rulerRef.addEventListener('wheel', this.handleWheel);
  }
}

性能优化

对于大型标尺场景,使用虚拟滚动技术减少 DOM 节点数量,通过动态计算只渲染可见区域的刻度。

export default {
  computed: {
    visibleTicks() {
      const ticks = [];
      const start = Math.max(0, Math.floor(this.offset / 100) * 100 - 100);
      const end = start + this.width / this.scale + 200;

      for (let i = start; i <= end; i += 10) {
        if (i < 0) continue;
        ticks.push({
          value: i,
          isMajor: i % 100 === 0,
          label: i.toString()
        });
      }
      return ticks;
    }
  }
}

组件使用示例

父组件通过 v-model 管理标尺状态,实现与其他组件的联动。

<template>
  <div>
    <RulerComponent 
      v-model:offset="offset"
      v-model:scale="scale"
      :width="containerWidth"
    />
    <!-- 其他关联组件 -->
  </div>
</template>

<script>
export default {
  data() {
    return {
      offset: 0,
      scale: 1,
      containerWidth: 800
    }
  }
}
</script>

标签: 标尺模块
分享给朋友:

相关文章

uniapp划动模块

uniapp划动模块

uniapp 滑动模块实现方法 使用 scroll-view 组件 scroll-view 是 uniapp 提供的滚动视图容器组件,支持横向和纵向滚动。基本属性包括 scroll-x(横向滚动)、s…

vue实现背景标尺

vue实现背景标尺

实现背景标尺的步骤 使用CSS和Vue动态生成标尺 在Vue中实现背景标尺可以通过CSS结合Vue的动态样式绑定来完成。以下是具体方法: 创建一个Vue组件,定义标尺的样式和布局。标尺通常包括水平…

vue实现树模块

vue实现树模块

Vue 实现树形组件的方法 递归组件实现树形结构 使用 Vue 的递归组件特性可以轻松实现树形结构。定义一个组件,该组件能够调用自身来渲染子节点。 <template> <ul…

vue评论模块如何实现

vue评论模块如何实现

实现评论模块的基本结构 使用 Vue 的单文件组件(SFC)结构,拆分评论模块为父组件和子组件。父组件管理数据逻辑,子组件负责渲染和交互。 <!-- CommentSection.vue -…

react如何动态加载模块

react如何动态加载模块

动态加载模块的方法 在React中动态加载模块可以通过几种方式实现,主要依赖于代码分割(Code Splitting)和动态导入(Dynamic Import)技术。以下是具体实现方法: 使用Re…

php模块实现

php模块实现

PHP 模块实现 PHP 模块通常指通过扩展 PHP 核心功能的自定义模块或扩展。以下是实现 PHP 模块的关键步骤和方法: 编写 PHP 扩展的基本流程 创建一个 PHP 扩展需要熟悉 C 语言和…