用 G2 绘制一个动态爱心效果
某天看到公众号的推送文章《用 Python 制作一个动态爱心效果》,感觉挺有意思,所以想用 G2 5.0 可视化的思维方式去实现一下。
这个图使用可视化的思维去实现的话,大概的逻辑是:
- 找到一个心形函数,可以生成这个图形
- 基于这个函数,随机产生 5000 个点,这样的话,这些点就可以拼凑出心形的形状
- 在具体坐标点绘制的时候,可以加一个随机函数,讲点随机散开
直接贴代码:
import { Chart } from '@antv/g2';
import { randomExponential } from 'd3-random'
const random = randomExponential(5, [0, 1]);
const direction = () => Math.random() > 0.5 ? 1 : -1
const chart = new Chart({
container: 'container',
autoFit: true,
});
const SAMPLE = 5000;
const HEART_COLOR = "#ff2121" // 心的颜色,这个是中国红
const JITTER_RATIO = 0.2;
function point(angle) {
const a = 6;
const x = a * (16 * Math.sin(angle) ** 3);
const y =
a *
(13 * Math.cos(angle) -
5 * Math.cos(2 * angle) -
2 * Math.cos(3 * angle) -
Math.cos(4 * angle));
return { x, y };
}
function getHeartPoints() {
return new Array(SAMPLE).fill(0).map(() => point(Math.random() * 2 * Math.PI))
}
chart
.point()
.data(getHeartPoints())
.encode('x', 'x')
.encode('y', 'y')
.encode('shape', 'point')
.encode('color', HEART_COLOR)
.encode('size', 1)
.transform({ type: Jitter })
.axis(false);
chart.render();
function Jitter() {
return (I, mark) => {
const { encode } = mark;
const { x, y } = encode;
const X = x.value;
const Y = y.value;
X.forEach((v, idx) => {
X[idx] = v += (v * random() * JITTER_RATIO * direction())
});
Y.forEach((v, idx) => {
Y[idx] = v += (v * random() * JITTER_RATIO * direction())
});
return [I, mark];
};
}
- 这里面
getHeartPoints
就是心形函数,随机生成数据 - 然后最后加了一个 Jitter 函数,为了让数据散开的时候,散开越远的点越少,所以使用了 exp 的 random 函数。
最后的效果如下,也可以把上面的代码贴到 G2 官网示例 中调参获得更好的效果。
总结
G2 可视化的思维方式,其实很简单,就是使用数据去驱动图形的属性,然后在渲染之前需要额外做一下调整(比如随机)就使用 transform。
再次感谢文章《用 Python 制作一个动态爱心效果》提供的思路。
转载自:https://juejin.cn/post/7176069612897828923