一、D3能做什么?

  • D3主要应用于2D场景 svg不生效
  • D3.js 是一个使用动态图形进行数据可视化的JavaScript程序库

    二、D3特点

    一款基于JavaScript的函数;借助HTML、SVG和CSS等实现可视化;组件强大,通过数据驱动的方式来操作DOM;
    svg和Canvas对比:

  • SVG:可缩放矢量图形,用于绘制可视化的图形

  • SVG 是使用 XML 来描述二维图形和绘图程序的语言。
  • Canvas 绘制的图像 都在Canvas这个画布里面,是Canvas的一部分,不能用js获取已经绘制好的图形元素。

    三、选择元素与绑定数据

    1.直接操作dom-d3选中元素和jQuery很像


    d3主要通过select , selectAll实现选择元素,参照原生js的querySelector querySelectorAll;
    d3是支持连缀操作的,当你选中元素后可以直接去更改它们; ``` const dataset = [12, 31, 22]; d3.select(‘body’).data(dataset).enter().append(‘h2’).text(‘New Title’) // data()方法接收数组作为参数,并运行三次后面的代码,每次对应数组中的一个对象。 d3.select(‘body’).selectAll(‘h2’).data(dataset).enter().append(‘h2’).text(‘New Title’) // select()这个标签元素,可用链式向标签里添加html节点append(),在往节点添加文本text() d3.select(‘p’).style(‘background’, ‘yellow’) d3.selectAll(‘p’).style(‘background’, ‘yellow’) // 不需要遍历,直接对整体进行操作
  1. <a name="w6XUB"></a>
  2. #### 2.当我们需要在当前[dom](https://so.csdn.net/so/search?q=dom&spm=1001.2101.3001.7020)中append一个子元素时,append返回的不是当前dom,而是子元素

d3.select(‘p’).append(‘span’).text(‘I am in span’) //文本添加在span复制代码

  1. <a name="JuRam"></a>
  2. #### 3.insert(newElement, targetElement) 返回插入的元素

p1

target

p2

// 讲新的p插到target前面 d3.select(‘body’).insert(‘p’, ‘#target’).text(‘I am new here’).style(‘color’, ‘pink’)

  1. <a name="E4zhP"></a>
  2. #### 4.remove删除元素

d3.select(‘body’).select(‘#target’).remove() //先选中然后直接remove

  1. <a name="lPKng"></a>
  2. #### 5.一些常用的修改dom样式,属性和内容的api
  3. attr,style,text 看名字其实就知道,attr常用来修改svg节点的属性, 这用attr做个案例
  1. d3.selectAll('p').text((d, i) => {
  2. if (i === 2) {
  3. d3.select(this).attr('class', 'new') //this为html
  4. } return d
  5. })
  1. <a name="vybgc"></a>
  2. #### 6.选中的dom和数据一一绑定

let dataset = [‘javascript’, ‘css’, ‘html’] d3.select(‘#list’).selectAll(‘li’).data(dataset).text((d, i) => i + ‘ : ‘ + d)

  1. <a name="VGq5s"></a>
  2. ## 四、svg属性
  3. 在线编辑网址: [https://www.nhooo.com/run/138120.html](https://www.nhooo.com/run/138120.html)
  4. <a name="zhhuV"></a>
  5. ### 1.svg坐标
  6. SVG 坐标空间的 x = 0,y = 0 坐标位于左上角。<br />SVG 坐标空间的 Y 坐标从上到下增长。
  7. <a name="Hs82P"></a>
  8. ### 2.svg的transform属性:
  9. transform的种类translate(平移)、skew(倾斜)、rotate(旋转)、scale(缩放)
  10. <a name="SyE9O"></a>
  11. ### 3.svg形状

// 折线

// 文本

I love SVG // 线条

// 矩形

// 圆形

// 椭圆

  1. <a name="uTydK"></a>
  2. #### 4.svg事件
  3. 鼠标事件
  4. - click:鼠标单机某元素(mousedown+mouseup)
  5. - mouseover:光标放在某元素上
  6. - mouseout:光标从某元素上移出来
  7. - mousemove:鼠标被移动
  8. - mousedown:鼠标被按下
  9. - mouseup:鼠标按钮被松开
  10. - 双击:没有 click+延迟判定来模拟(还不会)
  11. 键盘事件
  12. - keydown:按下任意键触发
  13. - keypress:按下字符键触发
  14. - keyup:释放键触发
  15. 触屏
  16. - touchstart:触摸点放在触摸屏上时
  17. - touchmove:触摸点移动
  18. - touchend:触摸点拿开
  19. svg其他属性,详见:[https://www.w3school.com.cn/svg/svg_rect.asp](https://www.w3school.com.cn/svg/svg_rect.asp)
  20. <a name="PMQay"></a>
  21. ## 五、实现思路
  22. - svg是操作dom元素, 在生命周期mounted/created里面操作dom,通过jquery操作dom的方式,给元素添加属性,用svg显示形状,在svg区域中创建图形。
  23. - svg 支持多种图形,比如矩形和圆形,并用它们来显示数据。例如,在条形图中一个矩形(rect )svg 图形可以创建一个组。
  24. - svg 的rect有四个属性。x和y坐标指定图形放在svg区域的位置,height和width指定图形大小。
  25. - rect元素和div有一些不同,rect必须添加在svg元素内,而不能直接添加在body内。同时,你需要告诉 D3 将rect放在svg区域的哪个位置。

// 添加中心区域背景底色 g.append(“rect”) .attr(“x”, -8) .attr(“y”, -5) .attr(‘width’, 155) .attr(‘height’, 137) .attr(“fill”, ‘rgba(32, 64, 132, 0.3)’) // 添加文字 g.append(“text”) .attr(“x”, 0) .attr(“y”,122) .attr(“font-size”, 14) .attr(“fill”, ‘#E0FFF9’) .text(function(data) { return data.center; });

  1. <a name="szxCK"></a>
  2. ## 六、svg项目使用
  3. <a name="V5asX"></a>
  4. #### 1. 安装命令

npm install d3 —save-dev

  1. <a name="hIoiS"></a>
  2. #### 2.项目引入D3

import * as d3 from ‘d3’ |

  1. <a name="DpGTR"></a>
  2. #### 3.绘制矩形方阵, 按照标准分辨率1440*900的尺寸,设置设置svg的宽高

let width = 1300, height = 780, gwWidth = 40, gwHeight = 40, clientWidth = document.documentElement.clientWidth, clientHeight = document.documentElement.clientHeight, widthScale = ((clientWidth - width) / 2), heightScale = ((clientHeight - height) / 2), div = d3.select(‘#chart’), svg = div.append(‘svg’) .attr(“id”,”mainSvg”) .attr(‘width’, clientWidth) .attr(‘height’, clientHeight)

  1. <a name="rcio7"></a>
  2. #### 4. 基于中心缩放方法

function zoomed() { let _t = d3.event.transform gbody.attr(‘transform’, ‘translate(‘+ (widthScale + _t.x) +’, ‘+ (heightScale + _t.y) +’) scale(‘+_t.k+’)’) localStorage.setItem(“key”, $(‘#mainSvg’).find(‘g’).attr(‘transform’))}

  1. <a name="olaCe"></a>
  2. #### 5.将一个'g'元素添加到SVG.g元素用于将SVG形状组合在一起 transform将svg标签放到页面中间

let gbody = svg.append(‘g’).data([gwData.availableZone])

  1. <a name="W11X7"></a>
  2. #### 6.svg的data只接受数组的数据

.attr(‘transform’, this.lastPosition || ‘translate(‘+ widthScale +’, ‘+ heightScale +’) scale(1)’)

  1. <a name="jIxbg"></a>
  2. #### 7.绘制线条

// 绘制线条-集群之间的调用情况 function drawLine(drawData){ for(var x = 0; x < drawData.length; x++){ let _item = drawData[x]; let dx = 0, x1=_item.x1,y1=_item.y1,x2=_item.x2,y2=_item.y2; let dy = Math.round(Math.abs( ( ( y2 - y1 ) / ( x2 - x1 ) ) * dx )); // 绝对值随机数 //向右上弯曲 let cpx = Math.round(( x1 + x2 ) / 2 + dx); let cpy = Math.round(( x1 + x2 ) / 2 - dy); var path = d3.path(); path.moveTo(x1,y1); path.quadraticCurveTo(cpx,cpy,x2,y2); drawData[x].path = path.toString(); } drawData.forEach(item => { let _item = item; gbody.append(‘path’) // 添加路径 .attr(‘d’, item.path) .attr(‘JSON’,JSON.stringify(item)) .attr(‘fill’,’none’) .attr(‘stroke-opacity’,’0.5’) // 透明度 .attr(‘stroke’, getStrokeState(_item.state)) .attr(‘marker-start’,’’) // 开始箭头 .attr(‘marker-end’,’url(#markerArrow)’) // 结束箭头 .on(“click”, lineClick) // click事件绑定 - 集群关系线条 }) }

// 根据数据绘制中心的数据 gbody.selectAll(‘g.centers’) .data(gwData.centers) //实例相关信息 将借口返回的数据渲染到页面上 .enter() .append(‘g’) .attr(‘transform’, function(d, i) { return’translate(‘+ 166 (i % 8)+’,’+ 148 (parseInt(i/8)+1)+’)’; }) // 一排八个 .attr(“key”, function(d,i){ return d.center }) .each(function(d, i) { drawCenter(d3.select(this), d, i); }); //调取方法 循环数组渲染

  1. ```
  2. function drawCenter(g, data, index) {
  3. // 添加文字
  4. g.append("text")
  5. .attr("x", 0)
  6. .attr("y",122)
  7. .attr("font-size", 14)
  8. .text(function(data) {
  9. return data.center;
  10. });
  11. // 绘制图片
  12. g.selectAll('image')
  13. .data(function(data) {
  14. return data.clusters;
  15. })
  16. .enter()
  17. .append('image')
  18. .attr('xlink:href', function(d, i) {
  19. return getClustersState(d.state);
  20. })
  21. .attr('x', function(d, i) {
  22. return24 * (i % 6); // 取余
  23. })
  24. .attr('y', function(d, i){
  25. return24 * (parseInt(i/6)); // 取整
  26. })
  27. .attr("state", function(d,i){
  28. return d.state // 记录集群状态值
  29. })
  30. .attr("key", function(d){
  31. let _cx = ((this.x.baseVal.value +
  32. this.parentNode.transform.animVal[0].matrix.e) + 6),
  33. _cy = ((this.y.baseVal.value +
  34. this.parentNode.transform.animVal[0].matrix.f) + 10);
  35. allNodes.push({
  36. type:'center',
  37. key:d.cluster,
  38. cx: _cx,
  39. cy: _cy,
  40. })
  41. return d.cluster
  42. })
  43. .attr("cx", function(d,i){
  44. return ((this.x.baseVal.value +
  45. this.parentNode.transform.animVal[0].matrix.e) + 9) // 计算元素x轴位置信息
  46. })
  47. .attr("cy", function(d,i){
  48. return ((this.y.baseVal.value +
  49. this.parentNode.transform.animVal[0].matrix.f) + 6)// 计算元素y轴位置信息
  50. })
  51. .attr('width', 18)
  52. .attr('height', 18)
  53. .on("click", clustersClick) // 点击事件绑定 - 网关
  54. .on("mouseover", clustersMouseover) // mouseover事件绑定 - 网关
  55. .on("mouseout",clustersMouseout) // mouseout事件绑定 - 网关
  56. }

在线项目地址:http://10.70.62.75:8081/dist/index.html#/alpha