先上效果图
项目需要做一个显示不同波形的示波器,所以研究了一下D3,代码放一下,便于自己温习,有需要的可以自行学习。(欢迎指正);项目环境为vue项目中在node环境下,使用d3实现
this.padding = {top: -10, right: 10, bottom: 120, left: 40};
//坐标data大致这个形式
this.data[0].gainVal = [{"x":0,"y":439},{"x":1,"y":17},{"x":2,"y":799},{"x":3,"y":751},{"x":4,"y":484},{"x":5,"y":587},{"x":6,"y":491},{"x":7,"y":82},{"x":8,"y":730},{"x":9,"y":668},{"x":10,"y":769},{"x":11,"y":316},{"x":12,"y":486},{"x":13,"y":750},{"x":14,"y":305},{"x":15,"y":804},{"x":16,"y":377},{"x":17,"y":824},{"x":18,"y":802},{"x":19,"y":219},{"x":20,"y":65},{"x":21,"y":157},{"x":22,"y":576},{"x":23,"y":310},{"x":24,"y":452},{"x":25,"y":765},{"x":26,"y":705},{"x":27,"y":597},{"x":28,"y":788},{"x":29,"y":248},{"x":30,"y":651},{"x":31,"y":314},{"x":32,"y":412},{"x":33,"y":390},{"x":34,"y":45},{"x":35,"y":245},{"x":36,"y":698},{"x":37,"y":672},{"x":38,"y":648},{"x":39,"y":86},{"x":40,"y":220},{"x":41,"y":825},{"x":42,"y":368},{"x":43,"y":301},{"x":44,"y":271},{"x":45,"y":395},{"x":46,"y":159},{"x":47,"y":756},{"x":48,"y":236},{"x":49,"y":733},{"x":50,"y":488},{"x":51,"y":168},{"x":52,"y":525},{"x":53,"y":782},{"x":54,"y":366},{"x":55,"y":219},{"x":56,"y":218},{"x":57,"y":746},{"x":58,"y":412},{"x":59,"y":770},{"x":60,"y":290},{"x":61,"y":466},{"x":62,"y":258},{"x":63,"y":275},{"x":64,"y":108},{"x":65,"y":186},{"x":66,"y":557},{"x":67,"y":516},{"x":68,"y":168},{"x":69,"y":71},{"x":70,"y":140},{"x":71,"y":673},{"x":72,"y":653},{"x":73,"y":414},{"x":74,"y":238},{"x":75,"y":193},{"x":76,"y":755},{"x":77,"y":535},{"x":78,"y":207},{"x":79,"y":13},{"x":80,"y":126},{"x":81,"y":340},{"x":82,"y":631},{"x":83,"y":123},{"x":84,"y":681},{"x":85,"y":170},{"x":86,"y":147},{"x":87,"y":224},{"x":88,"y":224},{"x":89,"y":273},{"x":90,"y":342},{"x":91,"y":153},{"x":92,"y":86},{"x":93,"y":266},{"x":94,"y":53},{"x":95,"y":714},{"x":96,"y":470},{"x":97,"y":338},{"x":98,"y":304},{"x":99,"y":498}]
toolPage.js?7fd9:146 [{"x":0,"y":792},{"x":1,"y":595},{"x":2,"y":523},{"x":3,"y":541},{"x":4,"y":189},{"x":5,"y":528},{"x":6,"y":780},{"x":7,"y":70},{"x":8,"y":281},{"x":9,"y":821},{"x":10,"y":667},{"x":11,"y":453},{"x":12,"y":654},{"x":13,"y":75},{"x":14,"y":113},{"x":15,"y":190},{"x":16,"y":708},{"x":17,"y":796},{"x":18,"y":809},{"x":19,"y":714},{"x":20,"y":85},{"x":21,"y":498},{"x":22,"y":392},{"x":23,"y":718},{"x":24,"y":327},{"x":25,"y":112},{"x":26,"y":615},{"x":27,"y":824},{"x":28,"y":268},{"x":29,"y":776},{"x":30,"y":404},{"x":31,"y":385},{"x":32,"y":25},{"x":33,"y":16},{"x":34,"y":344},{"x":35,"y":551},{"x":36,"y":342},{"x":37,"y":344},{"x":38,"y":464},{"x":39,"y":335},{"x":40,"y":286},{"x":41,"y":604},{"x":42,"y":634},{"x":43,"y":479},{"x":44,"y":159},{"x":45,"y":285},{"x":46,"y":46},{"x":47,"y":568},{"x":48,"y":769},{"x":49,"y":404},{"x":50,"y":24},{"x":51,"y":500},{"x":52,"y":388},{"x":53,"y":717},{"x":54,"y":532},{"x":55,"y":608},{"x":56,"y":759},{"x":57,"y":460},{"x":58,"y":762},{"x":59,"y":96},{"x":60,"y":721},{"x":61,"y":259},{"x":62,"y":698},{"x":63,"y":126},{"x":64,"y":732},{"x":65,"y":377},{"x":66,"y":435},{"x":67,"y":18},{"x":68,"y":73},{"x":69,"y":554},{"x":70,"y":53},{"x":71,"y":626},{"x":72,"y":494},{"x":73,"y":595},{"x":74,"y":595},{"x":75,"y":259},{"x":76,"y":787},{"x":77,"y":432},{"x":78,"y":674},{"x":79,"y":168},{"x":80,"y":384},{"x":81,"y":232},{"x":82,"y":367},{"x":83,"y":626},{"x":84,"y":672},{"x":85,"y":790},{"x":86,"y":59},{"x":87,"y":604},{"x":88,"y":42},{"x":89,"y":692},{"x":90,"y":397},{"x":91,"y":712},{"x":92,"y":726},{"x":93,"y":825},{"x":94,"y":7},{"x":95,"y":846},{"x":96,"y":100},{"x":97,"y":509},{"x":98,"y":134},{"x":99,"y":434}]
这句是用于做位置偏移的data数据对象。
<div id="oscillogram></div>
在上面这个盒子里面画我们的坐标轴以及曲线
D3画出的原理就是svg,图形中是由点和线段构成。首先我们添加一个svg
let svg = d3.select('#oscillogram').append('svg').attr('width', width).attr('height', height).attr('stroke', '#fff')```
接下来我们需要设置横纵坐标的范围阈值等信息
let xScale = d3.scaleLinear().domain([0, 100]).range([0, 400]);
let yScale = d3.scaleLinear().domain([0, 900).range([900, 0]);
接下来我们分别分三个函数来画线,网格,坐标,以及数据点
//xScale 和yScale即为上文中所取,svg为添加的svg对象。width和height为你想要添加进去的盒子容器的宽高
this.drawLine(xScale, yScale, svg);
this.drawCircle(xScale, yScale, svg);
this.drawAxis(xScale, yScale, svg, height, width);
this.drawGrid(yScale, svg);
drawAxis(xScale, yScale, svg, height, width)
{
//这里是设置坐标轴的样式,包括刻度的方向,文字颜色,等。
let arr = [];
for(let i = 0; i*5 < ToolPage.instance()._data.time; i++)
{
arr.push(i*5);
}
let arry = [];
for(let i = 0; i * 50 < ToolPage.instance()._data.dataset[0].max; i++)
{
arry.push(i * 50);
}
let xAxis = svg.append('g')
.attr('class', 'xAxis')
.attr('transform', 'translate(' + ToolPage.instance()._data.padding.left + ', ' + (height - 10)+ ')')
.call(d3.axisTop(xScale).ticks(arr.length).tickSizeInner(0).tickValues(arr));
svg.select('.xAxis').select('path').attr('stroke','#fff');
let yAxis = svg.append('g')
.attr('class', 'yAxis')
.attr('transform', 'translate(' + ToolPage.instance()._data.padding.left + ', ' + ToolPage.instance()._data.padding.top + ')')
.style('font-size', '13')
.call(d3.axisLeft(yScale).ticks(arry.length).tickValues(arry).tickSize(0).tickFormat(d3.format("d")) );
svg.select('.yAxis').select('path').attr('stroke','#fff');
}
drawLine(xScale, yScale, svg)
{
//画曲线,并设置对应的样式
var linePath = d3.line().curve(d3.curveBasis).x(function (d)
{
return xScale(d.x);
}).y(function (d)
{
return yScale(d.y);
});
//我这里,将两条曲线的数组存到了dataset数组第一个元素的gainVal对象种,这个对象也是一个数组对象
svg.selectAll('path').data(this._data.dataset[0].gainVal).enter().append('path')
.attr('transform', 'translate(' +this._data.padding.left + ', ' + this._data.padding.top + ')')
.attr('d', function(d, i)
{
return linePath(d);
})
.attr('fill', 'none').attr('stroke', function (d, i)//加了这个函数循环,就可以给两条线做不同的样式了i=0则是第一条曲线,i=1就是第二条曲线,以此类推
{
let color;
if(i === 0)
{
color = "#fff";
}
else
{
color = "yellowgreen";
}
return color
}).attr('stroke-width', 1);
}
drawCircle(xScale, yScale, svg)
{
//画数据点并设置对应的样式
let circle = svg.selectAll('circle').data(ToolPage.instance()._data.dataset[0].gainVal).enter().append('circle')
.attr('transform', 'translate(' + ToolPage.instance()._data.padding.left + ', ' + ToolPage.instance()._data.padding.top + ')')
.attr('fill', 'black')
.attr('cx', function (d)
{
return xScale(d.x);
})
.attr('cy', function (d)
{
return yScale(d.y);
})
.attr('r', 2)//设置曲线的宽度。
.on('mouseover', function (d,i)//设置数据点的滑入滑出样式
{
console.log(d)
d3.select(this).attr('fill', '#797979');
})
.on('mouseout', function (d,i)
{
d3.select(this).transition().duration(300).attr('fill', 'black');
});
}
drawGrid(yScale, svg)
{
//这里是画对应y轴刻度引出的横线
let arry = [];
for(let i = 0; i * 50 < ToolPage.instance()._data.dataset[0].max; i++)
{
arry.push(i * 50);
}
let yInner = d3.axisLeft(yScale).ticks(arry.length).tickValues(arry).tickSize(-document.querySelector('#oscillogram').clientWidth - 20).tickFormat(d => '');
let yInnerBar = svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(40," + ToolPage.instance()._data.padding.top + ")")
.call(yInner);
svg.select('.grid').select('path').attr('stroke','none');
svg.select('.grid').selectAll('.tick').select('line').attr('stroke',function (d, i)
{
let color ;
if(d === this._data.vData)//这里可以单独拿出一个刻度来设置不同的样式。我这里将和我数据对应的刻度写成了黄绿色
{
color = "yellowgreen";
}
else
{
color = "#ccc";
}
return color;
}).attr('stroke-width', '0.6');
}
最后添加一个移除节点的事件接口,方便刷新的时候随时调取更新
removeSVGDom()
{
let lineItems = document.querySelector('#oscillogram');
let svgDom;
svgDom = lineItems.querySelector('svg');
if(svgDom !== null)
{
svgDom.remove();
}
}
核心代码如上,记录在CSDN主要为了便于自己记忆。如果有需要的朋友,欢迎参考。