复制代码即可用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>canvas</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
.box {
position: absolute;
top: 10px;
left: 10px;
border: 1px solid greenyellow;
}
#canvas {
border: 1px solid green;
}
#rightBottom {
width: 50px;
height: 50px;
border: 1px solid red;
position: absolute;
bottom: 0;
right: 0;
cursor: se-resize;
}
#centerBox {
width: 50px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -25px;
margin-top: -25px;
border: 1px solid red;
cursor: pointer;
}
</style>
</head>
<body>
<div class="box">
<canvas id="canvas" width="600" height="500"></canvas>
<div id="centerBox"></div>
<div id="rightBottom"></div>
</div>
<script>
let data = [
{ xAxis: 2012, value: 2141 },
{ xAxis: 2013, value: 1499 },
{ xAxis: 2014, value: 3260 },
{ xAxis: 2015, value: 1170 },
{ xAxis: 2016, value: 970 },
{ xAxis: 2017, value: 2350 }
]
let canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
width = null,
height = null,
current = 0,
yRatio = 0,
padding = 0,
yNumber = 0,
yLength = 0,
xLength = 0,
box = document.querySelector('#rightBottom'),
flag = false,
centerBox = document.querySelector('#centerBox'),
totalBox = document.querySelector('.box'),
moveFlag = false
resize()
function resize() {
width = canvas.width
height = canvas.height
padding = 50
if (flag) {
current = 99
}
init()
looping()
}
function init() {
//=== 坐标轴 ===
ctx.beginPath()
ctx.lineWidth = 1
//y轴
ctx.moveTo(padding + 0.5, height - padding + 0.5)
ctx.lineTo(padding + 0.5, padding + 0.5)
ctx.stroke()
//x轴
ctx.moveTo(padding + 0.5, height - padding + 0.5)
ctx.lineTo(width - padding + 0.5, height - padding + 0.5)
ctx.stroke()
//y轴 x轴 刻度和值
yNumber = 5
yLength = Math.floor((height - padding * 2) / yNumber)
xLength = Math.floor((width - padding * 2) / data.length)
yRatio = yLength / 700
// ctx.beginPath()
ctx.textAlign = 'center'
ctx.fillStyle = '#000'
ctx.strokeStyle = '#000'
// y轴刻度和值
for (let i = 0; i < yLength; i++) {
let y = 700 * (i + 1),
ylen = yLength * (i + 1)
ctx.moveTo(padding + 5, height - padding - ylen)
ctx.lineTo(padding, height - padding - ylen)
ctx.stroke()
ctx.fillText(y, padding - 15, height - padding - ylen + 5)
}
// x轴刻度和值
for (let j = 0; j < data.length; j++) {
let xAxis = data[j].xAxis,
xlen = yLength * (j + 1)
ctx.moveTo(padding + xlen, height - padding)
ctx.lineTo(padding + xlen, height - padding + 5)
ctx.stroke() // 画轴线上的刻度
ctx.fillText(
xAxis,
padding + xlen - xLength / 2,
height - padding + 15
) // 填充文字
}
}
function looping() {
looped = requestAnimationFrame(looping)
if (current < 100) {
// current 用来计算当前柱状的高度占最终高度的百分之几,通过不断循环实现柱状上升的动画
current = current + 3 > 100 ? 100 : current + 3
drawAnimation()
} else {
window.cancelAnimationFrame(looped)
looped = null
}
}
function drawAnimation() {
for (let i = 0; i < data.length; i++) {
var x = Math.ceil(((data[i].value * current) / 100) * yRatio)
var y = height - padding - x
ctx.fillRect(padding + xLength * (i + 0.2), y, xLength / 2, x)
// 保存每个柱状的信息
data[i].left = padding + xLength / 4 + xLength * i
data[i].top = y
data[i].right = padding + (3 * xLength) / 4 + xLength * i
data[i].bottom = height - padding
}
}
// 实现canva 的缩放
box.onmousedown = e => {
e.stopPropagation()
flag = true
let boxWidth = width,
boxHeight = height,
xClick = e.pageX,
yClick = e.pageY
window.onmousemove = event => {
if (flag) {
let eX = event.pageX,
eY = event.pageY,
absX = (eX - xClick) / boxWidth,
absY = (eY - yClick) / boxHeight
canvas.width = (1 + absX) * boxWidth
canvas.height = (1 + absY) * boxHeight
resize()
}
}
}
window.onmouseup = () => {
flag = false
moveFlag = false
}
centerBox.onmousedown = e => {
moveFlag = true
}
centerBox.onmouseup = e => {
moveFlag = false
}
totalBox.onmousedown = e => {
let boxTop = e.pageX - totalBox.offsetLeft,
boxLeft = e.pageY - totalBox.offsetTop
window.onmousemove = event => {
if (moveFlag) {
let eX = event.pageX - boxTop,
eY = event.pageY - boxLeft
totalBox.style.top = eY + 'px'
totalBox.style.left = eX + 'px'
}
}
}
</script>
</body>
</html>