提交 8e2938ae authored 作者: 祖铭松's avatar 祖铭松

feat: update

上级 18ad5e72
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
import { ref, onMounted, onUnmounted } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm'; import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
import { chartMockData } from '../utils/mock'; import { chartMockData } from '../utils/mock';
import { setTips, setMaxMinNumber, coordinateScale, setColor, setCluster, setLegend, setLabel } from '../utils/index'; import { setTips, setMaxMinNumber, coordinateScale, setColor, setCluster, setLegend, legendActive, setLabel } from '../utils/index';
import PubSub from 'pubsub-js'; import PubSub from 'pubsub-js';
// 根节点实例 // 根节点实例
...@@ -35,7 +35,10 @@ const generateChart = (data) => { ...@@ -35,7 +35,10 @@ const generateChart = (data) => {
let marginLeft = Number(ret.margin_left) || 60; let marginLeft = Number(ret.margin_left) || 60;
let radius = Number(ret.point_radius) || 4; let radius = Number(ret.point_radius) || 4;
let colors = ret.data_color_list || ['#E53935', '#1E88E5']; let colors = ret.data_color_list || ['#E53935', '#1E88E5'];
let legendData = ['Cancer', 'Non-cance']; let legendData = [
{ name: 'Cancer', checked: true },
{ name: 'Non-cance', checked: true }
];
const titleConfig = { const titleConfig = {
label: !!ret.title ? ret.title : '', label: !!ret.title ? ret.title : '',
...@@ -85,7 +88,7 @@ const generateChart = (data) => { ...@@ -85,7 +88,7 @@ const generateChart = (data) => {
setTips(cluster); setTips(cluster);
// legend // legend
configObj.show_legend && setLegend(configObj); configObj.show_legend && setLegend(configObj, data);
// label // label
setLabel(configObj); setLabel(configObj);
......
...@@ -2,13 +2,14 @@ import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm'; ...@@ -2,13 +2,14 @@ import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
// color config // color config
export const setColor = (config) => { export const setColor = (config) => {
let colors = ['#E53935', '#1E88E5']; let colors = [];
if (Array.isArray(config.colors)) { if (Array.isArray(config.colors)) {
colors = !!config.colors.length ? config.colors : colors; colors = !!config.colors.length ? config.colors : colors;
} else if (!!config.colors) { } else if (!!config.colors) {
colors = config.colors.split(','); colors = config.colors.split(',');
} }
return d3.scaleOrdinal(colors).domain(config.legendData); const legend = config.legendData.map(item => item.name)
return d3.scaleOrdinal(colors).domain(legend);
}; };
// paddedMin paddedMax // paddedMin paddedMax
...@@ -26,12 +27,13 @@ export const setMaxMinNumber = (data) => { ...@@ -26,12 +27,13 @@ export const setMaxMinNumber = (data) => {
export const setCluster = (config, data) => { export const setCluster = (config, data) => {
return config.svg return config.svg
.append('g') .append('g')
.attr('class', 'main-chart')
.style('isolation', 'isolate') .style('isolation', 'isolate')
.selectAll('circle') .selectAll('circle')
.data(data) .data(data)
.enter() .enter()
.append('circle') .append('circle')
.attr('class', 'points') .attr('class', (d) => `points-${d.group}`)
.attr('cx', (d) => config.x(d.x)) .attr('cx', (d) => config.x(d.x))
.attr('cy', (d) => config.y(d.y)) .attr('cy', (d) => config.y(d.y))
.attr('fill', (d) => config.color(d.group)) .attr('fill', (d) => config.color(d.group))
...@@ -84,15 +86,17 @@ export const setTips = (rect) => { ...@@ -84,15 +86,17 @@ export const setTips = (rect) => {
}; };
// legend // legend
export const setLegend = (config) => { export const setLegend = (config, data) => {
config.svg.append('g') config.svg.append('g')
.attr('transform', `translate(${config.width - config.marginLeft - 70}, ${100})`) .attr('transform', `translate(${config.width - config.marginLeft - 70}, ${100})`)
.attr('cursor', 'pointer')
.selectAll() .selectAll()
.data(config.legendData) .data(config.legendData)
.join('g') .join('g')
.attr('class', 'legend-rect')
.attr('transform', (d, i) => `translate(0, ${i * 20})`) .attr('transform', (d, i) => `translate(0, ${i * 20})`)
.call((g) => g.append('rect').attr('width', 15).attr('height', 15).attr('fill', d => config.color(d))) .call((g) => g.append('rect').attr('class', 'rect-legend').attr('width', 15).attr('height', 15).attr('fill', d => config.color(d.name)))
.call((g) => .call((g) =>
g g
.append('text') .append('text')
...@@ -100,8 +104,10 @@ export const setLegend = (config) => { ...@@ -100,8 +104,10 @@ export const setLegend = (config) => {
.attr('y', 8) .attr('y', 8)
.attr('dy', '0.3em') .attr('dy', '0.3em')
.style('font', '13px sans-serif') .style('font', '13px sans-serif')
.text((d) => d) .text((d) => d.name)
); );
legendActive(config, data);
}; };
// title // title
...@@ -115,5 +121,59 @@ export const setLabel = (config) => { ...@@ -115,5 +121,59 @@ export const setLabel = (config) => {
.attr('font-style', `${config.titleConfig.fontStyle}`) .attr('font-style', `${config.titleConfig.fontStyle}`)
.attr('font-weight', `${config.titleConfig.fontWeight}`) .attr('font-weight', `${config.titleConfig.fontWeight}`)
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.text('group'); .text(config.titleConfig.label);
}; };
// legend active
export const legendActive = (config) => {
const legend = config.svg.selectAll('.legend-rect')
legend.on('click', (e, d) => {
config.legendData = config.legendData.map(item => {
if (item.name === d.name) {
return { ...item, checked: !item.checked }
} else {
return { ...item }
}
})
const currentLegend = config.legendData.find(item => item.name == d.name);
config.svg.selectAll('.rect-legend').data(config.legendData).attr('fill', (d) => d.checked ? config.color(d.name) : '#aaa');
config.svg.selectAll(`.points-${currentLegend.name}`).attr('display', `${currentLegend.checked ? 'block' : 'none'}`)
})
}
export const legendDataActive = (config) => {
const legend = config.svg.selectAll('.legend-rect')
const legendRect = legend.select('rect')
legend.on('click', (e, d) => {
config.legendData = config.legendData.map(item => {
if (item.name === d.name) {
return { ...item, checked: !item.checked }
} else {
return { ...item }
}
})
legendRect.data(config.legendData).attr('fill', (d, i) => d.checked ? config.color(d.name) : '#aaa');
const activeLegend = [];
let newData = [];
for (let i = 0; i < config.legendData.length; i++) {
if (config.legendData[i].checked) {
activeLegend.push(config.legendData[i].name)
}
}
if (activeLegend.length > 0) {
activeLegend.forEach(name => {
newData.push(...chartData.filter(item => item.group == name))
})
} else {
newData = []
}
config.svg.select('.main-chart').remove();
setTips(setCluster(config, newData))
})
}
\ No newline at end of file
...@@ -34,7 +34,10 @@ const generateChart = (data) => { ...@@ -34,7 +34,10 @@ const generateChart = (data) => {
let marginLeft = Number(ret.margin_left) || 120; let marginLeft = Number(ret.margin_left) || 120;
let legendPosition = ret.legend_position?.split(',') || [0.5, 1]; let legendPosition = ret.legend_position?.split(',') || [0.5, 1];
let colors = ret.data_color_list || ['#155C9C', '#44A79D']; let colors = ret.data_color_list || ['#155C9C', '#44A79D'];
let legendData = ['AD', 'Non_AD']; let legendData = [
{ name: 'AD', checked: true },
{ name: 'Non_AD', checked: true }
];
// 标题配置 // 标题配置
const titleConfig = { const titleConfig = {
...@@ -80,6 +83,7 @@ const generateChart = (data) => { ...@@ -80,6 +83,7 @@ const generateChart = (data) => {
let configObj = { let configObj = {
...ret, ...ret,
data,
svg, svg,
width, width,
height, height,
......
...@@ -8,7 +8,8 @@ export const setColor = (config) => { ...@@ -8,7 +8,8 @@ export const setColor = (config) => {
} else if (!!config.colors) { } else if (!!config.colors) {
colors = config.colors.split(','); colors = config.colors.split(',');
} }
return d3.scaleOrdinal(colors).domain(config.legendData); const legendData = config.legendData.map(item => item.name)
return d3.scaleOrdinal(colors).domain(legendData);
}; };
// tips // tips
...@@ -54,20 +55,22 @@ export const setLegend = (config) => { ...@@ -54,20 +55,22 @@ export const setLegend = (config) => {
g.append('g') g.append('g')
.attr('transform', `translate(0, 15)`) .attr('transform', `translate(0, 15)`)
.attr('cursor', 'pointer')
.selectAll() .selectAll()
.data(config.legendData) .data(config.legendData)
.join('g') .join('g')
.attr('class', 'legend-rect')
.attr('transform', (d, i) => `translate(${i * 90 + 20}, 0)`) .attr('transform', (d, i) => `translate(${i * 90 + 20}, 0)`)
.call((g) => .call((g) =>
g.append("path") g.append("path")
.attr("class", "dot") .attr("class", "dot-legend")
.attr("opacity", 1) .attr("opacity", 1)
.attr("stroke-opacity", 1) .attr("stroke-opacity", 1)
.attr("stroke-width", 2) .attr("stroke-width", 2)
.attr("stroke", (d) => config.color(d)) .attr("stroke", (d) => config.color(d.name))
.attr("fill", 'transparent') .attr("fill", 'transparent')
.attr("fill-opacity", 1) .attr("fill-opacity", 1)
.attr("d", (d) => setSymbol(d))) .attr("d", (d) => setSymbol(d.name)))
.call((g) => .call((g) =>
g g
.append('text') .append('text')
...@@ -75,8 +78,10 @@ export const setLegend = (config) => { ...@@ -75,8 +78,10 @@ export const setLegend = (config) => {
.attr('y', 0) .attr('y', 0)
.attr('dy', '0.3em') .attr('dy', '0.3em')
.style('font', '13px sans-serif') .style('font', '13px sans-serif')
.text((d) => d) .text((d) => d.name)
); );
legendActive(config);
}; };
// scale // scale
...@@ -184,6 +189,7 @@ export const setElliptic = (config) => { ...@@ -184,6 +189,7 @@ export const setElliptic = (config) => {
rects rects
.append('ellipse') .append('ellipse')
.attr('class', `elliptic-${config.legendData[0].name}`)
.attr('cx', `${config.ellipticAD.cx}`) .attr('cx', `${config.ellipticAD.cx}`)
.attr('cy', `${config.ellipticAD.cy}`) .attr('cy', `${config.ellipticAD.cy}`)
.attr('rx', `${config.ellipticAD.rx}`) .attr('rx', `${config.ellipticAD.rx}`)
...@@ -195,6 +201,7 @@ export const setElliptic = (config) => { ...@@ -195,6 +201,7 @@ export const setElliptic = (config) => {
rects rects
.append('ellipse') .append('ellipse')
.attr('class', `elliptic-${config.legendData[1].name}`)
.attr('cx', `${config.ellipticNon_AD.cx}`) .attr('cx', `${config.ellipticNon_AD.cx}`)
.attr('cy', `${config.ellipticNon_AD.cy}`) .attr('cy', `${config.ellipticNon_AD.cy}`)
.attr('rx', `${config.ellipticNon_AD.rx}`) .attr('rx', `${config.ellipticNon_AD.rx}`)
...@@ -212,7 +219,7 @@ export const setPoint = (config, data) => { ...@@ -212,7 +219,7 @@ export const setPoint = (config, data) => {
.selectAll("path") .selectAll("path")
.data(data) .data(data)
.join("path") .join("path")
.attr("class", "dot") .attr("class", d => `dot-${d.name}`)
.attr("opacity", 1) .attr("opacity", 1)
.attr("stroke-opacity", 1) .attr("stroke-opacity", 1)
.attr("stroke-width", 2) .attr("stroke-width", 2)
...@@ -236,3 +243,23 @@ export const setLabel = (config) => { ...@@ -236,3 +243,23 @@ export const setLabel = (config) => {
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.text(`${config.titleConfig.label}`); .text(`${config.titleConfig.label}`);
}; };
// legend active
export const legendActive = (config) => {
const legend = config.svg.selectAll('.legend-rect');
legend.on('click', (e, d) => {
config.legendData = config.legendData.map(item => {
if (item.name === d.name) {
return { ...item, checked: !item.checked }
} else {
return { ...item }
}
})
const currentLegend = config.legendData.find(item => item.name == d.name);
config.svg.selectAll('.dot-legend').data(config.legendData).attr('stroke', (d) => d.checked ? config.color(d.name) : '#aaa');
config.svg.selectAll(`.dot-${currentLegend.name}`).attr('display', `${currentLegend.checked ? 'block' : 'none'}`)
config.svg.select(`.elliptic-${currentLegend.name}`).attr('display', `${currentLegend.checked ? 'block' : 'none'}`)
})
}
\ No newline at end of file
...@@ -22,7 +22,7 @@ import ClusterHeatmapSecond from '../../components/ClusterHeatmapSecond/index.vu ...@@ -22,7 +22,7 @@ import ClusterHeatmapSecond from '../../components/ClusterHeatmapSecond/index.vu
import CircularHeatmap from '../../components/CircularHeatmap/index.vue'; import CircularHeatmap from '../../components/CircularHeatmap/index.vue';
import Test from '../../components/Test/index.vue'; import Test from '../../components/Test/index.vue';
const chartCurrent = ref(0); const chartCurrent = ref(4);
const chartList = shallowRef([ const chartList = shallowRef([
{ title: '线性拟合图', value: 1, comName: LinearFitting }, { title: '线性拟合图', value: 1, comName: LinearFitting },
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论