前言
我们前面实现了时间刻度尺,现在在时间刻度尺里面画一个长方形,长方形里面有数据展示。
效果
实现
1.先实现时间刻度尺
2.鼠标移动、按下事件监听并画出对应效果
3.在刻度尺里面画对应的长方形数据展示
javascript
<template>
<div>
<canvas id="rulerCanvas" width="1200" height="400"></canvas>
<div style="margin-top: 20px">
<el-button type="primary" @click="test0">添加空标记</el-button>
<el-button type="primary" @click="test1">添加锅</el-button>
<el-button type="primary" @click="test2">添加用料</el-button>
<el-button type="primary" @click="test3">添加菜盒</el-button>
<el-button type="primary" @click="test4">添加结束录制</el-button>
<el-button type="primary" @click="test5" plain>清空全部</el-button>
</div>
<div style="margin-top: 20px">
<span style="margin-right: 6px">开启鼠标弹框</span><el-switch v-model="value1" />
</div>
<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="dialogConfirm">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import * as fabric from 'fabric';
import {ref, onMounted} from 'vue';
const value1 = ref(false);
const dialogVisible = ref(false);
const input1 = ref("测试商品名称");
const input2 = ref("");
const dialogConfirm = () => {
dialogVisible.value = false;
console.log("====添加====")
};
let left = 40;
const test0 = () => {
draw0();
};
const test1 = () => {
draw1()
};
const test2 = () => {
draw();
};
const test3 = () => {
draw();
};
const test4 = () => {
draw4();
};
const test5 = () => {
console.log("清空全部");
// canvas.value.clear();
};
const canvas = ref(null);
onMounted(() => {
drawRuler();
});
// const onClickItem = ref(false);
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;
}
};
let movDummyLine = null;
let movDummyLineText = null;
let group = null;
let dummyLineText = null;
// 空标记
const draw0 = () => {
group = new fabric.Group([], {
left: left,
top: 40,
width: 150,
height: 400,
selectable: true,
lockMovementY: true,
// 添加以下属性来隐藏边界框和控制点
hasBorders: false,
hasControls: false,
hasRotatingPoint: false,
});
left = left + 150 + 20;
group.on('selected', (e) => {
console.log('组被选中', e);
});
// 为组添加移动事件监听器
group.on('moving', () => {
if (group.left >= 40) {
let startNumber = group.left - 40 + 20;
let timeNumber = parseInt(startNumber / 20);
dummyLineText.set('text', timeToStr(timeNumber));
}
});
const rect = new fabric.Rect({
left: 0,
top: 0,
width: 150,
height: 400,
fill: '#d8f2ed',
selectable: false,
lockMovementY: true,
}).set({left: group.left - 3, top: group.top});
group.add(rect);
// 添加虚线
const dummyLine = new fabric.Line([0, 800, 1, 0], {
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
selectable: false,
}).set({ left: group.left, top: group.top});
group.add(dummyLine);
const line = new fabric.Line([0, 800, 2, 0], {
stroke: '#3cbca3',
strokeWidth: 2,
selectable: true,
lockMovementY: true,
}).set({ left: group.left, top: group.top });
group.add(line);
const titleText = new fabric.Text("空标记", {
fontSize: 12,
fill: 'black',
selectable: false,
textAlign: 'center',
}).set({ left: group.left + 4, top: group.top + 4 });
group.add(titleText);
// 刻度时间
dummyLineText = new fabric.Text("00:00", {
fontSize: 12,
fill: 'black',
selectable: false,
textAlign: 'center',
}).set({ left: group.left - 10, top: group.top - 20});
group.add(dummyLineText);
// 将组添加到画布上
canvas.value.add(group);
// 激活组的选择功能(选中该分组)
// canvas.value.setActiveObject(group);
};
// 锅设置
const draw1 = () => {
group = new fabric.Group([], {
left: left,
top: 220,
selectable: true,
lockMovementY: true,
// 添加以下属性来隐藏边界框和控制点
hasBorders: false,
hasControls: false,
hasRotatingPoint: false,
});
left = left + 150 + 20;
group.on('selected', (e) => {
console.log('组被选中', e);
});
// 为组添加移动事件监听器
group.on('moving', () => {
if (group.left >= 40) {
let startNumber = group.left - 40 + 20;
let timeNumber = parseInt(startNumber / 20);
dummyLineText.set('text', timeToStr(timeNumber));
}
});
const rect = new fabric.Rect({
left: 0,
top: 0,
width: 150,
height: 180,
fill: '#fff0e7',
selectable: false,
lockMovementY: true,
}).set({left: group.left - 3, top: group.top});
group.add(rect);
const line = new fabric.Line([0, 180, 2, 0], {
stroke: '#fc9153',
strokeWidth: 2,
selectable: true,
lockMovementY: true,
}).set({ left: group.left, top: group.top });
group.add(line);
// 添加虚线
const dummyLine = new fabric.Line([0, 800, 1, 0], {
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
selectable: false,
}).set({ left: group.left, top: group.top});
group.add(dummyLine);
const titleText = new fabric.Text("锅设置为xxxx", {
fontSize: 12,
fill: 'black',
selectable: false,
textAlign: 'center',
}).set({ left: group.left + 4, top: group.top + 4 });
group.add(titleText);
// 创建灰色背景的小矩形
const textBackground = new fabric.Rect({
left: group.left + 10,
top: group.top + 20,
width: 70,
height: 35,
fill: '#fbfbfb',
selectable: false,
rx: 4,
});
group.add(textBackground);
const text = new fabric.Text('测试文字', {
left: group.left + 10,
top: group.top + 20,
fontSize: 12,
fill: 'black',
textAlign: 'center',
selectable: false,
});
text.set({
top: text.top + textBackground.height / 2 - text.height / 2,
left: text.left + textBackground.width / 2 - text.width / 2,
});
group.add(text);
// 刻度时间
dummyLineText = new fabric.Text("00:00", {
fontSize: 12,
fill: 'black',
selectable: false,
textAlign: 'center',
}).set({ left: group.left - 10, top: group.top - 20});
group.add(dummyLineText);
// 将组添加到画布上
canvas.value.add(group);
// 激活组的选择功能(选中该分组)
// canvas.value.setActiveObject(group);
};
// 用料、菜盒
const draw = () => {
group = new fabric.Group([], {
left: left,
top: 40,
width: 150,
height: 400,
selectable: true,
lockMovementY: true,
// 添加以下属性来隐藏边界框和控制点
hasBorders: false,
hasControls: false,
hasRotatingPoint: false,
});
left = left + 150 + 20;
group.on('selected', (e) => {
console.log('组被选中', e);
});
// 为组添加移动事件监听器
group.on('moving', () => {
if (group.left >= 40) {
let startNumber = group.left - 40 + 20;
let timeNumber = parseInt(startNumber / 20);
dummyLineText.set('text', timeToStr(timeNumber));
}
});
const rect = new fabric.Rect({
left: 0,
top: 0,
width: 150,
height: 400,
fill: '#e1efff',
selectable: false,
lockMovementY: true,
}).set({left: group.left - 3, top: group.top});
group.add(rect);
// 添加虚线
const dummyLine = new fabric.Line([0, 800, 1, 0], {
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
selectable: false,
}).set({ left: group.left, top: group.top});
group.add(dummyLine);
const line = new fabric.Line([0, 800, 2, 0], {
stroke: '#288bfd',
strokeWidth: 2,
selectable: true,
lockMovementY: true,
}).set({ left: group.left, top: group.top });
group.add(line);
const titleText = new fabric.Text("自动投放猪油11g", {
fontSize: 12,
fill: 'black',
selectable: false,
textAlign: 'center',
}).set({ left: group.left + 4, top: group.top + 4 });
group.add(titleText);
// 创建灰色背景的小矩形
const textBackground = new fabric.Rect({
left: group.left + 10,
top: group.top + 20,
width: 70,
height: 35,
fill: '#fbfbfb',
selectable: false,
rx: 4,
});
group.add(textBackground);
const text = new fabric.Text('测试文字', {
left: group.left + 10,
top: group.top + 20,
fontSize: 12,
fill: 'black',
textAlign: 'center',
selectable: false,
});
text.set({
top: text.top + textBackground.height / 2 - text.height / 2,
left: text.left + textBackground.width / 2 - text.width / 2,
});
group.add(text);
// 刻度时间
dummyLineText = new fabric.Text("00:00", {
fontSize: 12,
fill: 'black',
selectable: false,
textAlign: 'center',
}).set({ left: group.left - 10, top: group.top - 20});
group.add(dummyLineText);
// 将组添加到画布上
canvas.value.add(group);
// 激活组的选择功能(选中该分组)
// canvas.value.setActiveObject(group);
};
// 结束录制
const draw4 = () => {
group = new fabric.Group([], {
left: 1150,
top: 40,
width: 150,
height: 400,
selectable: true,
lockMovementY: true,
// 添加以下属性来隐藏边界框和控制点
hasBorders: false,
hasControls: false,
hasRotatingPoint: false,
});
left = left + 150 + 20;
group.on('selected', (e) => {
console.log('组被选中', e);
});
// 为组添加移动事件监听器
group.on('moving', () => {
if (group.left >= 40) {
let startNumber = group.left - 40 + 20;
let timeNumber = parseInt(startNumber / 20);
dummyLineText.set('text', timeToStr(timeNumber));
}
});
const rect = new fabric.Rect({
left: 0,
top: 0,
width: 50,
height: 400,
fill: '#ff4d4f',
selectable: false,
lockMovementY: true,
}).set({left: group.left - 3, top: group.top});
group.add(rect);
// 添加虚线
const dummyLine = new fabric.Line([0, 800, 1, 0], {
stroke: '#222',
strokeDashArray: [5, 5],
strokeWidth: 1,
selectable: false,
}).set({ left: group.left, top: group.top});
group.add(dummyLine);
const titleText = new fabric.Text("烹\n饪\n结\n束", {
fontSize: 16,
fill: '#fff',
selectable: false,
textAlign: 'center',
}).set({ left: group.left + 14, top: 180 });
group.add(titleText);
// 刻度时间
dummyLineText = new fabric.Text("00:00", {
fontSize: 12,
fill: 'black',
selectable: false,
textAlign: 'center',
}).set({ left: group.left - 10, top: group.top - 20});
group.add(dummyLineText);
// 将组添加到画布上
canvas.value.add(group);
// 激活组的选择功能(选中该分组)
// canvas.value.setActiveObject(group);
};
const onMouseMove = (options) => {
// console.log("====onMouseMove====", options);
// console.log("====onMouseMove====", options.pointer.x);
// let testStr = "00:28";
// console.log(testStr, "======================", strToTime(testStr));
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 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 strToTime = (str) => {
// let parts = str.split(':');
// return parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10);
// };
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>
如果侵权请联系我删除。