canvas+fabric实现时间刻度尺(二)

前言

我们前面实现了时间刻度尺,鼠标移动显示时间,接下来我们实现鼠标点击某个时间进行弹框。

效果

实现

1.监听鼠标按下事件

2.编写弹框页面

3.时间转换

javascript 复制代码
<template>
  <div>
      <canvas id="rulerCanvas" width="1200" height="400"></canvas>

     <el-dialog v-model="dialogVisible" title="添加调料" width="500">
          <div>
              <el-input v-model="input1" style="width: 240px" />
          </div>
          <div style="margin-top: 10px">
              <el-input v-model="input2" style="width: 240px" />
          </div>
          <template #footer>
              <div>
                  <el-button @click="dialogVisible = false">取消</el-button>
                  <el-button type="primary" @click="dialogVisible = false">确认</el-button>
              </div>
          </template>
      </el-dialog>
  </div>
</template>
<script setup>
import * as fabric  from 'fabric';
import {ref, onMounted} from 'vue';
 
 
const canvas = ref(null);

const value1 = ref(true);
const dialogVisible = ref(false);
const input1 = ref("测试商品名称");
const input2 = ref("");
const dialogConfirm = () => {
  dialogVisible.value = false;
  console.log("====添加====")
};

 
onMounted(() => {
  drawRuler();
});
 
 
 
let movDummyLine = null;
let movDummyLineText = null;
 
 
const onMouseMove = (options) => {
 
  if (options.pointer.x >= 40) {
    if (movDummyLine) {
      canvas.value.remove(movDummyLine);
      canvas.value.remove(movDummyLineText);
    }
    // 添加虚线
    movDummyLine = new fabric.Line([0, 800, 1, 0], {
      stroke: 'red',
      strokeDashArray: [5, 5],
      strokeWidth: 1,
      selectable: false,
    }).set({ left: options.pointer.x, top: 36 });
    canvas.value.add(movDummyLine);
    // group.add(movDummyLine);
 
 
    // 添加文字  (options.pointer.x)
    let startNumber = options.pointer.x - 40 + 20;
    let timeNumber = parseInt(startNumber / 20);
 
    movDummyLineText = new fabric.Text(timeToStr(timeNumber), {
      fontSize: 12,
      fill: 'black',
      selectable: false,
      textAlign: 'center',
    }).set({ left: options.pointer.x - 12, top: 20 });
    canvas.value.add(movDummyLineText);
    // group.add(movDummyLineText);
 
  }
 
};

const onMouseDown = (options) => {
  if (value1.value) {
    console.log("====onMouseMove====", options);
    let startNumber = options.pointer.x - 40;
    let timeNumber = parseInt(startNumber / 20);
    input2.value = timeToStr(timeNumber);
    dialogVisible.value = true;
  }
};

const drawRuler = () => {
  canvas.value = new fabric.Canvas('rulerCanvas');
 
  // 鼠标事件
  canvas.value.on('mouse:move', onMouseMove);

  canvas.value.on('mouse:down', onMouseDown);

  canvas.value.on('mouse:out', () => {
    if (movDummyLine) {
      canvas.value.remove(movDummyLine);
      canvas.value.remove(movDummyLineText);
      movDummyLine = null;
      movDummyLineText = null;
    }
  });
 
  // 时间刻度
  const startHour = 0;
  const startMinute = 0;
  const intervalMinutes = 5; // 间隔
  const totalHours = 1; // 当前刻度时间
  let currentMinute = startMinute;
  let currentHour = startHour;
 
  // 长方形
  const rect = new fabric.Rect({
    left: 0,
    top: 0,
    width: 1100,
    height: 40,
    fill: '#fff',
    strokeWidth: 1, // 边框宽度
    selectable: false,
  });
  canvas.value.add(rect);
  // 底部边框
  const bottomBorder = new fabric.Line([0, 40, 1200, 40], {
    stroke: '#000000',
    strokeWidth: 1,
    selectable: false,
  });
  canvas.value.add(bottomBorder);
 
  // 时间刻度
  for (let i = 0; i <= totalHours * 60; i += intervalMinutes) {
    const x = (i / (totalHours * 60)) *  canvas.value.width + 40;
    const timeText = formatTime(currentHour, currentMinute);
 
    // 画刻度线
    const b = new fabric.Line([x, 50, x, 60], {
      stroke: 'black',
      strokeWidth: 1,
      selectable: false,
    }).set({ left: x, top: 28 });
    canvas.value.add(b);
 
    // 添加时间文本
    const a = new fabric.Text(timeText, {
      fontSize: 12,
      fill: 'black',
      selectable: false,
      textAlign: 'center',
    }).set({ left: x-14, top: 10 });
    canvas.value.add(a);
 
    // 更新分钟和小时
    currentMinute += intervalMinutes;
    if (currentMinute >= 60) {
      currentMinute = 0;
      currentHour++;
    }
  }
};
 
const formatTime = (hour, minute) => {
  return `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
};
 
 
const timeToStr = (seconds) => {
  const minutes = Math.floor(seconds / 60);
  const secs = seconds % 60;
  const paddedMinutes = String(minutes).padStart(2, '0');
  const paddedSeconds = String(secs).padStart(2, '0');
  return `${paddedMinutes}:${paddedSeconds}`;
};
</script>
<style>
  #rulerCanvas {
      border: 1px solid black;
  }
</style>

如果侵权请联系我删除。

相关推荐
weixin_382395233 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__3 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.4 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~5 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华6 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子8 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅8 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni9 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学10 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端