fix:图表销毁解绑事件

This commit is contained in:
zyh
2023-04-10 14:26:46 +08:00
parent 37c5be765a
commit bf8f5ae241
8 changed files with 137 additions and 80 deletions

View File

@@ -137,7 +137,7 @@ export default {
} }
}, },
mounted () { mounted () {
// this.queryAllProjectData() this.queryAllProjectData()
this.$get('/topology/icon').then(res => { this.$get('/topology/icon').then(res => {
this.iconArray = [...res.data.list] this.iconArray = [...res.data.list]
}) })

View File

@@ -58,7 +58,8 @@ export default {
value: 0, value: 0,
mapping: {}, mapping: {},
show: false show: false
} },
svg: null
} }
}, },
methods: { methods: {
@@ -108,13 +109,14 @@ export default {
}, },
drawBubbleChart () { drawBubbleChart () {
this.$nextTick(() => { this.$nextTick(() => {
d3.select(`#bubble-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
const svg = document.getElementById(`bubble-svg-${this.chartId}`) this.svg = d3.select(`#bubble-svg-${this.chartId}`)
if (!svg) { const svgDom = document.getElementById(`bubble-svg-${this.chartId}`)
if (!svgDom) {
return false return false
} }
const width = svg.getBoundingClientRect().width const width = svgDom.getBoundingClientRect().width
const height = svg.getBoundingClientRect().height const height = svgDom.getBoundingClientRect().height
// 定义布局方式 // 定义布局方式
const pack = d3.pack() const pack = d3.pack()
.size([width, height]) .size([width, height])
@@ -137,7 +139,7 @@ export default {
return b.value - a.value return b.value - a.value
}) })
const nodes = pack(data).descendants() const nodes = pack(data).descendants()
const bubbles = d3.select(`#bubble-svg-${this.chartId}`).selectAll('.bubble') const bubbles = this.svg.selectAll('.bubble')
.data(nodes) .data(nodes)
.enter() .enter()
.filter(function (d) { .filter(function (d) {
@@ -236,11 +238,6 @@ export default {
` `
} }
}, },
resize () {
setTimeout(() => {
this.drawBubbleChart()
}, 50)
},
bubbleEnter (e, node) { // 移入气泡 bubbleEnter (e, node) { // 移入气泡
this.tooltip.title = node.data.alias this.tooltip.title = node.data.alias
this.tooltip.value = node.data.showValue this.tooltip.value = node.data.showValue
@@ -277,6 +274,20 @@ export default {
this.tooltip.y = e.pageY + 15 this.tooltip.y = e.pageY + 15
this.tooltip.x = e.pageX + 15 this.tooltip.x = e.pageX + 15
} }
},
resize () {
setTimeout(() => {
this.drawBubbleChart()
}, 50)
},
dispose () {
if (this.svg) {
this.svg.selectAll('.bubble').on('mouseenter', null)
this.svg.selectAll('.bubble').on('mousemove', null)
this.svg.selectAll('.bubble').on('mouseleave', null)
this.svg.selectAll('g').remove()
this.svg = null
}
} }
}, },
mounted () { mounted () {
@@ -284,7 +295,7 @@ export default {
this.chartInfo.loaded && this.initChart() this.chartInfo.loaded && this.initChart()
}, },
beforeDestroy () { beforeDestroy () {
d3.select(`#bubble-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
} }
} }
</script> </script>

View File

@@ -58,7 +58,8 @@ export default {
value: 0, value: 0,
mapping: {}, mapping: {},
show: false show: false
} },
svg: null
} }
}, },
methods: { methods: {
@@ -122,7 +123,7 @@ export default {
funnelData = funnelData.filter(item => item.value !== 0) funnelData = funnelData.filter(item => item.value !== 0)
} }
this.$nextTick(() => { this.$nextTick(() => {
d3.select(`#funnel-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
// 获取svg宽高 初始化画布 // 获取svg宽高 初始化画布
const svgDom = document.getElementById(`funnel-svg-${this.chartId}`) const svgDom = document.getElementById(`funnel-svg-${this.chartId}`)
if (!svgDom) { if (!svgDom) {
@@ -153,8 +154,8 @@ export default {
return d return d
} }
) )
const svg = d3.select(`#funnel-svg-${this.chartId}`) this.svg = d3.select(`#funnel-svg-${this.chartId}`)
const chart = svg.append('g').attr('width', chartWidth).attr('height', chartHeight).attr('transform', `translate(${margin}, ${margin})`) const chart = this.svg.append('g').attr('width', chartWidth).attr('height', chartHeight).attr('transform', `translate(${margin}, ${margin})`)
// 渲染梯形 // 渲染梯形
const trapezoids = chart const trapezoids = chart
@@ -290,11 +291,6 @@ export default {
` `
} }
}, },
resize () {
setTimeout(() => {
this.drawChart()
}, 50)
},
chartEnter (e, data) { chartEnter (e, data) {
this.tooltip.title = data.alias this.tooltip.title = data.alias
this.tooltip.value = data.showValue this.tooltip.value = data.showValue
@@ -367,6 +363,23 @@ export default {
(Math.round((t - B) * p) + B) (Math.round((t - B) * p) + B)
return `#${converted.toString(16).slice(1)}` return `#${converted.toString(16).slice(1)}`
},
resize () {
setTimeout(() => {
this.drawChart()
}, 50)
},
dispose () {
if (this.svg) {
this.svg.selectAll('.trap').on('mouseover', null)
this.svg.selectAll('.trap').on('mousemove', null)
this.svg.selectAll('.trap').on('mouseleave', null)
this.svg.selectAll('foreignObject').on('mouseover', null)
this.svg.selectAll('foreignObject').on('mousemove', null)
this.svg.selectAll('foreignObject').on('mouseleave', null)
this.svg.selectAll('g').remove()
this.svg = null
}
} }
}, },
mounted () { mounted () {
@@ -374,7 +387,7 @@ export default {
this.chartInfo.loaded && this.initChart(true) this.chartInfo.loaded && this.initChart(true)
}, },
beforeDestroy () { beforeDestroy () {
d3.select(`#funnel-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
} }
} }
</script> </script>

View File

@@ -45,7 +45,7 @@ export default {
mapping: {}, mapping: {},
show: false show: false
}, },
svgDom: null, svg: null,
spaceBetweenHexa: 3, spaceBetweenHexa: 3,
hexagonTimer: null hexagonTimer: null
} }
@@ -53,21 +53,19 @@ export default {
methods: { methods: {
hexbin, hexbin,
initChart () { initChart () {
this.clearCache().then(() => { if (this.timer) {
if (this.timer) { clearTimeout(this.timer)
clearTimeout(this.timer) this.timer = null
this.timer = null }
} this.timer = setTimeout(() => {
this.timer = setTimeout(() => { this.initHexagonData(this.chartInfo, this.chartData).then(() => {
this.initHexagonData(this.chartInfo, this.chartData).then(() => { this.getLayout().then(layout => {
this.getLayout().then(layout => { this.initHexagon(layout)
this.initHexagon(layout) }).catch(() => {
}).catch(() => {
})
}) })
}, 200) })
}) }, 200)
}, },
initHexagonData (chartInfo, originalDatas) { initHexagonData (chartInfo, originalDatas) {
this.HexagonData = [] this.HexagonData = []
@@ -135,7 +133,8 @@ export default {
const dom = document.getElementById(`chart-canvas-${this.chartId}`) const dom = document.getElementById(`chart-canvas-${this.chartId}`)
const child = document.getElementById('svgHex' + this.chartId) const child = document.getElementById('svgHex' + this.chartId)
if (dom && child) { if (dom && child) {
dom.removeChild(child) this.clearCache()
// dom.removeChild(child)
} }
if (dom) { if (dom) {
const hexaRadius = layout.radius const hexaRadius = layout.radius
@@ -164,13 +163,11 @@ export default {
const hexbin = this.hexbin() const hexbin = this.hexbin()
.radius(hexaRadius) .radius(hexaRadius)
.extent([[0, 0], [width, height]]) .extent([[0, 0], [width, height]])
this.svg = d3.create('svg')
const svg = d3.create('svg')
.attr('id', 'svgHex' + this.chartId) .attr('id', 'svgHex' + this.chartId)
.attr('width', width) .attr('width', width)
.attr('height', height) .attr('height', height)
.on('mousemove', this.hexagonMove) .on('mousemove', this.hexagonMove)
this.svgDom = 'svgHex' + this.chartId
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const point = data[i] const point = data[i]
const col = point.x const col = point.x
@@ -179,15 +176,15 @@ export default {
const vals = self.getCenter(hexaRadius, row, col) // Gets the Center coordinates with given row and column const vals = self.getCenter(hexaRadius, row, col) // Gets the Center coordinates with given row and column
const x = vals[0] const x = vals[0]
const y = vals[1] const y = vals[1]
const g = svg.append('g') const g = this.svg.append('g')
const hexa = self.drawHexagon(g, hexaRadius, spaceBetweenHexa, x, y, hexbin) // Draws hexagon const hexa = self.drawHexagon(g, hexaRadius, spaceBetweenHexa, x, y, hexbin) // Draws hexagon
hexa.attr('fill', color) // Paints hexagon hexa.attr('fill', color) // Paints hexagon
g.on('mouseenter', self.hexagonOver.bind(self, point)) g.on('mouseenter', self.hexagonOver.bind(self, point))
g.on('mouseleave', self.hexagonOut.bind(self, point)) g.on('mouseleave', self.hexagonOut.bind(self, point))
self.drawText(svg, vals, point, color, hexaRadius, g) // 文本 self.drawText(this.svg, vals, point, color, hexaRadius, g) // 文本
data[i].fcolor = color data[i].fcolor = color
} }
return svg.node() return this.svg.node()
}, },
hexagonOver (that, e) { // 移入六边形 hexagonOver (that, e) { // 移入六边形
this.tooltip.title = that.alias this.tooltip.title = that.alias
@@ -414,13 +411,13 @@ export default {
}) })
}, },
clearCache () { clearCache () {
return new Promise(resolve => { if (this.svg) {
// if (this.svgDom) { this.svg.on('mousemove', null)
// const dom = document.getElementById(this.svgDom) this.svg.selectAll('g').on('mouseenter', null)
// dom.off('mousemove', this.hexagonMove) this.svg.selectAll('g').on('mouseleave', null)
// } this.svg.remove()
resolve() this.svg = null
}) }
}, },
resize () { resize () {
if (this.hexagonTimer) { if (this.hexagonTimer) {
@@ -436,8 +433,6 @@ export default {
}, 50) }, 50)
} }
}, },
created () {
},
mounted () { mounted () {
// eslint-disable-next-line vue/no-mutating-props // eslint-disable-next-line vue/no-mutating-props
this.chartOption.color || (this.chartOption.color = initColor(20)) this.chartOption.color || (this.chartOption.color = initColor(20))
@@ -445,6 +440,14 @@ export default {
this.chartInfo.loaded && this.initChart(this.chartOption) this.chartInfo.loaded && this.initChart(this.chartOption)
}, },
beforeDestroy () { beforeDestroy () {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null
}
if (this.hexagonTimer) {
clearTimeout(this.hexagonTimer)
this.hexagonTimer = null
}
this.clearCache() this.clearCache()
} }
} }

View File

@@ -64,7 +64,8 @@ export default {
mapping: {}, mapping: {},
rank: 0, rank: 0,
show: false show: false
} },
svg: null
} }
}, },
methods: { methods: {
@@ -115,7 +116,7 @@ export default {
drawRankChart () { drawRankChart () {
this.$nextTick(() => { this.$nextTick(() => {
d3.select(`#rank-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
// 获取svg宽高 初始化画布 // 获取svg宽高 初始化画布
const svgDom = document.getElementById(`rank-svg-${this.chartId}`) const svgDom = document.getElementById(`rank-svg-${this.chartId}`)
if (!svgDom) { if (!svgDom) {
@@ -128,7 +129,7 @@ export default {
const margin = 40 const margin = 40
// 计算svg高度 // 计算svg高度
const height = this.rankData.length * (barHeight + margin) + margin const height = this.rankData.length * (barHeight + margin) + margin
const svg = d3.select(`#rank-svg-${this.chartId}`).attr('height', height) this.svg = d3.select(`#rank-svg-${this.chartId}`).attr('height', height)
const bodyX = 50 const bodyX = 50
const bodyWidth = width - 3 * bodyX const bodyWidth = width - 3 * bodyX
@@ -151,7 +152,7 @@ export default {
// 柱子最小宽度 // 柱子最小宽度
const minWidth = 2 const minWidth = 2
// 渲染柱形 // 渲染柱形
const bars = svg.append('g') const bars = this.svg.append('g')
.attr('transform', `translate(${bodyX})`) .attr('transform', `translate(${bodyX})`)
.selectAll() .selectAll()
.data(rankData) .data(rankData)
@@ -174,7 +175,7 @@ export default {
bars.exit().remove() bars.exit().remove()
// 文本标签 // 文本标签
svg.append('g') this.svg.append('g')
.attr('transform', `translate(${bodyX})`) .attr('transform', `translate(${bodyX})`)
.selectAll() .selectAll()
.data(rankData) .data(rankData)
@@ -203,7 +204,7 @@ export default {
.style('overflow', 'visible') .style('overflow', 'visible')
// 生成标签和矩形 // 生成标签和矩形
svg.append('g') this.svg.append('g')
.attr('transform', `translate(${bodyX})`) .attr('transform', `translate(${bodyX})`)
.selectAll('text') .selectAll('text')
.data(rankData) .data(rankData)
@@ -283,11 +284,22 @@ export default {
this.tooltip.x = e.pageX + 15 this.tooltip.x = e.pageX + 15
} }
}, },
resize () { resize () {
setTimeout(() => { setTimeout(() => {
this.drawRankChart() this.drawRankChart()
}, 50) }, 50)
},
dispose () {
if (this.svg) {
this.svg.selectAll('rect').on('mouseenter', null)
this.svg.selectAll('rect').on('mousemove', null)
this.svg.selectAll('rect').on('mouseleave', null)
this.svg.selectAll('foreignObject').on('mouseenter', null)
this.svg.selectAll('foreignObject').on('mousemove', null)
this.svg.selectAll('foreignObject').on('mouseleave', null)
this.svg.selectAll('g').remove()
this.svg = null
}
} }
}, },
@@ -296,7 +308,7 @@ export default {
this.chartInfo.loaded && this.initChart() this.chartInfo.loaded && this.initChart()
}, },
beforeDestroy () { beforeDestroy () {
d3.select(`#rank-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
} }
} }
</script> </script>

View File

@@ -59,7 +59,8 @@ export default {
value: 0, value: 0,
mapping: {}, mapping: {},
show: false show: false
} },
svg: null
} }
}, },
methods: { methods: {
@@ -136,8 +137,7 @@ export default {
drawSankeyChart () { drawSankeyChart () {
this.$nextTick(() => { this.$nextTick(() => {
d3.select(`#sankey-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
// 获取svg宽高 初始化画布 // 获取svg宽高 初始化画布
const svgDom = document.getElementById(`sankey-svg-${this.chartId}`) const svgDom = document.getElementById(`sankey-svg-${this.chartId}`)
if (!svgDom) { if (!svgDom) {
@@ -147,8 +147,8 @@ export default {
const height = svgDom.getBoundingClientRect().height const height = svgDom.getBoundingClientRect().height
const margin1 = 100 const margin1 = 100
const margin2 = 50 const margin2 = 50
const svg = d3.select(`#sankey-svg-${this.chartId}`) this.svg = d3.select(`#sankey-svg-${this.chartId}`)
const chart = svg.append('g').attr('transform', `translate(${margin2}, ${margin2})`) const chart = this.svg.append('g').attr('transform', `translate(${margin2}, ${margin2})`)
// 创建桑基图生成器 // 创建桑基图生成器
const sankey = d3Sankey const sankey = d3Sankey
@@ -389,6 +389,18 @@ export default {
setTimeout(() => { setTimeout(() => {
this.drawSankeyChart() this.drawSankeyChart()
}, 50) }, 50)
},
dispose () {
if (this.svg) {
this.svg.selectAll('path').on('mouseover', null)
this.svg.selectAll('path').on('mousemove', null)
this.svg.selectAll('path').on('mouseleave', null)
this.svg.selectAll('.node').on('mouseover', null)
this.svg.selectAll('.node').on('mousemove', null)
this.svg.selectAll('.node').on('mouseleave', null)
this.svg.selectAll('g').remove()
this.svg = null
}
} }
}, },
mounted () { mounted () {
@@ -396,7 +408,7 @@ export default {
this.chartInfo.loaded && this.initChart() this.chartInfo.loaded && this.initChart()
}, },
beforeDestroy () { beforeDestroy () {
d3.select(`#sankey-svg-${this.chartId}`).selectAll('g').remove() // 清空作图区域 this.dispose()
} }
} }
</script> </script>

View File

@@ -439,18 +439,18 @@ export default {
this.initChart(this.chartOption) this.initChart(this.chartOption)
} }
} }
},
'chartInfo.loaded': {
immediate: true,
deep: true,
handler (n) {
if (n) {
this.initChart && this.initChart(this.chartOption)
}
}
} }
// 'chartInfo.loaded': {
// immediate: true,
// deep: true,
// handler (n) {
// if (n) {
// this.initChart && this.initChart(this.chartOption)
// }
// }
// }
}, },
mounted () { created () {
this.chartId = `${this.chartInfo.id}${this.isFullscreen ? '-fullscreen' : ''}` this.chartId = `${this.chartInfo.id}${this.isFullscreen ? '-fullscreen' : ''}`
}, },
beforeDestroy () { beforeDestroy () {

View File

@@ -163,12 +163,12 @@ export default {
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.refreshDataFunc() this.refreshDataFunc()
this.timer = '' this.timer = null
}, 200) }, 200)
} else { } else {
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.refreshDataFunc() this.refreshDataFunc()
this.timer = '' this.timer = null
}, 200) }, 200)
} }
} }
@@ -181,6 +181,12 @@ export default {
} }
}, },
beforeDestroy () { beforeDestroy () {
if (this.timer) {
this.timer = setTimeout(() => {
this.refreshDataFunc()
this.timer = null
}, 200)
}
if (this.intervalTimer) { if (this.intervalTimer) {
clearInterval(this.intervalTimer) clearInterval(this.intervalTimer)
this.intervalTimer = null this.intervalTimer = null