一、简介
使用canvas,模拟绘制时间轴区域,有时间刻度标尺,时间轴区域上会有多行,每行都有一个滑块。
1、时间刻度标尺可以拖动,会自动对齐整数点秒数,最小步数为0.1秒。
2、滑块可以自由拖动,当滑块处于选中状态时,左右两边会出现可拖动的按钮,用于拉伸宽度。
3、滑块之间可以自由拖动交换位置。
4、滑块与滑块之间对齐时会出现对齐虚线,滑块与刻度标尺对齐时,刻度标尺会变色用于提醒用户此时已对齐。
5、当滑块拉伸到最右侧区域时,右侧空间不足时,会自动增加右侧空间区域。而当做右侧滑块的位置往左移动时,如果出现右侧空间区域过大,则会自动减少右侧空间区域,始终保持右侧空间留白区域是预设的宽度。
二、案例代码
<template>
<div class="main-container" ref="tWrap" @scroll="tWrapScroll($event)">
<canvas id="tl-canvas" ref="tl-canvas" width="700" height="300" @mousedown.stop.prevent="cMouseDown($event)"
@mousemove.stop.prevent="cMouseMove($event)" @mouseup.stop.prevent="cMouseUp($event)"
@mouseleave.stop.prevent="cMouseUp($event)"></canvas>
<div class="hidden-box" :style="{
width: cMaxWidth + 'px',
height: cMaxHeight + 'px'
}"></div>
</div>
</template>
<script>
export default {
data() {
return {
tWrapScrollTop: 0,
tWrapScrollLeft: 0,
tWrapEle: null,
tCanvas: null,
ctx: null,
minY: 50,
maxY: 500,
minX: 10, // 可拖动的x轴最左侧
maxX: 700, // 可拖动的x轴最右侧
rDistant: 300, // 画布右侧留白区域距离
cWidth: 700, // 画布的宽度
cHeight: 300, // 画布的高度
cMaxWidth: 1000, // 实际画布需要的宽度
cMaxHeight: 500, // 实际画布需要的高度
btnWidth: 20, // 左右按钮宽度
lineHeight: 50, // 滑块高度
moveItem: null, // 当前移动的滑块
items: [
{
zIndex: 1,
id: 1,
active: false,
tTop: 0,
tLeft: 10,
tWidth: 100,
tHeight: 50
},
{
zIndex: 2,
id: 2,
active: false,
tTop: 0,
tLeft: 10,
tWidth: 150,
tHeight: 50
},
{
zIndex: 3,
id: 3,
active: false,
tTop: 0,
tLeft: 10,
tWidth: 200,
tHeight: 50
},
],
bcMoveAbled: false, // 刻度尺可移动的标识
moveAbled: false, // 滑块可移动的标识
dragLeftAbled: false, // 滑块可左拖的标识
dragRightAbled: false, // 滑块可右拖的标识
oldMouseX: 0,
oldMouseY: 0,
alignLine: null, // 对齐虚线对象
alignStaff: false, // 刻度尺对齐标识
currentTime: 10, // 刻度尺当前对齐的时间
}
},
mounted() {
this.$nextTick(() => {
this.tCanvas = document.getElementById('tl-canvas')
this.ctx = this.tCanvas.getContext('2d')
let twrap = this.$refs['tWrap'].getBoundingClientRect()
this.tWrapEle = twrap
this.updateCanvasDom()
this.doDrawTimeLine()
})
},
beforeUnmount() {
},
methods: {
/**
* 监听滚动事件
* @param {*} e
*/
tWrapScroll(e) {
this.tWrapScrollTop = this.$refs['tWrap'].scrollTop
this.tWrapScrollLeft = this.$refs['tWrap'].scrollLeft
// console.log(this.$refs['tWrap'].scrollTop)
},
/**
* 判断点是否在多边形内
* @param {*} p
* @param {*} ptPolygon
*/
isInPolygon(p, ptPolygon) {
let ncross = 0;
for (let i = 0; i < ptPolygon.length; i++) {
let p1 = ptPolygon[i];
let p2 = ptPolygon[(i + 1) % ptPolygon.length]; // 相邻两条边p1,p2
if (p1.y == p2.y) {
continue;
}
if (p.y < Math.min(p1.y, p2.y)) {
continue;
}
if (p.y >= Math.max(p1.y, p2.y)) {
continue;
}
let x = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if (x > p.x) {
ncross++; // 只统计单边交点
}
}
return (ncross % 2 == 1);
},
/**
* 判断是否出现对齐虚线
*/
showAlignLine(item) {
let _n = 3
// 判断是否对齐刻度尺
let _bcX = (this.currentTime*10+this.minX)
// 移动对齐标尺
if(this.moveAbled) {
if(Math.abs(item.tLeft - _bcX) <= _n) {
this.alignStaff = true
return {
left: _bcX
}
} else if(Math.abs(item.tLeft+item.tWidth - _bcX) <= _n) {
this.alignStaff = true
return {
left: _bcX - item.tWidth
}
} else {
this.alignStaff = false
}
}
// 左拖对齐标尺
else if(this.dragLeftAbled) {
if(Math.abs(item.tLeft - _bcX) <= _n) {
this.alignStaff = true
return {
n: item.tLeft - _bcX,
left: _bcX
}
} else {
this.alignStaff = false
}
}
// 右拖对齐标尺
else if(this.dragRightAbled) {
if(Math.abs(item.tLeft + item.tWidth - _bcX) <= _n) {
this.alignStaff = true
return {
n: _bcX - (item.tLeft + item.tWidth)
}
} else {
this.alignStaff = false
}
}
// 判断滑块之间的对齐
for(let i=0; i < this.items.length; i++) {
// 移动
if(this.moveAbled && i !== this.moveItem.index) {
if(Math.abs(item.tLeft - this.items[i].tLeft) <= _n) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft,
height: this.cHeight
}
return {
left: this.items[i].tLeft
}
break
}
else if(Math.abs(item.tLeft+item.tWidth - this.items[i].tLeft) <= _n ) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft,
height: this.cHeight
}
return {
left: this.items[i].tLeft - item.tWidth
}
break
}
else if(Math.abs(this.items[i].tLeft+this.items[i].tWidth - item.tLeft) <= _n) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft+this.items[i].tWidth,
height: this.cHeight
}
return {
left: this.items[i].tLeft+this.items[i].tWidth
}
break
}
else if(Math.abs(item.tLeft+item.tWidth - (this.items[i].tLeft+this.items[i].tWidth)) <= _n) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft+this.items[i].tWidth,
height: this.cHeight
}
return {
left: this.items[i].tLeft+this.items[i].tWidth - item.tWidth
}
break
}
}
// 左拖
else if(this.dragLeftAbled && i !== this.moveItem.index) {
if(Math.abs(item.tLeft - this.items[i].tLeft) <= _n) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft,
height: this.cHeight
}
return {
n: item.tLeft - this.items[i].tLeft,
left: this.items[i].tLeft
}
break
}
else if(Math.abs(this.items[i].tLeft+this.items[i].tWidth - item.tLeft) <= _n) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft+this.items[i].tWidth,
height: this.cHeight
}
return {
n: item.tLeft - (this.items[i].tLeft+this.items[i].tWidth),
left: this.items[i].tLeft+this.items[i].tWidth
}
break
}
}
// 右拖
else if(this.dragRightAbled && i !== this.moveItem.index) {
if(Math.abs(item.tLeft+item.tWidth - (this.items[i].tLeft+this.items[i].tWidth)) <= _n) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft+this.items[i].tWidth,
height: this.cHeight
}
return {
n: this.items[i].tLeft+this.items[i].tWidth - (item.tLeft+item.tWidth),
// left: this.items[i].tLeft+this.items[i].tWidth - item.tWidth
}
break
}
else if(Math.abs(item.tLeft+item.tWidth - this.items[i].tLeft) <= _n) {
this.alignLine = {
top: 0,
left: this.items[i].tLeft,
height: this.cHeight
}
return {
n: this.items[i].tLeft - (item.tLeft+item.tWidth),
// left: this.items[i].tLeft - item.tWidth
}
break
}
}
}
// 没有对齐
this.alignLine = null
return false
},
/**
* 检测当前滑块的最大长度和数量,随时更新画布的最大宽度和高度
*/
updateCanvasDom() {
let maxWidth = 0
// 按层级排序
this.items.sort((a, b) => b.zIndex - a.zIndex)
for (let i = 0; i < this.items.length; i++) {
// 获取最大宽度
maxWidth = this.items[i].tLeft + this.items[i].tWidth > maxWidth ? this.items[i].tLeft + this.items[i].tWidth : maxWidth
// 重新更新y坐标
this.items[i].tTop = 5 + this.lineHeight * i + 5 * i + this.minY
}
this.items = JSON.parse(JSON.stringify(this.items))
// 留白区域大于预设
if (this.cMaxWidth - maxWidth > this.rDistant && this.cMaxWidth - this.rDistant > this.cWidth) {
this.cMaxWidth = maxWidth + this.rDistant
this.maxX = this.cMaxWidth - this.rDistant
}
// 留白区域小于预设
if (this.cMaxWidth - maxWidth < this.rDistant) {
this.cMaxWidth += (this.rDistant - (this.cMaxWidth - maxWidth))
this.maxX = this.cMaxWidth - this.rDistant
}
this.cMaxHeight = this.items.length * 55 > this.maxY ? this.items.length * 55 : this.maxY
},
/**
* 鼠标点击
*/
cMouseDown(e) {
// 判断是否点击到标尺
let _bcX = this.minX + this.currentTime*10
let _mX = e.clientX - this.tWrapEle.left + this.tWrapScrollLeft
if(_mX >= _bcX - 2 && _mX <= _bcX+2) {
console.log('点击标尺', this.currentTime)
this.tCanvas.style.cursor = 'grab'
this.bcMoveAbled = true
this.oldMouseX = e.clientX
this.oldMouseY = e.clientY
return
}
// 判断是否点击到滑块
for (let i = 0; i < this.items.length; i++) {
let item = JSON.parse(JSON.stringify(this.items[i]))
item.tLeft = item.tLeft - this.tWrapScrollLeft
item.tTop = item.tTop - this.tWrapScrollTop
// 判断鼠标坐标是否在滑块上
if (this.isInPolygon({
x: e.clientX - this.tWrapEle.left,
y: e.clientY - this.tWrapEle.top
}, [
{
x: item.tLeft,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop + item.tHeight
},
{
x: item.tLeft,
y: item.tTop + item.tHeight
}
])) {
if (item.active) {
// 判断是否在右按钮上
if (this.isInPolygon({
x: e.clientX - this.tWrapEle.left,
y: e.clientY - this.tWrapEle.top
}, [
{
x: item.tLeft + item.tWidth - this.btnWidth,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop + item.tHeight
},
{
x: item.tLeft + item.tWidth - this.btnWidth,
y: item.tTop + item.tHeight
}
])) {
this.dragRightAbled = true
this.tCanvas.style.cursor = 'e-resize'
}
// 判断是否在左按钮上
else if (this.isInPolygon({
x: e.clientX - this.tWrapEle.left,
y: e.clientY - this.tWrapEle.top
}, [
{
x: item.tLeft,
y: item.tTop
},
{
x: item.tLeft + this.btnWidth,
y: item.tTop
},
{
x: item.tLeft + this.btnWidth,
y: item.tTop + item.tHeight
},
{
x: item.tLeft,
y: item.tTop + item.tHeight
}
])) {
this.dragLeftAbled = true
this.tCanvas.style.cursor = 'w-resize'
}
// 在滑块上
else {
this.moveAbled = true
this.tCanvas.style.cursor = 'grab'
}
} else {
for (let i = 0; i < this.items.length; i++) {
this.items[i].active = false
}
// 在滑块上
this.tCanvas.style.cursor = 'grab'
this.moveAbled = true
this.items[i].active = true
}
// 保存移动的item
this.moveItem = JSON.parse(JSON.stringify(this.items[i]))
this.moveItem.index = i
console.log('点击', this.moveItem)
this.oldMouseX = e.clientX
this.oldMouseY = e.clientY
break
} else {
this.tCanvas.style.cursor = 'auto'
this.items[i].active = false
this.moveAbled = false
this.dragLeftAbled = false
this.dragRightAbled = false
this.oldMouseX = 0
this.oldMouseY = 0
}
}
},
/**
* 鼠标移动
*/
cMouseMove(e) {
// 刻度尺
if(this.bcMoveAbled) {
let _oldMouseX = e.clientX
let _d = _oldMouseX - this.oldMouseX
this.oldMouseX = _oldMouseX
let _n = 0.3
let _time = this.currentTime + _d/10
// 判断是否越界了
if(_time < 0) {
_time = 0
}
else if(_time * 10 + this.minX > this.maxX) {
console.log('xxxx', this.maxX)
_time = (this.maxX - this.minX)/10
}
// 判断是否移动到整数秒位置
else if(Math.abs(Math.round(_time) - _time) <= _n) {
this.oldMouseX += (Math.round(_time) - _time)*10
_time = Math.round(_time)
this.alignStaff = true
}
else {
this.alignStaff = false
}
this.currentTime = _time
console.log(this.currentTime)
}
else if (this.moveItem) {
// 移动中
if (this.moveAbled) {
let item = JSON.parse(JSON.stringify(this.moveItem))
// console.log(item)
let _oldMouseX = e.clientX
let _oldMouseY = e.clientY
let _d = _oldMouseX - this.oldMouseX
let _dy = _oldMouseY - this.oldMouseY
this.oldMouseX = _oldMouseX
this.oldMouseY = _oldMouseY
// 最左侧/最右侧/最上侧/最底侧
// if (item.tLeft + _d < this.minX || item.tLeft+item.tWidth + _d > this.maxX || item.tTop + _dy < this.minY || item.tTop + _dy + item.tHeight > this.maxY) {
if (item.tLeft + _d < this.minX || item.tTop + _dy < this.minY || item.tTop + _dy + item.tHeight > this.maxY) {
return
}
item.tLeft += _d
item.tTop += _dy
// 判断是否对齐
let _e = this.showAlignLine(item)
if(_e) {
item.tLeft = _e.left
}
this.moveItem = JSON.parse(JSON.stringify(item))
} else {
for (let i = 0; i < this.items.length; i++) {
if (this.moveItem.id == this.items[i].id) {
let item = JSON.parse(JSON.stringify(this.items[i]))
// 左拖中
if (this.dragLeftAbled) {
let _oldMouseX = e.clientX
let _oldMouseY = e.clientY
let _d = _oldMouseX - this.oldMouseX
this.oldMouseX = _oldMouseX
this.oldMouseY = _oldMouseY
// 滑块最小宽度/最左侧
if (item.tWidth - _d <= this.btnWidth || item.tLeft + _d < this.minX) {
return
}
item.tWidth -= _d
item.tLeft += _d
// 判断是否对齐
let _e = this.showAlignLine(item)
if(_e) {
this.oldMouseX += _e.n
this.items[i].tWidth = item.tWidth + _e.n
this.items[i].tLeft = _e.left
} else {
this.items[i] = JSON.parse(JSON.stringify(item))
}
}
// 右拖中
else if (this.dragRightAbled) {
let _oldMouseX = e.clientX
let _oldMouseY = e.clientY
let _d = _oldMouseX - this.oldMouseX
this.oldMouseX = _oldMouseX
this.oldMouseY = _oldMouseY
// 滑块最小宽度/最右侧
// if (item.tWidth + _d <= this.btnWidth || item.tLeft + item.tWidth + _d > this.maxX) {
if (item.tWidth + _d <= this.btnWidth) {
return
}
item.tWidth += _d
// 判断是否对齐
let _e = this.showAlignLine(item)
if(_e) {
this.oldMouseX += _e.n
this.items[i].tWidth = item.tWidth + _e.n
} else {
this.items[i] = JSON.parse(JSON.stringify(item))
}
this.updateCanvasDom()
}
break
}
}
}
}
else {
// 判断是否点击到标尺
let _mX = e.clientX - this.tWrapEle.left + this.tWrapScrollLeft
let _bcX = this.minX + this.currentTime*10
if(_mX >= _bcX - 2 && _mX <= _bcX + 2) {
this.tCanvas.style.cursor = 'grab'
return
}
for (let i = 0; i < this.items.length; i++) {
let item = JSON.parse(JSON.stringify(this.items[i]))
item.tLeft = item.tLeft - this.tWrapScrollLeft
item.tTop = item.tTop - this.tWrapScrollTop
// 判断鼠标坐标是否在滑块上
if (this.isInPolygon({
x: e.clientX - this.tWrapEle.left,
y: e.clientY - this.tWrapEle.top
}, [
{
x: item.tLeft,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop + item.tHeight
},
{
x: item.tLeft,
y: item.tTop + item.tHeight
}
])) {
if (item.active) {
// 判断是否在左按钮上
if (this.isInPolygon({
x: e.clientX - this.tWrapEle.left,
y: e.clientY - this.tWrapEle.top
}, [
{
x: item.tLeft,
y: item.tTop
},
{
x: item.tLeft + this.btnWidth,
y: item.tTop
},
{
x: item.tLeft + this.btnWidth,
y: item.tTop + item.tHeight
},
{
x: item.tLeft,
y: item.tTop + item.tHeight
}
])) {
this.tCanvas.style.cursor = 'w-resize'
}
// 判断是否在右按钮上
else if (this.isInPolygon({
x: e.clientX - this.tWrapEle.left,
y: e.clientY - this.tWrapEle.top
}, [
{
x: item.tLeft + item.tWidth - this.btnWidth,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop
},
{
x: item.tLeft + item.tWidth,
y: item.tTop + item.tHeight
},
{
x: item.tLeft + item.tWidth - this.btnWidth,
y: item.tTop + item.tHeight
}
])) {
this.tCanvas.style.cursor = 'e-resize'
} else {
this.tCanvas.style.cursor = 'grab'
}
} else {
this.tCanvas.style.cursor = 'grab'
}
break
} else {
this.tCanvas.style.cursor = 'auto'
}
}
}
},
/**
* 鼠标松开
* @param {*} e
*/
cMouseUp(e) {
if (this.moveAbled && this.moveItem) {
for (let i = 0; i < this.items.length; i++) {
// 判断中点是否在行内
// let _cx = this.moveItem.tLeft + this.moveItem.tWidth / 2 + this.minX
let _cy = this.moveItem.tTop + this.moveItem.tHeight / 2
if (_cy > this.items[i].tTop && _cy < this.items[i].tTop + this.items[i].tHeight) {
// console.log('在'+i+'行内')
if (this.items[i].id !== this.moveItem.id) {
let _oZindex = this.moveItem.zIndex
let _nZindex = this.items[i].zIndex
this.items[this.moveItem.index].zIndex = _nZindex
this.items[this.moveItem.index].tLeft = this.moveItem.tLeft
this.items[i].zIndex = _oZindex
} else {
this.items[i].tLeft = this.moveItem.tLeft
}
break
}
}
}
this.bcMoveAbled = false
this.moveAbled = false
this.dragLeftAbled = false
this.dragRightAbled = false
this.oldMouseX = 0
this.oldMouseY = 0
this.moveItem = null
this.alignLine = null
this.alignStaff = false
this.updateCanvasDom()
},
doDrawTimeLine() {
cancelAnimationFrame(this.requestAnimationFrameId)
this.drawTimeLine()
this.requestAnimationFrameId = requestAnimationFrame(this.doDrawTimeLine)
},
/**
* 绘制时间轴
*/
drawTimeLine() {
// this.ctx.reset()
this.ctx.clearRect(0, 0, this.cWidth, this.cHeight)
// 绘制行数
this.drawLine()
// 绘制最右侧线条
this.ctx.beginPath()
this.ctx.moveTo(this.maxX - this.tWrapScrollLeft, 0)
this.ctx.lineTo(this.maxX- this.tWrapScrollLeft, this.maxY)
this.ctx.stroke()
// 滑块绘制
for (let i = 0; i < this.items.length; i++) {
let item = JSON.parse(JSON.stringify(this.items[i]))
item.tLeft = item.tLeft - this.tWrapScrollLeft
item.tTop = item.tTop - this.tWrapScrollTop
this.drawHk(item)
if (this.moveAbled && this.moveItem) {
let _item = JSON.parse(JSON.stringify(this.moveItem))
_item.tLeft = _item.tLeft - this.tWrapScrollLeft
_item.tTop = _item.tTop - this.tWrapScrollTop
this.ctx.save()
this.ctx.globalAlpha = 0.3
this.drawHk(_item)
this.ctx.restore()
}
}
if(this.alignLine) {
// 绘制对齐虚线
this.ctx.save()
this.ctx.strokeStyle = 'white'
this.ctx.setLineDash([5,5])
this.ctx.lineWidth = 2
this.ctx.beginPath()
this.ctx.moveTo(this.alignLine.left - this.tWrapScrollLeft, this.alignLine.top)
this.ctx.lineTo(this.alignLine.left - + this.tWrapScrollLeft, this.alignLine.top+this.alignLine.height)
this.ctx.stroke()
this.ctx.restore()
}
// 绘制标尺
this.drawStaff()
},
/**
* 标尺绘制
*/
drawStaff() {
this.ctx.save()
if(this.alignStaff) {
this.ctx.fillStyle = 'pink'
} else {
this.ctx.fillStyle = 'white'
}
this.ctx.fillRect(this.minX + this.currentTime * 10 - 1 - this.tWrapScrollLeft, 0, 2, this.cHeight)
this.ctx.restore()
},
/**
* 行数绘制
*/
drawLine() {
for (let i = 0; i < this.items.length; i++) {
this.ctx.save()
this.ctx.beginPath()
this.ctx.fillStyle = 'yellow'
this.ctx.fillRect(this.minX - this.tWrapScrollLeft, this.minY + 5 + this.lineHeight * i + 5 * i - this.tWrapScrollTop, this.cMaxWidth, this.lineHeight)
this.ctx.fill()
this.ctx.restore()
}
},
/**
* 滑块绘制
*/
drawHk(item) {
// 绘制滑块
this.ctx.save()
this.ctx.fillStyle = 'red'
this.ctx.beginPath()
this.ctx.roundRect(item.tLeft, item.tTop, item.tWidth, item.tHeight, 3)
// this.ctx.fillRect(item.tLeft, item.tTop, item.tWidth, item.tHeight)
this.ctx.fill()
this.ctx.restore()
if (item.active) {
// 绘制编辑框
this.ctx.save()
// 左按钮
this.ctx.beginPath()
this.ctx.roundRect(item.tLeft, item.tTop, this.btnWidth, item.tHeight, [3, 0, 0, 3])
this.ctx.fillStyle = 'gray'
this.ctx.fill()
let _w = 2
let _h = 12
this.ctx.fillStyle = 'white'
this.ctx.fillRect(item.tLeft + (this.btnWidth - _w * 3) / 2, item.tTop + (item.tHeight - _h) / 2, _w, _h)
this.ctx.fillRect(item.tLeft + (this.btnWidth - _w * 3) / 2 + _w * 2, item.tTop + (item.tHeight - _h) / 2, _w, _h)
// 右按钮
this.ctx.beginPath()
this.ctx.roundRect(item.tLeft + item.tWidth - this.btnWidth, item.tTop, this.btnWidth, item.tHeight, [0, 3, 3, 0])
this.ctx.fillStyle = 'gray'
this.ctx.fill()
this.ctx.fillStyle = 'white'
this.ctx.fillRect(item.tLeft + item.tWidth - this.btnWidth + (this.btnWidth - _w * 3) / 2, item.tTop + (item.tHeight - _h) / 2, _w, _h)
this.ctx.fillRect(item.tLeft + item.tWidth - this.btnWidth + (this.btnWidth - _w * 3) / 2 + _w * 2, item.tTop + (item.tHeight - _h) / 2, _w, _h)
// 外边框
this.ctx.beginPath()
this.ctx.strokeStyle = "black"
this.ctx.lineWidth = 1
this.ctx.roundRect(item.tLeft+1, item.tTop+1, item.tWidth-2, item.tHeight-2, 3)
this.ctx.stroke()
// 文本
this.ctx.fillStyle = 'white'
this.ctx.font = "20px serif"
this.ctx.textBaseline = 'middle'
this.ctx.fillText('测试文本sssssswqwqwqwqwqwq', item.tLeft + this.btnWidth + 10, item.tTop + item.tHeight / 2, item.tWidth - this.btnWidth * 2 - 20)
this.ctx.restore()
} else {
// 文本
this.ctx.fillStyle = 'white'
this.ctx.font = "20px serif"
this.ctx.textBaseline = 'middle'
this.ctx.fillText('测试文本sssssswqwqwqwqwqwq', item.tLeft + this.btnWidth + 10, item.tTop + item.tHeight / 2, item.tWidth - this.btnWidth * 2 - 20)
}
}
}
}
</script>
<style lang="scss" scoped>
.main-container {
margin: 50px;
position: relative;
width: 700px;
height: 300px;
background-color: green;
overflow: auto;
#tl-canvas {
z-index: 11;
position: sticky;
top: 0;
left: 0;
width: 700px;
height: 300px;
}
.hidden-box {
position: absolute;
top: 0;
left: 0;
z-index: -1;
opacity: 0;
width: 1000px;
height: 500px;
}
}
</style>