提交 18ad5e72 authored 作者: 祖铭松's avatar 祖铭松

feat: update

上级 bff4fbe7
......@@ -29,7 +29,7 @@ const generateChart = (data) => {
const height = width;
const minSize = Math.min(width, height);
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......@@ -442,17 +442,11 @@ const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('left', '0px')
.style('top', '0px')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '80px')
.style('text-align', 'center')
.style('height', '20px')
.style('line-height', '20px')
.style('padding', '5px');
.style('padding', '10px');
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -460,7 +454,7 @@ const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 50 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`${d.data.value}`);
})
.on('mouseleave', function () {
......
......@@ -54,7 +54,7 @@ const generateChart = (chartData) => {
const heatHeight = 2 * radius * chartData.length;
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -100,15 +100,11 @@ export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '200px')
.style('text-align', 'center')
.style('height', '20px')
.style('line-height', '20px')
.style('padding', '5px');
.style('padding', '10px');
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -116,7 +112,7 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 50 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`${d}`);
})
.on('mouseleave', function () {
......
......@@ -52,7 +52,7 @@ const generateChart = () => {
const heatHeight = 2 * radius * chartData.length;
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......
......@@ -100,15 +100,11 @@ export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '200px')
.style('text-align', 'center')
.style('height', '20px')
.style('line-height', '20px')
.style('padding', '5px');
.style('padding', '10px');
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -116,7 +112,7 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 50 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`${d}`);
})
.on('mouseleave', function () {
......
......@@ -40,9 +40,9 @@ const generateChart = (data) => {
let width = Number(ret.chart_width) || 1000;
let height = Number(ret.chart_height) || 700;
let marginTop = Number(ret.margin_top) || 120;
let marginRight = Number(ret.margin_Right) || 120;
let marginBottom = Number(ret.margin_Bottom) || 60;
let marginLeft = Number(ret.margin_Left) || 120;
let marginRight = Number(ret.margin_right) || 120;
let marginBottom = Number(ret.margin_bottom) || 60;
let marginLeft = Number(ret.margin_left) || 120;
let legendPosition = ret.legend_position?.split(',') || [0, 0];
let legendData = [0.8, 0.85, 0.9, 0.95, 1];
let dendWidth = 100;
......@@ -53,7 +53,7 @@ const generateChart = (data) => {
];
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......
......@@ -44,15 +44,11 @@ export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '80px')
.style('height', '25px')
.style('line-height', '25px')
.style('text-align', 'center')
.style('padding', '5px')
.style('padding', '10px')
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -60,7 +56,7 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 55 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`${d.count}`);
})
.on('mouseleave', function () {
......
......@@ -44,7 +44,7 @@ const generateChart = () => {
let labels = ['main_cluster_id_0.4', 'celltype', 'sample_id'];
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......
......@@ -61,14 +61,11 @@ export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '200px')
.style('height', '45px')
.style('text-align', 'left')
.style('padding', '5px')
.style('padding', '10px')
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -76,7 +73,7 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 90 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`
<div>x: ${d.x}</div>
<div>y: ${d.y}</div>`);
......
......@@ -5,7 +5,6 @@
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import * as Plot from '@observablehq/plot';
// import * as d3 from 'd3';
import { chartData } from '../mock';
import PubSub from 'pubsub-js';
......
import * as d3 from 'd3';
export function linearRegression(data) {
let n = data.length, sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
for (let i = 0; i < data.length; ++i) {
const xi = data[i].x;
const yi = data[i].y;
if (!Number.isFinite(xi) || !Number.isFinite(yi)) { --n; continue; }
sumX += xi;
sumY += yi;
sumXY += xi * yi;
sumX2 += xi * xi;
}
const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
const intercept = (sumY - slope * sumX) / n;
return x => slope * x + intercept;
}
export function confidenceInterval(data, predict) {
const mean = d3.sum(data, (d) => d.x) / data.length;
let a = 0,
b = 0;
for (let i = 0; i < data.length; ++i) {
a += Math.pow(data[i].x - mean, 2);
b += Math.pow(data[i].y - predict(data[i].x), 2);
}
const sy = Math.sqrt(b / (data.length - 2));
const t = inverseT(+0.05, data.length - 2);
return function (x) {
const Y = predict(x);
const se = sy * Math.sqrt(1 / data.length + Math.pow(x - mean, 2) / a);
return { x, left: Y - t * se, right: Y + t * se };
};
}
export function normdev(p) {
if (p < 0 || p > 1) return false;
if (p == 0) return -Infinity;
if (p == 1) return Infinity;
let a0 = 3.3871328727963666080e+0,
a1 = 1.3314166789178437745e+2,
a2 = 1.9715909503065514427e+3,
a3 = 1.3731693765509461125e+4,
a4 = 4.5921953931549871457e+4,
a5 = 6.7265770927008700853e+4,
a6 = 3.3430575583588128105e+4,
a7 = 2.5090809287301226727e+3,
b1 = 4.2313330701600911252e+1,
b2 = 6.8718700749205790830e+2,
b3 = 5.3941960214247511077e+3,
b4 = 2.1213794301586595867e+4,
b5 = 3.9307895800092710610e+4,
b6 = 2.8729085735721942674e+4,
b7 = 5.2264952788528545610e+3,
c0 = 1.42343711074968357734e+0,
c1 = 4.63033784615654529590e+0,
c2 = 5.76949722146069140550e+0,
c3 = 3.64784832476320460504e+0,
c4 = 1.27045825245236838258e+0,
c5 = 2.41780725177450611770e-1,
c6 = 2.27238449892691845833e-2,
c7 = 7.74545014278341407640e-4,
d1 = 2.05319162663775882187e+0,
d2 = 1.67638483018380384940e+0,
d3 = 6.89767334985100004550e-1,
d4 = 1.48103976427480074590e-1,
d5 = 1.51986665636164571966e-2,
d6 = 5.47593808499534494600e-4,
d7 = 1.05075007164441684324e-9,
e0 = 6.65790464350110377720e+0,
e1 = 5.46378491116411436990e+0,
e2 = 1.78482653991729133580e+0,
e3 = 2.96560571828504891230e-1,
e4 = 2.65321895265761230930e-2,
e5 = 1.24266094738807843860e-3,
e6 = 2.71155556874348757815e-5,
e7 = 2.01033439929228813265e-7,
f1 = 5.99832206555887937690e-1,
f2 = 1.36929880922735805310e-1,
f3 = 1.48753612908506148525e-2,
f4 = 7.86869131145613259100e-4,
f5 = 1.84631831751005468180e-5,
f6 = 1.42151175831644588870e-7,
f7 = 2.04426310338993978564e-15;
let q = p - 0.5, r, z;
// p close to 0.5
if (Math.abs(q) <= 0.425) {
r = 0.180625 - q * q;
z = q * (((((((a7 * r + a6) * r + a5) * r + a4) * r + a3) * r + a2) * r + a1) * r + a0)
/ (((((((b7 * r + b6) * r + b5) * r + b4) * r + b3) * r + b2) * r + b1) * r + 1);
return z;
}
if (q > 0) r = 1 - p;
else r = p;
r = Math.sqrt(-Math.log(r));
// p neither close to 0.5 nor 0 or 1
if (r <= 5) {
r += -1.6;
z = (((((((c7 * r + c6) * r + c5) * r + c4) * r + c3) * r + c2) * r + c1) * r + c0)
/ (((((((d7 * r + d6) * r + d5) * r + d4) * r + d3) * r + d2) * r + d1) * r + 1);
}
// p near 0 or 1
else {
r += -5;
z = (((((((e7 * r + e6) * r + e5) * r + e4) * r + e3) * r + e2) * r + e1) * r + e0)
/ (((((((f7 * r + f6) * r + f5) * r + f4) * r + f3) * r + f2) * r + f1) * r + 1);
}
if (q < 0.0) z = -z;
return z;
}
export function inverseT(p, df) {
const { sin, cos, sqrt, pow, exp, PI } = Math;
let a, b, c, d, t, x, y;
if (df == 1) return cos(p * PI / 2) / sin(p * PI / 2);
if (df == 2) return sqrt(2 / (p * (2 - p)) - 2);
a = 1 / (df - 0.5);
b = 48 / (a * a);
c = ((20700 * a / b - 98) * a - 16) * a + 96.36;
d = ((94.5 / (b + c) - 3) / b + 1) * sqrt(a * PI * 0.5) * df;
x = d * p;
y = pow(x, 2 / df);
if (y > 0.05 + a) {
// The procedure normdev(p) is assumed to return a negative normal
// deviate at the lower tail probability level p, e.g. -2.32 for p = 0.01.
x = normdev(p / 2);
y = x * x;
if (df < 5) c = c + 0.3 * (df - 4.5) * (x + 0.6);
c = (((0.05 * d * x - 5) * x - 7) * x - 2) * x + b + c;
y = (((((0.4 * y + 6.3) * y + 36) * y + 94.5) / c - y - 3) / b + 1) * x;
y = a * y * y;
if (y > 0.002) y = exp(y) - 1;
else y = 0.5 * y * y + y;
}
else {
y = ((1 / (((df + 6) / (df * y) - 0.089 * d - 0.822) * (df + 2) * 3) + 0.5 / (df + 4)) * y - 1) *
(df + 1) / (df + 2) + 1 / y;
}
return sqrt(df * y);
}
\ No newline at end of file
......@@ -38,7 +38,7 @@ const generateChart = (data) => {
let legendData = ['Cancer', 'Non-cance'];
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......
......@@ -60,14 +60,11 @@ export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '200px')
.style('height', '65px')
.style('text-align', 'left')
.style('padding', '5px')
.style('padding', '10px')
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -75,7 +72,7 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 90 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`
<div>${d.group}</div>
<div>x: ${d.x}</div>
......
<template>
<div ref="chartRef" class="chart-box">
<div class="tip"></div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { chartMockData } from '../mock.js';
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
import PubSub from 'pubsub-js';
import { setTips, setColor, setLegend, setScale, setAxis, setPoint, setLabel, setElliptic } from '../utils/index';
const chartRef = ref(null);
// 配置项数据
const options = ref({});
// 图表实例
const svgInstance = ref(null);
// pubsub实例
const pubSubInstance = ref(null);
// 生成图表
const generateChart = (data) => {
const ret = options.value;
let width = Number(ret.chart_width) || 900;
let height = Number(ret.chart_height) || 700;
let marginTop = Number(ret.margin_top) || 120;
let marginRight = Number(ret.margin_right) || 120;
let marginBottom = Number(ret.margin_bottom) || 120;
let marginLeft = Number(ret.margin_left) || 120;
let legendPosition = ret.legend_position?.split(',') || [1, 0];
let colors = ret.data_color_list || ['#FF0000', '#0000FF'];
let legendData = ['M', 'F'];
// 标题配置
const titleConfig = {
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
fontFamily: ret.title_font_family || 'Arial',
fontWeight: ret.title_font_weight ? 'bold' : 'normal'
};
// 大椭圆
let ellipticOne = {
rx: (width - marginLeft - marginRight) / 2 - 30,
ry: (height - marginTop - marginBottom) / 2 - 70,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 60,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 60
};
// 椭圆 M
let ellipticM = {
rx: 120,
ry: 90,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 50,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 90,
rotate: 10,
stroke: colors[0]
};
// 椭圆 F
let ellipticF = {
rx: 120,
ry: 100,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 150,
cy: (marginTop + height - marginTop - marginBottom) / 2,
rotate: 20,
stroke: colors[1]
};
const svg = d3.create('svg').attr('width', width).attr('height', height);
let configObj = {
...ret,
svg,
width,
height,
marginTop,
marginRight,
marginBottom,
marginLeft,
titleConfig,
colors,
legendData,
legendPosition,
ellipticOne,
ellipticM,
ellipticF
};
setChart(configObj, data);
svgInstance.value = svg.node();
// Append the SVG element.
chartRef.value.appendChild(svgInstance.value);
};
const setChart = (config, data) => {
const color = setColor(config);
const { x, y } = setScale(config, data);
let configObj = {
...config,
color,
x,
y
};
// elliptic
setElliptic(configObj);
// rects
const points = setPoint(configObj, data);
// tips
setTips(points);
// axis
setAxis(configObj);
// legend
setLegend(configObj);
// label
setLabel(configObj);
};
onMounted(() => {
const chartData = chartMockData;
pubSubInstance.value = PubSub.subscribe('options', (m, data) => {
options.value = data;
chartRef.value.removeChild(svgInstance.value);
generateChart(chartData);
});
generateChart(chartData);
});
onUnmounted(() => {
PubSub.unsubscribe(pubSubInstance.value);
});
</script>
<style scoped>
.chart-box {
position: relative;
}
</style>
<template>
<div class="form-container">
<h3 class="type content">画布</h3>
<div class="form-item">
<span>宽:</span>
<input type="text" v-model="dynamic_parameter.chart_width" />
</div>
<div class="form-item">
<span>高:</span>
<input type="text" v-model="dynamic_parameter.chart_height" />
</div>
<div class="form-item">
<span>上边距:</span>
<input type="text" v-model="dynamic_parameter.margin_top" />
</div>
<div class="form-item">
<span>右边距:</span>
<input type="text" v-model="dynamic_parameter.margin_right" />
</div>
<div class="form-item">
<span>下边距:</span>
<input type="text" v-model="dynamic_parameter.margin_bottom" />
</div>
<div class="form-item">
<span>左边距:</span>
<input type="text" v-model="dynamic_parameter.margin_left" />
</div>
<h3 class="type content">文本</h3>
<div class="form-item">
<span>标题:</span>
<input type="text" v-model="dynamic_parameter.title" />
</div>
<div class="form-item">
<span>字体:</span>
<input type="text" v-model="dynamic_parameter.title_font_family" />
</div>
<div class="form-item">
<span>字号:</span>
<input type="text" v-model="dynamic_parameter.title_font_size" />
</div>
<div class="form-item">
<span>字体颜色:</span>
<input type="text" v-model="dynamic_parameter.title_font_color" />
</div>
<div class="form-item">
<span>字体加粗:</span>
<input type="checkbox" v-model="dynamic_parameter.title_font_weight" />
</div>
<div class="form-item">
<span>斜体:</span>
<input type="checkbox" v-model="dynamic_parameter.title_font_style" />
</div>
<h3 class="type content">X轴配置</h3>
<div class="form-item">
<span>显示坐标轴:</span>
<input type="checkbox" v-model="dynamic_parameter.show_x_axis" />
</div>
<div class="form-item">
<span>显示刻度线:</span>
<input type="checkbox" v-model="dynamic_parameter.show_x_tickMarks" />
</div>
<div class="form-item">
<span>刻度线颜色:</span>
<input type="text" v-model="dynamic_parameter.x_tickMarks_color" />
</div>
<div class="form-item">
<span>刻度线长度:</span>
<input type="text" v-model="dynamic_parameter.x_tickMarks_length" />
</div>
<div class="form-item">
<span>字体:</span>
<input type="text" v-model="dynamic_parameter.xtitle_font_family" />
</div>
<div class="form-item">
<span>字号:</span>
<input type="text" v-model="dynamic_parameter.xtitle_font_size" />
</div>
<div class="form-item">
<span>字体颜色:</span>
<input type="text" v-model="dynamic_parameter.xtitle_font_color" />
</div>
<div class="form-item">
<span>字体加粗:</span>
<input type="checkbox" v-model="dynamic_parameter.xtitle_font_weight" />
</div>
<div class="form-item">
<span>斜体:</span>
<input type="checkbox" v-model="dynamic_parameter.xtitle_font_style" />
</div>
<div class="form-item">
<span>标题展示:</span>
<input type="checkbox" v-model="dynamic_parameter.show_x_title" />
</div>
<div class="form-item">
<span>标题:</span>
<input type="text" v-model="dynamic_parameter.x_title" />
</div>
<h3 class="type content">Y轴配置</h3>
<div class="form-item">
<span>显示坐标轴:</span>
<input type="checkbox" v-model="dynamic_parameter.show_y_axis" />
</div>
<div class="form-item">
<span>显示刻度线:</span>
<input type="checkbox" v-model="dynamic_parameter.show_y_tickMarks" />
</div>
<div class="form-item">
<span>刻度线颜色:</span>
<input type="text" v-model="dynamic_parameter.y_tickMarks_color" />
</div>
<div class="form-item">
<span>刻度线长度:</span>
<input type="text" v-model="dynamic_parameter.y_tickMarks_length" />
</div>
<div class="form-item">
<span>字体:</span>
<input type="text" v-model="dynamic_parameter.ytitle_font_family" />
</div>
<div class="form-item">
<span>字号:</span>
<input type="text" v-model="dynamic_parameter.ytitle_font_size" />
</div>
<div class="form-item">
<span>字体颜色:</span>
<input type="text" v-model="dynamic_parameter.ytitle_font_color" />
</div>
<div class="form-item">
<span>字体加粗:</span>
<input type="checkbox" v-model="dynamic_parameter.ytitle_font_weight" />
</div>
<div class="form-item">
<span>斜体:</span>
<input type="checkbox" v-model="dynamic_parameter.ytitle_font_style" />
</div>
<div class="form-item">
<span>标题展示:</span>
<input type="checkbox" v-model="dynamic_parameter.show_y_title" />
</div>
<div class="form-item">
<span>标题:</span>
<input type="text" v-model="dynamic_parameter.y_title" />
</div>
<h3 class="type content">图例</h3>
<div class="form-item">
<span>显示图例:</span>
<input type="checkbox" v-model="dynamic_parameter.show_legend" />
</div>
<div class="form-item">
<span>图例位置:</span>
<input type="text" v-model="dynamic_parameter.legend_position" />
</div>
<div class="btn">
<button @click="submit">提交</button>
</div>
</div>
</template>
<script setup>
import { reactive, onMounted } from 'vue';
import PubSub from 'pubsub-js';
//动态图参数,固定参数
const dynamic_parameter = reactive({
//长宽间距
chart_width: 900,
chart_height: 700,
margin_top: 120,
margin_right: 120,
margin_bottom: 120,
margin_left: 120,
//标题配置
title: 'Scores(OPLS-DA)',
title_font_family: 'Arial',
title_font_weight: true,
title_font_size: 20,
title_font_color: '#333333',
title_font_style: false,
//横轴标题
xtitle_font_family: 'Arial',
xtitle_font_weight: false,
xtitle_font_style: false,
xtitle_font_size: 14,
xtitle_font_color: '#333333',
//纵轴标题
ytitle_font_family: 'Arial',
ytitle_font_weight: false,
ytitle_font_style: false,
ytitle_font_size: 14,
ytitle_font_color: '#333333',
//颜色设置
data_color_list: ['#FF0000', '#0000FF'],
point_radius: 5, // 散点图半径
shadow_opacity: 0.5, // 阴影透明度 0~1
//图例
show_legend: true,
legend_position: '1,0',
//坐标轴
show_x_axis: true,
show_x_line: true,
show_x_tickMarks: true,
show_x_gridLine: false,
show_x_title: true,
x_title: 't1(5%)',
x_tickMarks_color: '#333333',
x_tickMarks_length: '5',
show_y_axis: true,
show_y_line: true,
show_y_tickMarks: true,
show_y_gridLine: false,
show_y_title: true,
y_title: 'to1',
y_tickMarks_color: '#333333',
y_tickMarks_length: '5',
//节点相关的参数,可能还会有更多
node_id: null, //节点id
node_color: null, //节点颜色
is_delect_node: false, //是否删除节点
node_search_name: null, //节点名称搜索
node_search_color: '#FF0404', //节点搜索后的颜色
node_edit_name: null, //修改节点名称
node_height: 100, //节点大小
path_id: null
});
const submit = () => {
PubSub.publish('options', dynamic_parameter);
};
onMounted(() => {
submit();
});
</script>
<style scoped>
.form-item span {
display: inline-block;
width: 120px;
text-align: left;
}
.btn {
width: 100%;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<template>
<div class="chart-container">
<Chart />
<Config />
</div>
</template>
<script setup>
import Chart from './components/chart.vue';
import Config from './components/config.vue';
</script>
<style scoped>
.chart-container {
display: flex;
}
</style>
差异被折叠。
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
// color config
export const setColor = (config) => {
let colors = [];
if (Array.isArray(config.colors)) {
colors = !!config.colors.length ? config.colors : colors;
} else if (!!config.colors) {
colors = config.colors.split(',');
}
return d3.scaleOrdinal(colors).domain(config.legendData);
};
// tips
export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('padding', '10px')
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
})
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`
<div>${d.group}</div>
<div>p1: ${d.p1}</div>
<div>p2: ${d.p2}</div>
`);
})
.on('mouseleave', function () {
tips.style('visibility', 'hidden');
});
};
// legend
export const setLegend = (config) => {
let legendX = config.legendPosition[0] == 0 ? config.marginLeft + 20 : config.legendPosition[0] == 0.5 ? config.width / 2 : config.width - config.marginLeft - 30;
let legendY = config.legendPosition[1] == 0 ? config.marginTop + 20 : config.legendPosition[1] == 0.5 ? config.height / 2 - 50 : config.height - config.marginTop - 110;
config.svg.append('g')
.attr('transform', `translate(${legendX}, ${legendY})`)
.selectAll()
.data(config.legendData)
.join('g')
.attr('transform', (d, i) => `translate(0, ${i * 50})`)
.call((g) => g.append('rect').attr('width', 20).attr('height', 50).attr('fill', d => config.color(d)))
.call((g) =>
g
.append('text')
.attr('x', -10)
.attr('y', 25)
.attr('dy', '0.3em')
.style('font', '10px sans-serif')
.style('text-anchor', 'middle')
.text((d) => d)
);
};
// scale
export const setScale = (config, data) => {
const xMax = d3.max(data, (d) => d.p1)
const xMin = d3.min(data, (d) => d.p1)
const yMax = d3.min(data, (d) => d.p2)
const yMin = d3.min(data, (d) => d.p2)
const xDomain = (Math.abs(xMax) >= Math.abs(xMin) ? Math.abs(xMax) : Math.abs(xMin)) + 6
const yDomain = (Math.abs(yMax) >= Math.abs(yMin) ? Math.abs(yMax) : Math.abs(yMin)) + 5
const x = d3
.scaleLinear()
.domain([-xDomain, xDomain])
.range([config.marginLeft, config.width - config.marginRight])
const y = d3
.scaleLinear()
.domain([-yDomain, yDomain])
.range([config.height - config.marginBottom, config.marginTop])
return { x, y }
}
// axis
export const setAxis = (config) => {
config.show_x_axis && config.svg.append('g')
.attr('transform', `translate(0, ${config.height - config.marginBottom})`)
.style('font', `${config.xtitle_font_size}px ${config.xtitle_font_family}`)
.style('color', `${config.xtitle_font_color}`)
.style('font-weight', `${config.xtitle_font_weight ? 'bold' : 'normal'}`)
.style('font-style', `${config.xtitle_font_style ? 'oblique' : 'normal'}`)
.call(d3.axisBottom(config.x).tickSize(Number(config.show_x_tickMarks ? config.x_tickMarks_length : 0)))
.call(g => g.selectAll("line").clone()
.attr("stroke", d => d == 0 ? 'black' : '#aaa')
.attr("y2", -(config.height - config.marginBottom - config.marginTop))
)
.call((g) => g.selectAll('.domain').remove())
.selectAll('text')
.style('text-anchor', 'middle');
config.show_x_title && config.svg.append('g')
.attr('transform', `translate(${config.width / 2}, ${config.height - config.marginBottom + 50})`)
.append('text')
.style('text-anchor', 'middle')
.text(config.x_title)
config.show_y_axis && config.svg.append('g')
.attr('transform', `translate(${config.marginLeft}, 0)`)
.style('font', `${config.ytitle_font_size}px ${config.ytitle_font_family}`)
.style('color', `${config.ytitle_font_color}`)
.style('font-weight', `${config.ytitle_font_weight ? 'bold' : 'normal'}`)
.style('font-style', `${config.ytitle_font_style ? 'oblique' : 'normal'}`)
.call(d3.axisLeft(config.y).ticks(null, 's'))
.call(g => g.selectAll("line").clone()
.attr("stroke", d => d == 0 ? 'black' : '#aaa')
.attr("x2", config.width - config.marginLeft - config.marginRight))
.call((g) => g.selectAll('.domain').remove())
config.show_y_title && config.svg.append('g')
.attr('transform', `translate(${config.marginLeft - 50}, ${config.height / 2})`)
.append('text')
.style('text-anchor', 'middle')
.attr('transform', `rotate(-90)`)
.text(config.y_title)
}
// elliptic
export const setElliptic = (config) => {
let rects = config.svg
.append('g')
.attr('width', config.width - config.marginLeft - config.marginRight)
.attr('height', config.height - config.marginTop - config.marginBottom);
rects
.append('rect')
.attr('x', `${config.marginLeft}`)
.attr('y', `${config.marginTop}`)
.attr('width', `${config.width - config.marginLeft - config.marginRight}`)
.attr('height', `${config.height - config.marginTop - config.marginBottom}`)
.attr('stroke', '#000000')
.attr('stroke-width', 2)
.attr('fill', 'white');
rects
.append('ellipse')
.attr('cx', `${config.ellipticOne.cx}`)
.attr('cy', `${config.ellipticOne.cy}`)
.attr('rx', `${config.ellipticOne.rx}`)
.attr('ry', `${config.ellipticOne.ry}`)
.attr('stroke', 'black')
.attr('fill', 'transparent');
rects
.append('ellipse')
.attr('cx', `${config.ellipticM.cx}`)
.attr('cy', `${config.ellipticM.cy}`)
.attr('rx', `${config.ellipticM.rx}`)
.attr('ry', `${config.ellipticM.ry}`)
.attr('transform-origin', 'center')
.attr('fill', 'transparent')
.attr('stroke', config.ellipticM.stroke)
.attr('transform', `rotate(${config.ellipticM.rotate})`)
rects
.append('ellipse')
.attr('cx', `${config.ellipticF.cx}`)
.attr('cy', `${config.ellipticF.cy}`)
.attr('rx', `${config.ellipticF.rx}`)
.attr('ry', `${config.ellipticF.ry}`)
.attr('fill', 'transparent')
.attr('transform-origin', 'center')
.attr('stroke', config.ellipticF.stroke)
.attr('transform', `rotate(${config.ellipticF.rotate})`)
}
// point
export const setPoint = (config, data) => {
return config.svg
.append("g")
.selectAll("text")
.data(data)
.join("text")
.attr("dy", "0.35em")
.attr("x", d => config.x(d.p1) + 7)
.attr("y", d => config.y(d.p2))
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr('cursor', 'default')
.attr('fill', d => config.color(d.group))
.text(d => d.sample)
}
// title
export const setLabel = (config) => {
config.svg.append('text')
.attr('x', config.width / 2)
.attr('y', 30)
.attr('fill', config.titleConfig.color)
.attr('font-size', `${config.titleConfig.fontSize}px`)
.attr('font-family', `${config.titleConfig.fontFamily}`)
.attr('font-style', `${config.titleConfig.fontStyle}`)
.attr('font-weight', `${config.titleConfig.fontWeight}`)
.style('text-anchor', 'middle')
.text(`${config.titleConfig.label}`);
};
......@@ -29,16 +29,16 @@ const generateChart = (data) => {
let width = Number(ret.chart_width) || 700;
let height = Number(ret.chart_height) || 800;
let marginTop = Number(ret.margin_top) || 120;
let marginRight = Number(ret.margin_Right) || 120;
let marginBottom = Number(ret.margin_Bottom) || 120;
let marginLeft = Number(ret.margin_Left) || 120;
let marginRight = Number(ret.margin_right) || 120;
let marginBottom = Number(ret.margin_bottom) || 120;
let marginLeft = Number(ret.margin_left) || 120;
let legendPosition = ret.legend_position?.split(',') || [0.5, 1];
let colors = ret.data_color_list || ['#155C9C', '#44A79D'];
let legendData = ['AD', 'Non_AD'];
// 标题配置
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......@@ -56,8 +56,8 @@ const generateChart = (data) => {
// 椭圆 AD
let ellipticAD = {
rx: 80,
ry: 350,
rx: 70,
ry: 280,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 60,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 60,
rotate: 10,
......@@ -67,10 +67,10 @@ const generateChart = (data) => {
// 椭圆 Non_AD
let ellipticNon_AD = {
rx: 350,
ry: 60,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 60,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 20,
rx: 240,
ry: 50,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 40,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 10,
rotate: 20,
fill: colors[1],
fillOpacity: 0.2
......
......@@ -16,14 +16,11 @@ export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '120px')
.style('height', '65px')
.style('text-align', 'left')
.style('padding', '5px 10px')
.style('padding', '10px')
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -31,7 +28,7 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 55 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`
<div>${d.name}</div>
<div>x: ${d.PC1}</div>
......@@ -117,7 +114,7 @@ export const setAxis = (config) => {
.style('font-style', `${config.xtitle_font_style ? 'oblique' : 'normal'}`)
.call(d3.axisBottom(config.x).tickSize(Number(config.show_x_tickMarks ? config.x_tickMarks_length : 0)))
.call(g => g.selectAll("line").clone()
.attr("display", d => d == 0 ? 'block' : 'none')
.attr("display", d => d == 0 ? 'black' : 'none')
.attr("stroke-dasharray", '3')
.attr("y2", -(config.height - config.marginBottom - config.marginTop))
)
......@@ -139,7 +136,7 @@ export const setAxis = (config) => {
.style('font-style', `${config.ytitle_font_style ? 'oblique' : 'normal'}`)
.call(d3.axisLeft(config.y).tickSize(Number(config.show_y_tickMarks ? config.y_tickMarks_length : 0)))
.call(g => g.selectAll("line").clone()
.attr("display", d => d == 0 ? 'block' : 'none')
.attr("display", d => d == 0 ? 'black' : 'none')
.attr("stroke-dasharray", '3')
.attr("x2", config.width - config.marginLeft - config.marginRight))
.call((g) => g.selectAll('.domain').remove())
......@@ -162,7 +159,7 @@ export const setSymbol = (type) => {
export const setElliptic = (config) => {
let rects = config.svg
.append('g')
.attr('max-width', config.width - config.marginLeft - config.marginRight)
.attr('width', config.width - config.marginLeft - config.marginRight)
.attr('height', config.height - config.marginTop - config.marginBottom);
rects
......
......@@ -19,19 +19,19 @@ const options = ref({});
const generateChart = (data) => {
const ret = options.value;
let width = 700;
let height = 800;
let width = 900;
let height = 700;
let marginTop = 120;
let marginRight = 120;
let marginBottom = 120;
let marginLeft = 120;
let legendData = ['AD', 'Non_AD'];
let legendPosition = [0.5, 1];
let colors = ['#155C9C', '#44A79D'];
let legendData = ['M', 'F'];
let legendPosition = [1, 0];
let colors = ['#FF0000', '#0000FF'];
// 标题配置
const titleConfig = {
label: !!ret.title ? ret.title : null,
label: !!ret.title ? ret.title : '',
color: ret.title_font_color || '#333333',
fontSize: ret.title_font_size || 20,
fontStyle: ret.title_font_style ? 'oblique' : 'normal',
......@@ -41,27 +41,27 @@ const generateChart = (data) => {
// 大椭圆
let ellipticOne = {
rx: (width - marginLeft - marginRight) / 2 - 20,
ry: (height - marginTop - marginBottom) / 2 - 20,
rx: (width - marginLeft - marginRight) / 2 - 30,
ry: (height - marginTop - marginBottom) / 2 - 70,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 60,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 60
};
// 椭圆 AD
let ellipticAD = {
rx: 80,
ry: 350,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 60,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 60,
// 椭圆 M
let ellipticM = {
rx: 120,
ry: 90,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 50,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 90,
rotate: 10
};
// 椭圆 Non_AD
let ellipticNon_AD = {
rx: 350,
ry: 60,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 60,
cy: (marginTop + height - marginTop - marginBottom) / 2 + 20,
// 椭圆 F
let ellipticF = {
rx: 120,
ry: 100,
cx: (marginLeft + width - marginLeft - marginRight) / 2 + 150,
cy: (marginTop + height - marginTop - marginBottom) / 2,
rotate: 20
};
......@@ -80,8 +80,8 @@ const generateChart = (data) => {
legendData,
legendPosition,
ellipticOne,
ellipticAD,
ellipticNon_AD
ellipticM,
ellipticF
};
setChart(configObj, data);
......@@ -130,8 +130,4 @@ onMounted(() => {
.chart-box {
position: relative;
}
.main {
width: 500px;
overflow: hidden;
}
</style>
......@@ -2,7 +2,7 @@ import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
// color config
export const setColor = (config) => {
let colors = ['#2265A1', '#44A79D'];
let colors = [];
if (Array.isArray(config.colors)) {
colors = !!config.colors.length ? config.colors : colors;
} else if (!!config.colors) {
......@@ -16,14 +16,12 @@ export const setTips = (rect) => {
const tips = d3
.select('.tip')
.style('visibility', 'hidden')
.style('position', 'relative')
.style('position', 'absolute')
.style('background-color', 'rgba(0, 0, 0, .8)')
.style('color', '#fff')
.style('border-radius', '5px')
.style('width', '120px')
.style('height', '65px')
.style('text-align', 'left')
.style('padding', '5px 10px')
.style('padding', '10px')
rect.on('mouseover', (event, d) => {
tips.style('visibility', 'visible');
......@@ -31,11 +29,11 @@ export const setTips = (rect) => {
.on('mousemove', function (event, d) {
tips.style('visibility', 'visible')
.style('left', event.offsetX + 15 + 'px')
.style('top', event.offsetY + 55 + 'px')
.style('top', event.offsetY + 15 + 'px')
.html(`
<div>${d.name}</div>
<div>x: ${d.x}</div>
<div>y: ${d.y}</div>
<div>${d.group}</div>
<div>p1: ${d.p1}</div>
<div>p2: ${d.p2}</div>
`);
})
.on('mouseleave', function () {
......@@ -46,38 +44,24 @@ export const setTips = (rect) => {
// legend
export const setLegend = (config) => {
const g = config.svg.append('g')
.attr('transform', `translate(${(config.width - 210) * config.legendPosition[0]}, ${(config.height - 35) * config.legendPosition[1]})`)
let legendX = config.legendPosition[0] == 0 ? config.marginLeft + 20 : config.legendPosition[0] == 0.5 ? config.width / 2 : config.width - config.marginLeft - 30;
let legendY = config.legendPosition[1] == 0 ? config.marginTop + 20 : config.legendPosition[1] == 0.5 ? config.height / 2 - 50 : config.height - config.marginTop - 110;
g.append('rect').attr('width', 200)
.attr('height', 30)
.attr('stroke', 'black')
.attr("stroke-width", 2)
.attr('fill', 'transparent')
g.append('g')
.attr('transform', `translate(0, 15)`)
config.svg.append('g')
.attr('transform', `translate(${legendX}, ${legendY})`)
.selectAll()
.data(config.legendData)
.join('g')
.attr('transform', (d, i) => `translate(${i * 90 + 20}, 0)`)
.call((g) =>
g.append("path")
.attr("class", "dot")
.attr("opacity", 1)
.attr("stroke-opacity", 1)
.attr("stroke-width", 2)
.attr("stroke", (d) => config.color(d))
.attr("fill", 'transparent')
.attr("fill-opacity", 1)
.attr("d", (d) => setSymbol(d)))
.attr('transform', (d, i) => `translate(0, ${i * 50})`)
.call((g) => g.append('rect').attr('width', 20).attr('height', 50).attr('fill', d => config.color(d)))
.call((g) =>
g
.append('text')
.attr('x', 15)
.attr('y', 0)
.attr('x', -10)
.attr('y', 25)
.attr('dy', '0.3em')
.style('font', '13px sans-serif')
.style('font', '10px sans-serif')
.style('text-anchor', 'middle')
.text((d) => d)
);
};
......@@ -85,13 +69,13 @@ export const setLegend = (config) => {
// scale
export const setScale = (config, data) => {
const xMax = d3.max(data, (d) => d.x)
const xMin = d3.min(data, (d) => d.x)
const yMax = d3.min(data, (d) => d.y)
const yMin = d3.min(data, (d) => d.y)
const xMax = d3.max(data, (d) => d.p1)
const xMin = d3.min(data, (d) => d.p1)
const yMax = d3.min(data, (d) => d.p2)
const yMin = d3.min(data, (d) => d.p2)
const xDomain = (Math.abs(xMax) >= Math.abs(xMin) ? Math.abs(xMax) : Math.abs(xMin)) + 10
const yDomain = (Math.abs(yMax) >= Math.abs(yMin) ? Math.abs(yMax) : Math.abs(yMin)) + 10
const xDomain = (Math.abs(xMax) >= Math.abs(xMin) ? Math.abs(xMax) : Math.abs(xMin)) + 6
const yDomain = (Math.abs(yMax) >= Math.abs(yMin) ? Math.abs(yMax) : Math.abs(yMin)) + 5
const x = d3
......@@ -114,8 +98,7 @@ export const setAxis = (config) => {
.style('font', '12px verdana')
.call(d3.axisBottom(config.x).tickSizeOuter(0))
.call(g => g.selectAll("line").clone()
.attr("display", d => d == 0 ? 'block' : 'none')
.attr("stroke-dasharray", '3')
.attr("stroke", d => d == 0 ? 'black' : '#aaa')
.attr("y2", -(config.height - config.marginBottom - config.marginTop))
)
.call((g) => g.selectAll('.domain').remove())
......@@ -133,8 +116,7 @@ export const setAxis = (config) => {
.style('font', '12px verdana')
.call(d3.axisLeft(config.y).ticks(null, 's'))
.call(g => g.selectAll("line").clone()
.attr("display", d => d == 0 ? 'block' : 'none')
.attr("stroke-dasharray", '3')
.attr("stroke", d => d == 0 ? 'black' : '#aaa')
.attr("x2", config.width - config.marginLeft - config.marginRight))
.call((g) => g.selectAll('.domain').remove())
config.svg.append('g')
......@@ -174,49 +156,48 @@ export const setElliptic = (config) => {
.attr('cy', `${config.ellipticOne.cy}`)
.attr('rx', `${config.ellipticOne.rx}`)
.attr('ry', `${config.ellipticOne.ry}`)
.attr('stroke', '#ADADAD')
.attr('stroke-width', 3)
.attr('stroke', 'black')
.attr('stroke-width', 1)
.attr('fill', 'transparent');
rects
.append('ellipse')
.attr('cx', `${config.ellipticAD.cx}`)
.attr('cy', `${config.ellipticAD.cy}`)
.attr('rx', `${config.ellipticAD.rx}`)
.attr('ry', `${config.ellipticAD.ry}`)
.attr('cx', `${config.ellipticM.cx}`)
.attr('cy', `${config.ellipticM.cy}`)
.attr('rx', `${config.ellipticM.rx}`)
.attr('ry', `${config.ellipticM.ry}`)
.attr('transform-origin', 'center')
.attr('transform', `rotate(${config.ellipticAD.rotate})`)
.attr('fill', config.colors[0])
.attr('fill-opacity', 0.2);
.attr('transform', `rotate(${config.ellipticM.rotate})`)
.attr('stroke', config.colors[0])
.attr('fill', 'transparent')
rects
.append('ellipse')
.attr('cx', `${config.ellipticNon_AD.cx}`)
.attr('cy', `${config.ellipticNon_AD.cy}`)
.attr('rx', `${config.ellipticNon_AD.rx}`)
.attr('ry', `${config.ellipticNon_AD.ry}`)
.attr('cx', `${config.ellipticF.cx}`)
.attr('cy', `${config.ellipticF.cy}`)
.attr('rx', `${config.ellipticF.rx}`)
.attr('ry', `${config.ellipticF.ry}`)
.attr('transform-origin', 'center')
.attr('transform', `rotate(${config.ellipticNon_AD.rotate})`)
.attr('fill', config.colors[1])
.attr('fill-opacity', 0.2);
.attr('transform', `rotate(${config.ellipticF.rotate})`)
.attr('stroke', config.colors[1])
.attr('fill', 'transparent')
}
// point
export const setPoint = (config, data) => {
return config.svg
.append("g")
.selectAll("path")
.selectAll("text")
.data(data)
.join("path")
.attr("class", "dot")
.attr("opacity", 1)
.attr("stroke-opacity", 1)
.attr("stroke-width", 2)
.attr("stroke", (d) => config.color(d.name))
.attr("fill", 'transparent')
.attr("fill-opacity", 1)
.attr("d", (d) => setSymbol(d.name))
.attr("transform", d => `translate(${config.x(d.x)}, ${config.y(d.y)})`)
.join("text")
.attr("dy", "0.35em")
.attr("x", d => config.x(d.p1) + 7)
.attr("y", d => config.y(d.p2))
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr('cursor', 'default')
.attr('fill', d => config.color(d.group))
.text(d => d.sample)
}
// title
......
......@@ -12,6 +12,7 @@
import { ref, shallowRef } from 'vue';
import LinearFitting from '../../components/LinearFitting/index.vue';
import PcaAnalysis from '../../components/PcaAnalysis/index.vue';
import OplsDa from '../../components/OplsDa/index.vue';
import MsDimplot from '../../components/MsDimplot/index.vue';
import FeaturePlot from '../../components/FeaturePlot/index.vue';
import BeeColonyDiagram from '../../components/BeeColonyDiagram/index.vue';
......@@ -26,13 +27,14 @@ const chartCurrent = ref(0);
const chartList = shallowRef([
{ title: '线性拟合图', value: 1, comName: LinearFitting },
{ title: 'pca分析图', value: 2, comName: PcaAnalysis },
{ title: 'ms-dimplot', value: 3, comName: MsDimplot },
{ title: 'Feature Plot', value: 4, comName: FeaturePlot },
{ title: '蜂群图', value: 5, comName: BeeColonyDiagram },
{ title: '相关性分析', value: 6, comName: CorrelationAnalysis },
{ title: '聚类热图', value: 7, comName: ClusterHeatmap },
{ title: '聚类热图-2', value: 8, comName: ClusterHeatmapSecond },
{ title: '环状热图', value: 9, comName: CircularHeatmap },
{ title: 'opls-da', value: 3, comName: OplsDa },
{ title: 'ms-dimplot', value: 4, comName: MsDimplot },
{ title: 'Feature Plot', value: 5, comName: FeaturePlot },
{ title: '蜂群图', value: 6, comName: BeeColonyDiagram },
{ title: '相关性分析', value: 7, comName: CorrelationAnalysis },
{ title: '聚类热图', value: 8, comName: ClusterHeatmap },
{ title: '聚类热图-2', value: 9, comName: ClusterHeatmapSecond },
{ title: '环状热图', value: 10, comName: CircularHeatmap },
{ title: 'test', value: 0, comName: Test }
]);
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论