forked from cxumol/html
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtricolor_venn.html
134 lines (121 loc) · 5.47 KB
/
tricolor_venn.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" /><meta charset="utf-8" />
<title>三色图生成器</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/arp242/hello-css@refs/heads/master/dist/all.min.css">
<style>
text { font-size: 16px; }
main { display: flex; }
main > section { margin: 1em; flex: 1; }
</style>
</head>
<body>
<header>
<h1>三色图生成器</h1>
<p>稳定、速度、便宜 —— 不可能三角</p>
</header>
<main>
<section>
<form>
<label for="region1">区域 1 (C - 青色):</label><input type="text" id="region1" value="稳定"><br>
<label for="region2">区域 2 (M - 品红):</label><input type="text" id="region2" value="速度"><br>
<label for="region3">区域 3 (Y - 黄色):</label><input type="text" id="region3" value="便宜"><br>
<label for="region4">区域 4 (CM - 蓝色):</label><input type="text" id="region4" value="贵"><br>
<label for="region5">区域 5 (CY - 绿色):</label><input type="text" id="region5" value="慢"><br>
<label for="region6">区域 6 (MY - 红色):</label><input type="text" id="region6" value="渣"><br>
<label for="region7">区域 7 (CMY - 黑色):</label><input type="text" id="region7" value="不可能"><br>
<label for="textColor">文字颜色:</label><input type="color" id="textColor" value="#000000"><br>
</form>
</section>
<section>
<h2>预览</h2>
<article>
<svg id="venn" width="300" height="300"></svg>
</article>
<h2>导出</h2>
<button onclick="exportSvg()">导出 SVG</button>
</section>
</main>
<script>
var getId = id => document.getElementById(id);
var svgNS = "http://www.w3.org/2000/svg";
var regions = ['region1', 'region2', 'region3', 'region4', 'region5', 'region6', 'region7'];
var colors = ['cyan', 'magenta', 'yellow', 'blue', 'lime', 'red', 'black'];
var venn = getId('venn');
var radius = 80;
var centerX = 150;
var centerY = 150;
var offset = radius * Math.sqrt(3) / 3;
var circlePositions = [
{ x: centerX - offset, y: centerY - offset }, // C
{ x: centerX + offset, y: centerY - offset }, // M
{ x: centerX, y: centerY + offset } // Y
];
function drawCircle(cx, cy, color, id) {
var circle = document.createElementNS(svgNS, 'circle');
circle.setAttribute('cx', cx);
circle.setAttribute('cy', cy);
circle.setAttribute('r', radius);
circle.setAttribute('fill', color);
circle.setAttribute('opacity', 0.5);
circle.setAttribute('id', id + 'Circle');
circle.setAttribute('style', 'mix-blend-mode: multiply;');
return circle;
}
function calculateCentroid(region) {
if (region === 'region1') return { x: circlePositions[0].x - offset / 2, y: circlePositions[0].y - offset / 4 };
if (region === 'region2') return { x: circlePositions[1].x + offset / 2, y: circlePositions[1].y - offset / 4 };
if (region === 'region3') return { x: centerX, y: circlePositions[2].y + offset / 2 };
if (region === 'region4') return { x: centerX, y: centerY - offset *1.3 };
if (region === 'region5') return { x: circlePositions[0].x*1.05, y: centerY*1.1 };
if (region === 'region6') return { x: circlePositions[1].x*0.95, y: centerY*1.1 };
if (region === 'region7') return { x: centerX, y: centerY*0.9 };
return { x: centerX, y: centerY };
}
function drawText(regionId, text, textColor) {
var centroid = calculateCentroid(regionId);
var textElem = document.createElementNS(svgNS, 'text');
textElem.setAttribute('x', centroid.x);
textElem.setAttribute('y', centroid.y);
textElem.setAttribute('text-anchor', 'middle');
textElem.setAttribute('dominant-baseline', 'middle');
textElem.textContent = text;
textElem.setAttribute('id', regionId + 'Text');
textElem.setAttribute('fill', textColor);
venn.appendChild(textElem);
return textElem
}
function updateVenn() {
venn.innerHTML = '';
var texts = regions.map(regionId => getId(regionId).value);
var textColor = getId('textColor').value;
var group = document.createElementNS(svgNS, 'g');
group.setAttribute('class', 'isolate');
group.setAttribute('style', 'isolation: isolate;');
group.appendChild(drawCircle(circlePositions[0].x, circlePositions[0].y, colors[0], 'c'));
group.appendChild(drawCircle(circlePositions[1].x, circlePositions[1].y, colors[1], 'm'));
group.appendChild(drawCircle(circlePositions[2].x, circlePositions[2].y, colors[2], 'y'));
venn.appendChild(group);
regions.forEach((regionId, index) => {
drawText(regionId, texts[index], textColor);
});
}
function exportSvg() {
var svgData = new XMLSerializer().serializeToString(venn);
var svgBlob = new Blob([svgData], { type: "image/svg+xml;charset=utf-8" });
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = "三色图.svg";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
regions.forEach(regionId => getId(regionId).oninput = updateVenn);
regions.forEach(regionId => getId(regionId).onchange = updateVenn);
getId('textColor').oninput = updateVenn;
updateVenn();
</script>
</body>
</html>