写码,看书,思考,这周挺多感触的。
因为手上的项目前端用了Angular,所以UI改版的时候考虑了Angular-material,学校的项目前端用了React,所以也想接入ant-design mobile的那套设计规范,这两个都是业界非常不错的UI库,看他们的文档都会让你觉得能使手上的web应用瞬间高大上起来。
其实不然,即便是开源,也不是拿来就用那么美好,那晚尝试接入ant-design的轮播组件,出现下一张图片的一部分盖在上一张图片上情况,而官方文档写得极少,于是去看源码,发现了一些bug,自己用一些比较hack的方法纠正后发现组件体积大概有30k(压缩后),于是自己实现了一个light-swiper,未压缩只有4k,兼容性够用。
这件事让我清醒了一些,过去自己喜欢并且推崇的那些库,其实自己并没有深入地去了解别人的实现,万一某天这些通用性的库不能满足你的个性化需求,你该何去何从。
工具固然重要,可只有不依赖工具,工具才是真正为你所用。
不多说了,下面简单说说怎么用D3.js画一个趋势缩略图,先上效果图(截于Google Trend):
对SVG比较熟的老司机肯定一眼看穿这个图是怎么组成的:
就是两个SVG的path(不了解的可以先了解一下),第一个用于绘制折线,第二个用于绘制区域。一开始我想一个path用于绘制区域就能达到这种效果了吧,后来效果不佳,还是采取了Google的实践,后面会提到。
标题还提到了D3.js,简单介绍一下。
D3.js是一个用于数据可视化的js库,以数据驱动的方式去操作SVG,或原生的DOM,数据驱动的方式很有意思,下面看代码会有感触。
很简单的一个东西,直接放码过来好了:
<html>
<head>
<script src="https://d3js.org/d3.v4.min.js">script>
head>
<body>
<svg width="100" height="32">svg>
<script>
var data = [100,321,50,100,80];
var svg_height = 32;
var svg_width = 100;
var d = svg_width / data.length;
//比例尺
var scale = d3.scaleLinear().domain([0, d3.max(data)]).range([0, svg_height]);
//折线生成函数
var line_generator = function(x,i) {
var offset = -1;
var line_data = data.map( function(y) {
offset ++;
return { y: svg_height - scale(y), x: offset * d };
} );
var lineFunction = d3.line().x(function(d){return d.x;}).y(function(d){return d.y;});
return lineFunction(line_data);
};
//区域生成函数
var area_generator = function(x,i) {
var offset = -1;
var area_data = data.map( function(y) {
offset ++;
return [offset * d, svg_height - scale(y)];
} );
var area = d3.area().y0(svg_height);
return area(area_data);
};
setTimeout( function() {
// line
d3.select('svg')
.data(data) //数据驱动:根据data的长度去生成对应的path
.append('path')
.attr('stroke', 'rgb(66, 132, 243)')
.attr('stroke-width', 2)
.attr('fill', 'none')
.attr('d', line_generator);
// area
d3.select('svg')
.data(data)
.append('path')
.attr('stroke', 'none')
.attr('fill', 'rgba(66, 132, 243, 0.2)')
.attr('d', area_generator);
}, 300 );
script>
body>
html>
只用区域实现的效果:
对边界进行调整后:
第二个图因为做了调整,随意后面的比例有所变化,在产品中还是采取折线加区域的实现方式。下面是只用区域的代码。
<html>
<head>
<script src="https://d3js.org/d3.v4.min.js">script>
head>
<body>
<svg width="100" height="32">svg>
<script>
var data = [100,321,50,100,80];
var svg_height = 32;
var svg_width = 100;
var d = svg_width / data.length;
//比例尺
var scale = d3.scaleLinear().domain([0, d3.max(data)]).range([0, svg_height]);
//区域生成函数
var area_generator = function(x,i) {
var offset = -1;
var area_data = data.map( function(y) {
offset ++;
//去除左右stroke
if( offset == 0 ) return [-5, svg_height - scale(y)];
if( offset == data.length - 1 ) return [offset * d + 30, svg_height - scale(y)];
return [offset * d, svg_height - scale(y)];
} );
//去除下stroke
var area = d3.area().y0(svg_height+10);
return area(area_data);
};
setTimeout( function() {
// area
d3.select('svg')
.data(data)
.append('path')
.attr('stroke', 'rgb(66, 132, 243)')
.attr('fill', 'rgba(66, 132, 243, 0.2)')
.attr('d', area_generator);
}, 300 );
script>
body>
html>
趋势图的实现比较简单,用D3.js有点杀鸡用牛刀的感觉,而且要引入D3.js(76.8k大小),不过D3.js确实好玩:
站点24小时PV图: