- 使用
canvas
绘制 - 使用
div
绘制
我们将设定场景来讲解~
使用 canvas 绘制
实现均分尺子,如下图:
下面来讲解:
``html
均分尺子
减少 增加
Slider:
```
添加点样式,让布局不至于碍眼~
代码语言:javascript复制html, body {
padding: 0;
margin: 0;
height: 100%;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
// transform: scale(0.5);
// 可以通过 scale 进行缩放
}
#content {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
margin-bottom: 20px;
// transform: scale(0.5);
// 可以通过 scale 进行缩放
#canvas {
background-color: transparent;
}
.buttons {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-left: 12px;
button {
margin-top: 6px;
margin-bottom: 6px;
}
}
}
#controls {
display: flex;
justify-content: center;
align-items: center;
}
下面我们操作 javascript
实现功能(代码即文档):
window.onload = function() {
let caculateWidth = 199; // 宽度计算
let height = 288; // 高度固定(后期是计算)
let heightDivide = 10; // 等分固定
let paddingLeft = 20; // 左侧的预留
let paddingRight = 10; // 右侧的预留
let offset = 0; // 偏移的距离
let cell = height / heightDivide; // 每个单元格之间的距离
let canvasDom = document.getElementById('canvas'); // 获取画布
let rangeDom = document.getElementById('range');
rangeDom.addEventListener('change', changeSlider); // 监听 slider 的更改
let context = canvasDom.getContext('2d'); // 获取画笔
// 增加功能
let increaseDom = document.getElementById('increase');
increaseDom.addEventListener('click', () => {
if(offset >= 25) return;
offset = 1;
draw(caculateWidth paddingLeft paddingRight)
})
// 减少功能
let decreaseDom = document.getElementById('decrease');
decreaseDom.addEventListener('click', () => {
if(offset <= 0) return;
offset -= 1;
draw(caculateWidth paddingLeft paddingRight)
})
// 这部分是重点,对 canvas 进行操作
context.strokeStyle = '#000';
context.lineWidth = 1;
context.font = 12;
function draw(width) {
canvasDom.width = width;
canvasDom.height = height;
context.clearRect(0, 0, width, height);
// 水平线
for(let i = 0; i < heightDivide; i = 1) {
context.beginPath();
context.moveTo(paddingLeft, i * cell (cell / 2));
context.lineTo(caculateWidth paddingLeft, i * cell (cell / 2));
context.stroke();
context.closePath();
}
// 垂直线
for(let i = 0; i < heightDivide; i = 1) {
context.beginPath();
// 开始
context.moveTo(paddingLeft, i * cell (cell / 2) - 10);
context.lineTo(paddingLeft, i * cell (cell / 2) context.lineWidth / 2);
// 序号
context.fillText(i 1 offset, 0, i * cell (cell / 2));
for(let j = 0; j < i offset; j = 1) {
context.moveTo(caculateWidth / (i 1 offset) * (j 1) paddingLeft, i * cell (cell / 2) - 6);
context.lineTo(caculateWidth / (i 1 offset) * (j 1) paddingLeft, i * cell (cell / 2));
}
// 结尾
context.moveTo(caculateWidth paddingLeft, i * cell (cell / 2) - 10);
context.lineTo(caculateWidth paddingLeft, i * cell (cell / 2) context.lineWidth / 2);
context.stroke();
context.closePath();
}
}
draw(caculateWidth paddingLeft paddingRight);
// slider 更改
function changeSlider(event) {
caculateWidth = parseInt(event.target.value);
draw(caculateWidth paddingLeft paddingRight)
}
}
上面的代码,其实可以进一步提炼,比如 25
,可以设置为 const OFFSET_NUMBER = 25
。感兴趣的读者可以对其进行优化。
使用 div 绘制
绘制时间线,如下:
假设我们知道了开始的时间 10:10:13
- 其时间戳 diagramTimeFrameBegin
是 1691806213000
和间隔的时间 20
分钟 - 即变量 fragmentTime
为 20 * 60 * 1000
毫秒。
实现该 timeline
,我们主要是使用了伪元素。
代码语言:javascript复制案例使用到了
angular
的语法
<div class="timeline" #timeline>
<div class="horizontal-line begin-line">{{axisLabelFormatter(diagramTimeFrameBegin)}}</div>
<div *ngFor="let item of timelineData" class="horizontal-line middle-line"
[ngStyle]="{
'left': cellWidth * (item.index 1) 'px'
}"
>{{axisLabelFormatter(item.timestamp)}}</div>
<div class="horizontal-line end-line">{{axisLabelFormatter(diagramTimeFrameBegin fragmentTime)}}</div>
</div>
我们在 typescript
中对时间进行格式化:
import moment from "moment";
// format chart begin and end time
public formatChartTime(value: number): string {
return moment(value).format('HH:mm:ss');
}
重点是下面的 css
对刻度线的绘制和布局:
.timeline {
border-bottom: 1px solid #666;
position: relative;
height: 48px;
}
.timeline .horizontal-line {
width: 100px;
height: 48px;
line-height: 48px;
text-align: center;
position: absolute;
bottom: 0;
}
/* 绘制刻度 */
.timeline .horizontal-line:after {
content: "";
display: block;
width: 1px;
height: 10px;
background-color: #000;
margin-left: 50px;
position: relative;
bottom: 9px;
}
/* 居中对齐 */
.timeline .begin-line {
left: 0;
transform: translateX(-50%);
}
.timeline .middle-line {
transform: translateX(-50%);
}
.timeline .end-line {
right: 0;
transform: translateX(50%);
}
是的,我们介绍的这两种绘制刻度尺的方法,在这两个案例中是可以互相转换的。我们可以使用 canva
来画图,也可以直接使用多 html
元素来布局。具体的业务具体分析。