仿天眼查-股权结构图
股权结构图 (vue2.0 + d3)
在pubic下的html文件中引入d3.js
<script src="https://cdn.bootcss.com/d3/3.2.7/d3.min.js"/>
准备好容器
<template><div id="borrow"><div id="mountNode"></div></div>
</template>
初始化数据
data() {return {companyName: '123',isFullscreen: true,rootData: {downward: {direction: 'down',name: 'origin',children: [{name: '公司名称',amount: '100',ratio: '55%',hasHumanholding: true,hasChildren: true,isExpand: false,type: 2,hasNode: 1,children: [{name: '公司名字',hasHumanholding: false,hasChildren: true,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2,children: []},{name: '公司名字',hasHumanholding: false,hasChildren: true,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2,children: []}]},{name: '公司名称11',amount: '100',isHoldingCompany: true,ratio: '55%',hasHumanholding: true,hasChildren: true,isExpand: false,type: 2,hasNode: 1,children: [{name: '公司名字',hasHumanholding: false,hasChildren: true,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2,children: []},{name: '公司名字',hasHumanholding: false,hasChildren: true,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2,children: []}]},{name: '公司名称',amount: '100',isHoldingCompany: true,ratio: '55%',hasHumanholding: true,hasChildren: true,isExpand: false,type: 2,hasNode: 1,children: [{name: '公司名字',hasHumanholding: false,hasChildren: true,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2,children: []},{name: '公司名字',hasHumanholding: false,hasChildren: true,amount: '100',ratio: '55%',type: 2,children: []}]},{name: '公司名称',hasHumanholding: false,hasChildren: true,amount: '100',ratio: '55%',type: 2,children: []},{name: '公司名称',hasHumanholding: false,hasChildren: true,isExpand: false,amount: '100',ratio: '55%',type: 2,hasNode: 1,children: [{name: '公司或股东名字',hasHumanholding: false,amount: '100',ratio: '55%',type: 2,children: []},{name: '公司或股东名字',hasHumanholding: false,amount: '100',ratio: '55%',type: 2,children: []},{name: '公司或股东名字',hasHumanholding: false,amount: '100',ratio: '55%',type: 2,children: []},{name: '公司或股东名字',hasHumanholding: false,amount: '100',ratio: '55%',type: 2,children: []}]}]},upward: {direction: 'up',name: 'origin',children: [{name: '...(有限合伙)',hasHumanholding: false,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2},{name: '...(有限合伙)',hasHumanholding: false,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2,hasNode: 1,children: [{name: '公司或股东名字',hasHumanholding: false,amount: '100',isHoldingCompany: true,ratio: '55%',type: 1,children: [],isFHolder: true,holderPercent: '5%'},{name: '公司或股东名字',hasHumanholding: false,isExpand: false,amount: '100',isHoldingCompany: true,ratio: '55%',type: 2,hasNode: 1,children: [{name: '公司或股东名字',hasHumanholding: false,amount: '100',isHoldingCompany: true,ratio: '55%',type: 1,isFHolder: true,isActualController: true,holderPercent: '95%',children: []},{name: '公司或股东名字',hasHumanholding: false,amount: '100',ratio: '55%',type: 2,children: []}]},{name: '公司或股东名字',hasHumanholding: false,amount: '100',ratio: '55%',type: 1,children: []}]}]}},rootName: '公司名称',beijingCrid: '98682337095519887'}},
获取节点
mounted() {this.getInitData()// this.drawing()window.addEventListener('resize', function() {const svg = document.getElementById('svg')svg.setAttribute('height', window.innerHeight)})},
方法
methods: {getInitData() {this.rootName = '123'this.drawing()console.log(this.rootData)},drawing() {const width = document.getElementById('mountNode').scrollWidthconst height = document.getElementById('mountNode').scrollHeight || 600const strokeColor = {isActualController: '#FBC6C3',isFHolder: '#F3DDB6',person: '#0084FF',default: '#CCC'}const lineColor = {isActualController: '#FA6B64',isFHolder: '#F1B03A',person: '#0084FF',default: '#919191'}const fillColor = {isActualController: '#FFFBFB',isFHolder: '#FEFBF3',person: '#F5FAFF',default: '#FFF'}var _this = this// var rootName = ''; //根节点的名字var rootRectWidth = 0 //根节点rect的宽度var downwardLength = 0,upwardLength = 0var forUpward = truevar treeChart = function(d3Object) {this.d3 = d3Objectthis.directions = ['upward', 'downward']}treeChart.prototype.drawChart = function() {// First get tree data for both directions.this.treeData = {}var self = thisself.directions.forEach(function(direction) {self.treeData[direction] = _this.rootData[direction]})// rootName = '上海冰鉴信息科技有限公司';rootRectWidth = _this.rootName.length * 15 + 60//获得upward第一级节点的个数upwardLength = _this.rootData.upward.children.length//获得downward第一级节点的个数downwardLength = _this.rootData.downward.children.lengthself.graphTree(self.getTreeConfig())}treeChart.prototype.getTreeConfig = function() {var treeConfig = {margin: {top: 10,right: 5,bottom: 0,left: 30}}treeConfig.chartWidth = width - treeConfig.margin.right - treeConfig.margin.lefttreeConfig.chartHeight = height - treeConfig.margin.top - treeConfig.margin.bottomtreeConfig.centralHeight = treeConfig.chartHeight / 2treeConfig.centralWidth = treeConfig.chartWidth / 2treeConfig.linkLength = 160treeConfig.duration = 500 //动画时间return treeConfig}treeChart.prototype.graphTree = function(config) {var self = thisvar d3 = this.d3var linkLength = config.linkLengthvar duration = config.durationvar hasChildNodeArr = []var id = 0var diagonal = function(obj) {//折线var s = obj.sourcevar t = obj.targetlet multiplier = s.x > t.x ? -1 : s.x < t.x ? 1 : 0let path = s.y > t.y ? s.y / 3 + (t.y * 2) / 3 : s.y / 3 + (t.y * 2) / 3 + 15return ('M' +s.x +',' +(s.y + 12) +'L' +s.x +',' +path +'L' +t.x +',' +path +// pathA+'L' +t.x +',' +t.y)}var zoom = d3.behavior.zoom().scaleExtent([0.5, 2]).on('zoom', redraw)var svg = d3.select('#mountNode').append('svg').attr('id', 'svg').attr('width', config.chartWidth + config.margin.right + config.margin.left).attr('height', config.chartHeight + config.margin.top + config.margin.bottom).attr('xmlns', 'http://www.w3.org/2000/svg').on('mousedown', disableRightClick).call(zoom).on('dblclick.zoom', null)var treeG = svg.append('g').attr('class', 'gbox').attr('transform', 'translate(' + config.margin.left + ',' + config.margin.top + ')')d3.select('#reset').on('click', function(d) {interpolateZoom([0, 0], 1)})function interpolateZoom(translate, scale) {var self = thisreturn d3.transition().duration(350).tween('zoom', function() {var iTranslate = d3.interpolate(zoom.translate(), translate),iScale = d3.interpolate(zoom.scale(), scale)return function(t) {zoom.scale(iScale(t)).translate(iTranslate(t))redraw()}})}function zoomClick() {var clicked = d3.event.target,direction = 1,factor = 0.2,target_zoom = 1,center = [width / 2, height / 2],extent = zoom.scaleExtent(),translate = zoom.translate(),translate0 = [],l = [],view = { x: translate[0], y: translate[1], k: zoom.scale() }d3.event.preventDefault()direction = this.id === 'zoomOut' ? 1 : -1target_zoom = Number(zoom.scale() + factor * direction).toFixed(1)if (target_zoom === extent[0] || target_zoom === extent[1]) {return false}if (target_zoom < extent[0]) {target_zoom = extent[0]}if (target_zoom > extent[1]) {target_zoom = extent[1]}translate0 = [(center[0] - view.x) / view.k, (center[1] - view.y) / view.k]view.k = target_zooml = [translate0[0] * view.k + view.x, translate0[1] * view.k + view.y]view.x += center[0] - l[0]view.y += center[1] - l[1]interpolateZoom([view.x, view.y], view.k)}d3.select('#zoomIn').on('click', zoomClick)d3.select('#zoomOut').on('click', zoomClick)for (var d in this.directions) {var direction = this.directions[d]var data = self.treeData[direction]data.x0 = config.centralWidthdata.y0 = config.centralHeightdata.children.forEach(collapse)update(data, data, treeG)}function update(source, originalData, g) {var direction = originalData['direction']forUpward = direction == 'up'var node_class = direction + 'Node'var link_class = direction + 'Link'var downwardSign = forUpward ? -1 : 1var nodeColor = forUpward ? '#37592b' : '#8b4513'var isExpand = falsevar statusUp = truevar statusDown = truevar nodeSpace = 210var tree = d3.layout.tree().sort(sortByDate).nodeSize([nodeSpace, 0])var nodes = tree.nodes(originalData)var links = tree.links(nodes)var offsetX = -config.centralWidthnodes.forEach(function(d) {d.y = downwardSign * (d.depth * linkLength) + config.centralHeightd.x = d.x - offsetXif (d.name == 'origin') {d.x = config.centralWidthd.y += downwardSign * 0 // 上下两树图根节点之间的距离}})var node = g.selectAll('g.' + node_class).data(nodes, function(d) {return d.id || (d.id = ++id)})var nodeEnter = node.enter().append('g').attr('class', node_class).attr('transform', function(d) {return 'translate(' + source.x0 + ',' + source.y0 + ')'}).style('cursor', function(d) {return d.name == 'origin' ? '' : d.children || d._children ? 'pointer' : ''}).on('click', d => {if (d.type == 2) {if ((d.direction == 'up' && d.beijingCrid) || (d.direction == 'down' && d.pbeijingCrid)) {_this.$router.push({path: '/search/detail',name: 'search-detail',query: {companyId: d.direction == 'up' ? d.beijingCrid : d.pbeijingCrid}})}}}).on('mouseover', d => {if (d.name === 'origin') {return false}let hoverLinkArr = [d.id]let sColor = strokeColor.defaultlet lColor = lineColor.defaultif (d.isActualController) {sColor = strokeColor.isActualControllerlColor = lineColor.isActualController} else if (d.isFHolder) {sColor = strokeColor.isFHolderlColor = lineColor.isFHolder} else {sColor = strokeColor.personlColor = lineColor.person}getRelationLink(d.id, lColor)d3.selectAll('marker#resolved' + d.id).selectAll('path').attr('fill', lColor)let linkif (d.direction == 'up') {link = d3.selectAll('.upLink')} else {link = d3.selectAll('.downLink')}link.sort(function(a, b) {if (a.target.id === d.id) {return 1} else {return -1}})rect.style('stroke-width', function(r) {if (r.id === d.id) {return '2'}}).style('stroke', function(r) {if (r.id === d.id) {if (r.type == 2) {return '#0084FF'} else {if (r.type == 1) {if (r.isActualController) {return '#FA6B64'} else if (r.isFHolder) {return '#F1B03A'} else {return '#0084FF'}} else {return '#CCC'}}} else {if (r.type == 1) {if (r.isActualController) {return '#FBC6C3'} else if (r.isFHolder) {return '#F3DDB6'} else {return '#83C6FF'}} else if (r.name === 'origin') {return '#0E78DB'} else {return '#CCC'}}})}).on('mouseout', d => {if (d.name === 'origin') {return false}d3.selectAll('marker#resolved' + d.id).selectAll('path').attr('fill', lineColor.default)link.style('stroke', function(l) {return '#919191'}).style('stroke-width', function(l) {return 1})rect.style('stroke-width', function(r) {if (r.id === d.id) {return '1'}}).style('stroke', function(r) {if (r.type == 1) {if (r.isActualController) {return '#FBC6C3'} else if (r.isFHolder) {return '#F3DDB6'} else {return '#83C6FF'}} else if (r.name === 'origin') {return '#0E78DB'} else {return '#CCC'}})})function getRelationLink(id, color) {if (id == 1) {return false}let sourceId = ''link.style('stroke', function(l) {if (id === l.target.id) {sourceId = l.source.idreturn color}}).style('stroke-width', function(l) {if (id === l.target.id) {return 2}})}const rect = nodeEnter.append('svg:rect').attr('x', function(d) {return d.name == 'origin' ? -(rootRectWidth / 2) : -100}).attr('y', function(d) {return d.name == 'origin' ? -20 : forUpward ? -52 : 12}).attr('width', function(d) {return d.name == 'origin' ? rootRectWidth : 200}).attr('height', function(d) {return d.name == 'origin' ? 40 : 80}).attr('rx', 0).style('cursor', 'pointer').style('stroke', function(d) {if (d.name == 'origin') {return '#0E78DB'} else if (d.type == 1) {if (d.isActualController) {return '#FBC6C3'} else if (d.isFHolder) {return '#F3DDB6'} else {return '#83C6FF'}} else {return '#CCC'}}).style('fill', function(d) {if (d.name == 'origin') {return '#0084FF'} else if (d.type == 1) {if (d.isActualController) {return '#FFFBFB'} else if (d.isFHolder) {return '#FEFBF3'} else {return '#F5FAFF'}} else {return '#fff'}})const personTopRect = nodeEnter.append('svg:rect').attr('x', function(d) {return -100}).attr('y', function(d) {return !d.isFHolder ? 0 : d.isActualController ? -102 : -82}).attr('width', function(d) {return d.isFHolder ? 200 : 0}).attr('height', function(d) {return !d.isFHolder ? 0 : d.isActualController ? 50 : 30}).attr('rx', 2).style('stroke', function(d) {return d.isActualController ? '#FA6B64' : '#F1B03A'}).style('fill', function(d) {return d.isActualController ? '#FA6B64' : '#F1B03A' //节点背景色})nodeEnter.append('svg:path').attr('fill', d => {return d.isActualController ? '#FA6B64' : '#F1B03A'}).attr('d', function(d) {if (d.isFHolder) {return 'M0 -44 L-10 -54 L10 -54 Z'} else {return ''}})const holdingCompanyRect = nodeEnter.append('svg:rect').attr('x', '-40').attr('y', function(d) {return d.name == 'origin' ? '.35em' : forUpward ? '31' : '-9'}).attr('rx', 2).attr('width', function(d) {return d.isHoldingCompany ? 30 : 0}).attr('height', function(d) {return d.isHoldingCompany ? 20 : 0}).style('fill', '#EBF5FF')nodeEnter.append('text').attr('x', '-35').attr('dy', function(d) {return d.name == 'origin' ? '.35em' : forUpward ? '45' : '5'}).attr('text-anchor', 'start').style('fill', '#0084FF').style('font-size', 10).text(function(d) {return d.isHoldingCompany ? '控股' : ''})nodeEnter.append('circle').attr('r', 1e-6)nodeEnter.append('text').attr('x', function(d) {return '0'}).attr('dy', function(d) {return d.name == 'origin' ? '.35em' : forUpward ? '-24' : '40'}).attr('text-anchor', function(d) {return 'middle'}).text(function(d) {if (d.name == 'origin') {return _this.rootName}if (d.repeated) {return '[Recurring] ' + d.name}return d.name.length > 12 ? d.name.substr(0, 12) : d.name}).style({fill: function(d) {if (d.name == 'origin') {return '#fff'} else {return '#333'}},'font-size': function(d) {return d.name == 'origin' ? 16 : 14},cursor: 'pointer'}).on('click', Change_modal).append('svg:title').text(d => d.name)nodeEnter.append('text').attr('x', '0').attr('dy', function(d) {return d.name == 'origin' ? '.35em' : forUpward ? '-5' : '59'}).attr('text-anchor', function() {return 'middle'}).attr('fill', '#333').text(function(d) {return d.name.length > 24 ? d.name.substr(12, 12) + '...' : d.name.substr(12, d.name.length)}).style({'font-size': function(d) {return d.name == 'origin' ? 16 : 14},cursor: 'pointer'}).append('svg:title').text(d => d.name)nodeEnter.append('text').attr('x', '0').attr('dy', function(d) {if (d.name === 'origin') {return '.35em'} else {if (forUpward) {if (d.name.length > 12) {return '16'} else {return '6'}} else {if (d.name.length > 12) {return '80'} else {return '70'}}}}).attr('text-anchor', 'middle').attr('class', 'linkname').style('fill', '#666').style('cursor', 'pointer').style('font-size', 12).text(function(d) {var str = d.name == 'origin' ? '' : '认缴金额:' + d.amount + '万人民币'return str.length > 18 ? str.substr(0, 18) + '..' : str})nodeEnter.append('text').attr('x', '10').attr('dy', function(d) {return d.name == 'origin' ? '.35em' : forUpward ? '45' : '5'}).attr('text-anchor', 'start').attr('class', 'linkname').style('fill', '#0084FF').style('font-size', 10).text(function(d) {return d.name == 'origin' ? '' : d.ratio})nodeEnter.append('text').attr('x', '0').attr('dy', function(d) {return d.isActualController ? -87 : -72}).attr('text-anchor', 'middle').style('fill', '#fff').style('font-size', 12).text(function(d) {return d.isActualController ? '疑似实际控制人' : ''})nodeEnter.append('text').attr('x', '0').attr('dy', function(d) {return d.isActualController ? -65 : -63}).attr('text-anchor', 'middle').style('fill', '#fff').style('font-size', 12).text(function(d) {return d.isFHolder ? '最终受益人:' + d.holderPercent : ''})var nodeUpdate = node.transition().duration(duration).attr('transform', function(d) {return 'translate(' + d.x + ',' + d.y + ')'})nodeUpdate.select('circle').attr('r', function(d) {return d.hasNode == 1 ? 10 : 0}).attr('cy', function(d) {return d.name == 'origin' ? -20 : forUpward ? -63 : 103}).style('fill', function(d) {return d.hasNode == 1 ? '#9CD0FF' : ''}).style('stroke', function(d) {return d.hasNode == 1 ? '#9CD0FF' : ''}).style('stroke-width', function(d) {if (d.repeated) {return 5}})//代表是否展开的+-号nodeEnter.append('svg:text').attr('class', 'isExpand').attr('x', '0').attr('dy', function(d) {return forUpward ? -57 : 109}).attr('text-anchor', 'middle').style('fill', '#fff').style('font-size', '20px').style('cursor', 'pointer').text(function(d) {if (d.name == 'origin') {return ''}return d.hasNode == 1 ? '+' : ''}).on('click', click)nodeUpdate.select('text').style('fill-opacity', 1)var nodeExit = node.exit().transition().duration(duration).attr('transform', function(d) {return 'translate(' + source.x + ',' + source.y + ')'}).remove()nodeExit.select('circle').attr('r', 1e-6)nodeExit.select('text').style('fill-opacity', 1e-6)var link = g.selectAll('path.' + link_class).data(links, function(d) {return d.target.id})link.enter().insert('path', 'g').attr('class', link_class).attr('stroke', function(d) {// return '#8b4513'return '#919191'}).attr('fill', 'none').attr('stroke-width', '1px')// .attr('opacity', 0.5).attr('d', function(d) {var o = {x: source.x0,y: source.y0}return diagonal({source: o,target: o})}).attr('marker-end', function(d, i) {return forUpward ? getMarkerUpArrow(d, i) : getMarkerDownArrow(d, i)}).attr('id', function(d, i) {return 'mypath' + '-' + d.source.id + '-' + d.target.id})link.transition().duration(duration).attr('d', diagonal)link.exit().transition().duration(duration).attr('d', function(d) {var o = {x: source.x,y: source.y}return diagonal({source: o,target: o})}).remove()nodes.forEach(function(d) {d.x0 = d.xd.y0 = d.y})function getMarkerUpArrow(d, i) {svg.append('defs').append('marker') //箭头.attr('id', 'resolved' + d.target.id).attr('markerUnits', 'strokeWidth') //设置为strokeWidth箭头会随着线的粗细发生变化.attr('markerUnits', 'userSpaceOnUse').attr('viewBox', '0 -5 10 10') //坐标系的区域.attr('refX', -28) //箭头坐标.attr('refY', 0).attr('markerWidth', 12) //标识的大小.attr('markerHeight', 12).attr('orient', '90') //绘制方向,可设定为:auto(自动确认方向)和 角度值.attr('stroke-width', 2) //箭头宽度.append('path').attr('d', 'M0,-5L10,0L0,5') //箭头的路径.attr('fill', '#919191') //箭头颜色return 'url(#resolved' + d.target.id + ')'}function getMarkerDownArrow(d, i) {svg.append('defs').append('marker') //箭头.attr('id', 'resolved' + d.target.id).attr('markerUnits', 'strokeWidth') //设置为strokeWidth箭头会随着线的粗细发生变化.attr('markerUnits', 'userSpaceOnUse').attr('viewBox', '0 -5 10 10') //坐标系的区域.attr('refX', 0) //箭头坐标.attr('refY', 0).attr('markerWidth', 12) //标识的大小.attr('markerHeight', 12).attr('orient', '90') //绘制方向,可设定为:auto(自动确认方向)和 角度值.attr('stroke-width', 2) //箭头宽度.append('path').attr('d', 'M0,-5L10,0L0,5') //箭头的路径.attr('fill', '#919191')return 'url(#resolved' + d.target.id + ')'}function Change_modal() {_this.Modal = true}function click(d) {event.stopPropagation()if (forUpward) {} else {if (d._children) {console.log('对外投资--ok')} else {console.log('对外投资--no')}}isExpand = !isExpandif (d.name == 'origin') {return}if (d.children) {d._children = d.childrend.children = nulld3.select(this).text('+')update(d, originalData, g)} else {if (d._children && d._children.length > 0) {d.children = d._childrend._children = nullif (d.name == 'origin') {d.children.forEach(expand)}d3.select(this).text('-')update(d, originalData, g)} else {gqctt({beijingCrid: d.direction == 'up' ? d.beijingCrid : d.pbeijingCrid,direction: d.direction}).then(res => {if (res.code === 0) {if (d.direction == 'up') {d.children = res.result.investorListd.children.map(item => {item.amount = Number(item.subConAm).toFixed(2)item.isFHolder = trueitem.ratio = item.subComBl.length > 6 ? calculation.accMul(item.subComBl, 100).toFixed(2) + '%' : calculation.accMul(item.subComBl, 100) + '%'item.name = item.entNameitem.type = item.bz === '企业' ? 2 : 1item.isHoldingCompany = item.isHolding == 1 ? true : falseitem.isFHolder = item.subComBl >= 0.25 && item.type == 1item.direction = directionitem.holderPercent = item.ratio})} else {d.children = res.result.holderListd.children.map(item => {item.amount = Number(item.subConAm).toFixed(2)item.isFHolder = trueitem.ratio = item.subComBl.length > 6 ? calculation.accMul(item.subComBl, 100).toFixed(2) + '%' : calculation.accMul(item.subComBl, 100) + '%'item.name = item.pentNameitem.type = item.bz === '企业' ? 2 : 1item.isHoldingCompany = item.isHolding == 1 ? true : falseitem.isFHolder = item.subComBl >= 0.25 && item.type == 1item.direction = directionitem.holderPercent = item.ratio})}d._children = nullif (d.name == 'origin') {d.children.forEach(expand)}d3.select(this).text('-')update(d, originalData, g)}})}}}}function expand(d) {if (d._children) {d.children = d._childrend.children.forEach(expand)d._children = null}}function collapse(d) {if (d.children && d.children.length != 0) {d._children = d.childrend._children.forEach(collapse)d.children = nullhasChildNodeArr.push(d)}}function redraw() {treeG.attr('transform', 'translate(' + zoom.translate() + ')' + ' scale(' + zoom.scale() + ')')}function disableRightClick() {// stop zoomif (d3.event.button == 2) {console.log('No right click allowed')d3.event.stopImmediatePropagation()}}function sortByDate(a, b) {var aNum = a.name.substr(a.name.lastIndexOf('(') + 1, 4)var bNum = b.name.substr(b.name.lastIndexOf('(') + 1, 4)return d3.ascending(aNum, bNum) || d3.ascending(a.name, b.name) || d3.ascending(a.id, b.id)}}var d3GenerationChart = new treeChart(d3)d3GenerationChart.drawChart()},onJumpReport() {// this.$router.push(...)},downloadImpByChart(chartName) {var _this = thisvar html = document.getElementsByTagName('html')[0] //获取可视区域宽var Bwidth = html.clientWidth + 20 //转换屏幕宽高var Bheight = html.clientHeight + 150var Bmax = Bwidth > Bheight ? Bwidth : Bheightvar Bmin = Bwidth > Bheight ? Bheight : Bwidthvar canvas = document.createElement('canvas')var g = document.getElementsByTagName('g')[0].getBBox()var svgbox = d3.select('#mountNode svg')var gbox = document.getElementsByClassName('gbox')[0] || document.getElementsByClassName('container')[0]var x = g.width / 2 - html.clientWidth / 2 + 20 //计算偏移位置var y = 0g.y < 0 ? (y = Math.abs(g.y)) : (y = 0)// gbox.style.transform = "translate(" + x + 'px' + "," + (y-60) + "px" + ") scale(1)"; //偏移位置gbox.style.transform = 'translate(' + x + 'px' + ',' + y + 'px' + ') scale(1)' //偏移位置svgbox.attr('width', g.width + 20)svgbox.attr('height', g.height + 150)var svg = document.getElementById('mountNode').innerHTMLvar c = canvas.getContext('2d')//新建Image对象var img = new Image()//svg内容img.src = 'data:image/svg+xml,' + encodeURIComponent(svg) //svg内容中可以有中文字符// img.src = "data:image/svg+xml," + svg; //svg内容中不能有中文字符//图片初始化完成后调用var cwidth = g.widthimg.onload = function() {//将canvas的宽高设置为图像的宽高canvas.width = cwidth + 20canvas.height = g.height + 150//canvcas画图片c.fillStyle = '#fff'c.fillRect(0, 0, canvas.width, canvas.height)c.drawImage(img, 0, 30)var a = document.createElement('a')a.download = `${chartName}-${_this.companyName}.png`a.href = canvas.toDataURL('image/png')a.click()}//图片转换为base64后 传给后端 发邮件gbox.style.transform = ''svgbox.attr('width', Bmax)svgbox.attr('height', Bmin)},checkFull() {var isFull = document.fullscreenEnabled || window.fullScreen || document.webkitIsFullScreen || document.msFullscreenEnabledif (isFull === undefined) {isFull = false}return isFull},FullScreen(el) {if (this.isFullscreen) {//退出全屏if (document.exitFullscreen) {document.exitFullscreen()} else if (document.mozCancelFullScreen) {document.mozCancelFullScreen()} else if (document.webkitExitFullscreen) {document.webkitExitFullscreen()} else if (!document.msRequestFullscreen) {document.msExitFullscreen()}} else {//进入全屏if (el.requestFullscreen) {el.requestFullscreen()} else if (el.mozRequestFullScreen) {el.mozRequestFullScreen()} else if (el.webkitRequestFullscreen) {//改变平面图在google浏览器上面的样式问题el.webkitRequestFullscreen()} else if (el.msRequestFullscreen) {this.isFullscreen = trueel.msRequestFullscreen()}}},toggleFullScreen(e) {this.isFullscreen = !this.isFullscreenthis.FullScreen(document.getElementById('borrow'))}}
<style>
.borrow {height: 1000px;position: relative;top: -66px;
}
</style>
效果图:
仿天眼查-股权结构图相关推荐
- D3 天眼查 股权结构图
效果大致就是上图 tianyancha上面 该效果叫股权结构 图上信息属于公示信息 不存在泄密 暂时不考虑兼容性和下载 旋转等问题.如有这些问题 可以查看我上一篇股权穿透图 有对应解决方案. 本文 ...
- D3 天眼查 股权穿透 股权结构
效果图如上 大致效果就是仿照天眼查股权穿透图 曲线会出现节点位置不对(曲线的算法是在不会 技术菜解决不了) 最后刀放到产品脖子他同意用折线代替 在下面已经补充 JSON数据 把请求换成请求本地j ...
- D3 天眼查 股权穿透 股权结构,默认第一行,异步添加,加减号居中,拖拽,缩放, hover。
因为公司项目需求,在以下相关博客的的基础上,进行了修改. D3 天眼查 股权穿透 股权结构 1.鼠标经过路径高亮. 2. 加减号优化,很多文章都是直接text标签渲染 "+&qu ...
- 仿企查查、天眼查股权穿透d3
企业图谱做出来了,接下来仿企查查写个股权穿透的图谱 企查查股权穿透 自己的 首先使用的方法以及生成图的方法 跟企业图谱类似 也是用的d3官方demo给出的生成双向树的方法,不过版本是d3.v3 相比企 ...
- d3 企业图谱 仿天眼查 企查查
最近接到一个需求,终端要加入企业图谱的功能.能无线穿透下去,之前写过一个类似树形图但是节点长度没有自适应(如下图),样式也不够好看,产品提出做一个类似企查查那种的企业图谱,能更直观的展示企业信息,无奈 ...
- 前端vue uni-app仿企查查、天眼查关联投资机构 股权结构 树形结构 控股结构
快速实现vue uni-app前端仿企查查.天眼查关联投资机构 股权结构 树形结构 控股结构, 下载请访问uni-app插件市场:https://ext.dcloud.net.cn/plugin?id ...
- 仿企查查、天眼查关系图以及架构图(双向树,集团图谱,组织架构图谱,企业图谱,网络拓扑,人物关系网络)
前言: 最近公司有一些新需求,要求仿照企查查,爱企查,天眼查等软件的关系图.股权结构图.公司架构图等作出相似的功能一开始考虑使用echarts来实现但是最后做出的效果与他们的效果太不一样也不太理想,偶 ...
- “二查”再开打:企查查控诉天眼查窃取数据
数据智能产业创新服务媒体 --聚焦数智 · 改变商业 近日,企查查官方微博发布<关于天眼查窃取数据的控诉>声明,并表示:"我们谢绝一切偷盗行为!目前我们已将相关数据信息取证,并同 ...
- 专业版云南_云南核桃集中上市市民“囤货”忙,天眼查:我国8万余家核桃相关企业,云南省数量最多...
[猎云网(微信:ilieyun)北京]11月18日报道 据央视财经报道,现在正是云南的鲜核桃上市的季节. 在昆明一农贸市场,记者看到新鲜核桃标价是二十到二十五元钱一公斤.商户们说,今年新鲜核桃刚上市价 ...
最新文章
- 智能产品AI服务智商的权重研究|未来研究
- PAT 1052. Linked List Sorting
- 从前序与中序遍历序列构造二叉树Python解法
- ecshop goods.php,重命名ecshop的商品页goods.php为shangpin.php
- Web前端—— JQuery迷你版实现以及使用
- python如何将数据保存到本地json文件
- 修理计算机英语,英语口语对话:修理电脑
- Spring Cloud Hystrix——熔断器
- 第一台电子计算机于1846年诞生,全国2010年1月高等教育自学考试计算机与网络技术基础试题.doc...
- java开发转测试开发经历
- Java的发展 Java在不同系统下的开发环境 Java语言特性 Java实现跨平台
- cad文字递增快捷键_史上最全CAD快捷键命令大全(图文版、文字版、键盘版)
- 塑料壳上下扣合的卡扣设计_卡扣结构设计常识,结构设计中扣合量如何留
- 从零开始部署深信服EDR
- 直播平台源码搭建教程之Android音视频开发
- JAVA编写元音字母(Switch语句)
- 地理信息系统-什么是GIS
- Python多线程、多进程最全整理
- MySQL数据库:SQL语句优化
- node.js命令行程序在Windows系统和Linux系统下的部署
热门文章
- 【shell脚本】沐风晓月跟你聊聊shell脚本中的while循环
- Docker: 企业级镜像仓库Harbor的使用
- 据说年薪30万的Android程序员必须知道的帖子
- 【前端学习笔记day35】4.5. Photoshop制作雪碧图技巧
- 面朝大海,春暖花开--曼陀山庄之段誉[zz]
- r语言导出文件为xlxs_R语言学习——R读取txt、csv、xls和xlsx格式文件
- 北大青鸟职业技能等级认定第三方评价机构迎来首考
- 使用计算机开机按啥建,电脑开机按TAB键有什么作用?
- BurpSuite安装(附安装包)
- 2021HW | 04/12 第四天总结