Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save leecz/853b76a5e6fb512c7d7fd3bbdc009899 to your computer and use it in GitHub Desktop.
Save leecz/853b76a5e6fb512c7d7fd3bbdc009899 to your computer and use it in GitHub Desktop.
<template>
<canvas :id="id" class="park-canvas" :height="height" width="400"></canvas>
</template>
<script>
const BOTTOM_HEIGHT = 30
const WEEKS_CN = ['一', '二', '三', '四', '五', '六', '日']
// 这个函数解决 canvas 在 Retina 屏下,线条模糊的问题
function scaleCanvas(cv, ctx) {
const pixelRatio = window.devicePixelRatio || 1
cv.style.width = cv.width + 'px' // CSS 属性,眼睛看到的 canvas 的宽度
cv.style.height = cv.height + 'px' // CSS 属性,眼睛看到的 canvas 的高度
cv.width *= pixelRatio // canvas 属性,根据设备像素比来增加画布的逻辑宽度
cv.height *= pixelRatio // canvas 属性,根据设备像素比来增加画布的逻辑高度
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0) // 如果画布的逻辑大小变大了,而 CSS 的大小不变,表现为实际看到的画布元素变小了,所以要缩放回来。跟屏幕类似。
}
export default {
data() {
return {
id: Math.random()
.toString(36)
.substring(7),
ctx: {},
canvas: {},
cWidth: 0,
cHeight: 0
}
},
props: {
// dataSet : [[1, 2], [ 100, 120], ...]
dataSet: {
type: Array,
default: []
},
primaryColor: {
type: String,
default: '#333333'
},
activeColor: {
type: String,
default: '#0dd122'
},
height: {
type: Number,
default: 100
}
},
watch: {
dataSet: {
deep: true,
handler() {
this.updateWeekStat()
}
}
},
methods: {
clearCanvas() {
this.ctx.clearRect(0, 0, this.cWidth, this.cHeight)
},
drawLine(ctx, beginX, beginY, endX, endY, color, width) {
ctx.beginPath()
ctx.moveTo(beginX, beginY)
ctx.lineTo(endX, endY)
ctx.strokeStyle = color
ctx.lineWidth = width
ctx.stroke()
},
addGraduations() {
// 画 刻度线, 一个星期 7格大格
let perStep = this.cWidth / 7
let ctx = this.ctx
this.drawLine(
ctx,
0,
this.cHeight - BOTTOM_HEIGHT,
this.cWidth,
this.cHeight - BOTTOM_HEIGHT,
this.primaryColor,
1
)
WEEKS_CN.forEach((el, index) => {
this.drawLine(
ctx,
Math.floor(perStep * index),
0,
Math.floor(perStep * index),
this.cHeight - BOTTOM_HEIGHT / 2,
this.primaryColor,
1
)
ctx.fillText(
el,
Math.floor(perStep * index + perStep / 2),
this.cHeight - BOTTOM_HEIGHT / 2
)
})
this.drawLine(
ctx,
this.cWidth - 0.5,
this.cHeight - BOTTOM_HEIGHT,
this.cWidth - 0.5,
this.cHeight - BOTTOM_HEIGHT / 2,
this.primaryColor,
1
)
},
renderCells() {
this.dataSet.forEach(data => {
let pxPerMin = this.cWidth / (7 * 24 * 60)
let start = data[0]
let end = data[1]
this.drawCell(
Math.floor(start * pxPerMin),
Math.floor((end - start) * pxPerMin)
)
})
},
drawCell(startX, width) {
this.ctx.fillStyle = this.activeColor
this.ctx.fillRect(startX, 0, width, this.cHeight - BOTTOM_HEIGHT)
},
updateWeekStat() {
this.clearCanvas()
let ctx = this.ctx
ctx.clearRect(0, 0, this.cWidth, this.cHeight)
ctx.fillStyle = '#666666'
ctx.fillRect(0, 0, this.cWidth, this.cHeight - BOTTOM_HEIGHT)
this.addGraduations()
this.renderCells()
},
renderWeekInfo() {
// 主渲染函数
const canvas = document.getElementById(this.id)
canvas.style.width = '100%'
canvas.width = canvas.offsetWidth
let ctx = canvas.getContext('2d')
this.cWidth = canvas.width
this.cHeight = canvas.height
scaleCanvas(canvas, ctx)
this.ctx = ctx
this.updateWeekStat()
}
},
mounted() {
this.renderWeekInfo()
}
}
</script>
<style lang="scss" scoped>
.park-canvas {
width: 100%;
height: auto;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment