d3.v4.js数据可视化力导向图 force 产业链

it2022-05-09  38

PC和APP(手机网页版均可)静态图(我录好的视频不能上传) d3.v4 中文API文档地址https://github.com/xswei/d3js_doc/blob/master/API_Reference/API.md d3.js 力导向图中默认提供了 5 种作用力:

中心力(Centering) 中心力作用于所有的节点而不是某些单独节点,可以将所有的节点的中心一致的向指定的位置移动,而且这种移动不会修改速度也不会影响节点间的相对位置。 碰撞力(Collision) 碰撞力将每个节点视为一个具有一定半径的圆,这个力会阻止代表节点的这个圆相互重叠,即两个节点间会相互碰撞,可以通过设置 strength 设置这个碰撞力的强度。 弹簧力(Links) 当两个节点通过设置 link 连接到一起后,可以设置弹簧力,这个力将根据两个节点间的距离将两个节点拉近或推远,力的强度和这个距离成比例就和弹簧一样。 电荷力(Many-Body) 通过设置 strength 来模拟所有节点间的相互作用力,如果为正节点间就会相互吸引,可以用来模拟电荷吸引力,如果为负节点间就会相互排斥。这个力的大小也和节点间的距离有关。 定位力(Positioning) 这个力可以将节点沿着指定的维度推向一个指定位置,比如通过设置 forceX 和 forceY 就可以在 X轴 和 Y轴 方向推或者拉所有的节点,forceRadial 则可以形成一个圆环把所有的节点都往这个圆环上相应的位置推。

部分代码

var simulation = d3.forceSimulation() .alpha(1.5) .alphaMin(0.001) .alphaDecay(0.0228) .alphaTarget(0) .force("link", d3.forceLink() .links(links) .id(function (d) { return d.index; }) ) .force("charge", d3.forceManyBody().strength(stren)) .force("collide", d3.forceCollide(function (d) { var v = 0 if (grade(d.type) === 1) { v = bigW - 60 } else if (d.is_back === 0 || d.is_back === 1) { v = 20 } else if (grade(d.type) === 2) { v = cv + 20 } else if (grade(d.type) === 3) { v = cv } return v }) .strength(0.2) .iterations(5)) .nodes(nodes) .on('tick', tick) if (!isPc) { simulation.force("center", d3.forceCenter(width / divW, height / divH)) } var zooms = d3.zoom() .scaleExtent([0.5, 1.5]) .on("zoom", zoomed); function zoomed () { svg.selectAll(".svg_g").attr("transform",d3.event.transform) if (!isforbid) { var x = d3.event.transform.x var y = d3.event.transform.y var s = d3.event.transform.k if (s === scaled ) { if (x - sumX > 10) { animation(img_name_l, 1.3) animation(img_name_r, 1) } else if (x - sumX < -10) { animation(img_name_r, 1.3) animation(img_name_l, 1) } else if (y - sumY > 10 && Math.abs(x - sumX) < 10) { animation(img_name_t, 1.3) animation(img_name_b, 1) } else if (y - sumY < -10 && Math.abs(x - sumX) < 10) { animation(img_name_b, 1.3) animation(img_name_t, 1) } } scaled = s sumX = x sumY = y } } function animation (className, sl) { var u = navigator.userAgent var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) if (isiOS) { if ($('.' + className).length > 0) { $('.' + className).animate({'transform': 'scale(' + sl + ')', 'transform-origin': 'center center'},250) } } else { d3.selectAll('.' + className) .transition().duration(250) .attr('transform', 'scale(' + sl + ')') .attr('transform-origin', 'center center') } } var drags = d3.drag() .on('start', function (d) { d3.event.sourceEvent.stopPropagation() if (!d3.event.active) simulation.alphaTarget(0.3).restart() d.fx = d.x d.fy = d.y }) .on('drag', function (d) { d.fx = d3.event.x d.fy = d3.event.y var tag = d3.event.sourceEvent.srcElement.tagName if (tag != 'image' && tag != 'text' && tag != 'tspan' && tag != 'g' && tag != 'svg') { simulation.alphaTarget(0); d.fx = null d.fy = null return false } }) .on('end', function (d) { if (!d3.event.active) simulation.alphaTarget(0) d.fx = null d.fy = null })

设置fx和fy可以固定位置

手机网页版兼容很麻烦 监听横竖屏事件

window.addEventListener(evt, function() { if (vm.isiOS && (Math.abs(window.orientation) === 90)) { // 横屏 setTimeout(function () { vm.widths = $(document).width() vm.heights = $(document).height() }, 250) } else if (vm.isiOS && (Math.abs(window.orientation) === 0)) { // 竖屏 setTimeout(function () { vm.widths = $(document).width() vm.heights = $(document).height() }, 250) } })

横竖屏切换时,获取的width和height还是切换前的宽高,所以加了一个定时器

时间有限我先粗略的写吧,扣扣交流1979751899


最新回复(0)