Created
June 27, 2018 14:23
-
-
Save leecz/853b76a5e6fb512c7d7fd3bbdc009899 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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