light-chart
Version:
Charts for mobile visualization.
324 lines (285 loc) • 8.48 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<title>折线图</title>
<link rel="stylesheet" href="./assets/common.css">
<style>
#mountNode {
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<div>
<canvas id="mountNode"></canvas>
<div>
<button id='one'>近 1 月</button>
<button id='three'>近 3 月</button>
<button id='six'>近 6 月</button>
<button id='oneYear'>近 1 年</button>
<!-- <button id='threeYear'>近 3 年</button> -->
</div>
</div>
<script src="./assets/jquery-3.2.1.min.js"></script>
<script src="../build/f2-all.js"></script>
<script>
const G = F2.G;
const Util = F2.Util;
let data;
let oneMonth;
let threeMonth;
let sixMonth;
let oneYear;
let chart;
let lastData;
let isForward = false; // 判断下时序
$('#one').click(e => {
const one = data.slice(oneMonth);
isForward = (one.length > lastData.length);
lastData = one;
chart.scale('reportDateTimestamp', {
type: 'timeCat',
mask: 'MM-DD'
});
chart.changeData(one);
});
$('#three').click(e => {
const three = data.slice(threeMonth);
isForward = (three.length > lastData.length);
lastData = three;
chart.scale('reportDateTimestamp', {
type: 'timeCat',
mask: 'YYYY-MM'
});
chart.changeData(three);
});
$('#six').click(e => {
const six = data.slice(sixMonth);
isForward = (six.length > lastData.length);
lastData = six;
chart.scale('reportDateTimestamp', {
type: 'timeCat',
mask: 'YYYY-MM'
});
chart.changeData(six);
});
$('#oneYear').click(e => {
const year = data.slice(oneYear);
isForward = (year.length > lastData.length);
lastData = year;
chart.scale('reportDateTimestamp', {
type: 'timeCat',
mask: 'YYYY-MM'
});
chart.changeData(year);
});
let zeroY;
F2.Animate.registerAnimation('lineUpdate', function(updateShape, animateCfg, coord) {
const cacheShape = updateShape.get('cacheShape'); // 该动画 shape 的前一个状态
const cacheAttrs = cacheShape.attrs; // 上一个 shape 属性
const geomType = cacheShape.geomType; // 图形类型
const oldPoints = cacheAttrs.points; // 上一个状态的关键点
const newPoints = updateShape.attr('points'); // 当前 shape 的关键点
const oldLength = oldPoints.length;
const newLength = newPoints.length;
let deltaLength = (geomType === 'area') ? (oldLength - newLength) / 2 : (oldLength - newLength);
// 对比前后状态进行补点
if (deltaLength > 0 ) {
const firstPoint = newPoints[0];
const lastPoint = newPoints[newPoints.length - 1];
for (let i =0; i< deltaLength; i++) {
newPoints.splice(0, 0, firstPoint);
}
if (geomType === 'area') { // 对于区域图,关键点还包含底边,点的个数同顶边相同,所以上面会除以一半,绘制顺序是先绘制顶边再绘制底边,按照顺时针
for (let i = 0; i< deltaLength; i++) {
newPoints.push(lastPoint);
}
}
} else {
deltaLength = Math.abs(deltaLength);
const firstPoint = oldPoints[0];
const lastPoint = oldPoints[oldPoints.length - 1];
for (let i =0; i< deltaLength; i++) {
oldPoints.splice(0, 0, firstPoint);
}
if (geomType === 'area') {
for (let i =0; i< deltaLength; i++) {
oldPoints.push(lastPoint);
}
}
cacheAttrs.points = oldPoints;
}
updateShape.attr(cacheAttrs);
updateShape.animate().to({
attrs: {
points: newPoints
},
duration: 800,
easing: animateCfg.easing
});
});
$.getJSON('./data/3nian.json', json => {
const source = [];
let i = 0;
json.map(obj => {
i++;
if (obj.reportDate === "2018-01-02") {
oneMonth = i;
} else if (obj.reportDate === "2017-11-01") {
threeMonth = i;
} else if (obj.reportDate === "2017-08-01") {
sixMonth = i;
} else if (obj.reportDate === "2017-01-03") {
oneYear = i;
}
// obj.value = obj.value * 1;
source.push(obj);
});
data = source;
let t = performance.now();
chart = new F2.Chart({
id: 'mountNode',
width: 375,
height: 200,
pixelRatio: window.devicePixelRatio,
padding: [ 'auto', 40 ]
});
lastData = data.slice(oneMonth);
chart.source(data.slice(oneMonth), {
reportDateTimestamp: {
type: 'timeCat',
mask: 'MM-DD'
},
rate: {
formatter: rate => `${(rate * 100).toFixed(1)}%`,
tickCount: 5
}
});
chart.animate({
line: false,
area: {
update: false
},
'axis-label': {
enter: {
animation: function(shape, animateCfg, coord) {
if (!zeroY) {
zeroY = chart.getPosition({
reportDateTimestamp: '2018-01-18',
rate: 0
}).y;
if (zeroY > coord.y.start) {
zeroY = coord.y.start;
}
if (zeroY < coord.y.end) {
zeroY = coord.y.end
}
}
const id = shape._id;
if (id.indexOf('axis-y0') > -1) {
const actualY = shape.attr('y');
const startY = coord.y.start;
const endY = coord.y.end;
shape.attr('fillOpacity', 0.1);
// if (actualY > zeroY) {
shape.attr('y', zeroY)
shape.animate().to({
attrs: {
y: actualY,
fillOpacity: 1
},
duration: 800,
easing: animateCfg.easing
})
// } else {
// }
} else if (id.indexOf('axis-x') > -1) {
if (isForward) {
const startX = coord.x.start - 10;
const actualX = shape.attr('x');
shape.attr('x', startX);
shape.attr('fillOpacity', 0.1);
shape.animate().to({
attrs: {
x: actualX,
fillOpacity: 1
},
duration: 800,
easing: animateCfg.easing
});
} else {
const startX = coord.x.end + 10;
const actualX = shape.attr('x');
shape.attr('x', startX);
shape.attr('fillOpacity', 0.1);
shape.animate().to({
attrs: {
x: actualX,
fillOpacity: 1
},
duration: 800,
easing: animateCfg.easing
});
}
}
},
},
update: {
animation: function(shape, animateCfg, coord) {
const id = shape._id;
const cacheShape = shape.get('cacheShape'); // 该动画 shape 的前一个状态
const cacheAttrs = cacheShape.attrs;
const actualX = shape.attr('x');
const actualY = shape.attr('y');
if (id.indexOf('axis-y0') > -1) {
shape.attr('y', cacheAttrs.y);
shape.animate().to({
attrs: {
y: actualY
},
duration: 800,
easing: animateCfg.easing
})
} else if (id.indexOf('axis-x') > -1) {
shape.attr('x', cacheAttrs.x);
shape.animate().to({
attrs: {
x: actualX
},
duration: 800,
easing: animateCfg.easing
})
}
}
},
// leave() {
// return function(shape, animateCfg, coord) {
// shape.animate().to({
// attrs: {
// fillOpacity: 0
// },
// duration: 200,
// easing: animateCfg.easing
// }).onEnd(() => {
// shape.destroy();
// });
// }
// }
}
});
chart.legend({
showTitle: true
});
chart.line({
sortable: false
}).position('reportDateTimestamp*rate');
chart.area({
sortable: false
}).position('reportDateTimestamp*rate');
chart.render();
});
</script>
</body>
</html>