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>

如果侵权请联系我删除。

相关推荐
hdsoft_huge2 分钟前
1panel面板中部署SpringBoot和Vue前后端分离系统 【图文教程】
vue.js·spring boot·后端
CappuccinoRose26 分钟前
JavaScript 学习文档(二)
前端·javascript·学习·数据类型·运算符·箭头函数·变量声明
这儿有一堆花32 分钟前
Vue 是什么:一套为「真实业务」而生的前端框架
前端·vue.js·前端框架
全栈前端老曹1 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
NCDS程序员1 小时前
v-model: /v-model/ :(v-bind)三者核心区别
前端·javascript·vue.js
夏幻灵1 小时前
CSS三大特性:层叠、继承与优先级解析
前端·css
小杨同学呀呀呀呀2 小时前
Ant Design Vue <a-timeline>时间轴组件失效解决方案
前端·javascript·vue.js·typescript·anti-design-vue
qq_532453532 小时前
使用 Three.js 构建沉浸式全景图AR
开发语言·javascript·ar
华玥作者10 小时前
[特殊字符] VitePress 对接 Algolia AI 问答(DocSearch + AI Search)完整实战(下)
前端·人工智能·ai
Mr Xu_10 小时前
告别冗长 switch-case:Vue 项目中基于映射表的优雅路由数据匹配方案
前端·javascript·vue.js