增加放大图标

This commit is contained in:
锦恢 2024-12-29 21:11:32 +08:00
parent 0bcb475812
commit 6587cd3150
25 changed files with 702 additions and 329 deletions

View File

@ -1,6 +1,6 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 4440655 */ font-family: "iconfont"; /* Project id 4797805 */
src: url('iconfont.woff2?t=1735201425292') format('woff2'); src: url('iconfont.woff2?t=1735470843861') format('woff2');
} }
.iconfont { .iconfont {
@ -11,164 +11,32 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-single-click:before { .icon-memory-chip:before {
content: "\e664"; content: "\e600";
} }
.icon-wheel-change:before { .icon-wave-square:before {
content: "\e6ad"; content: "\ebd0";
} }
.icon-double-click:before { .icon-about:before {
content: "\e6fc"; content: "\e601";
} }
.icon-i18n:before { .icon-setting:before {
content: "\e678"; content: "\e657";
} }
.icon-gou:before { .icon-collections:before {
content: "\e84b"; content: "\e689";
} }
.icon-menu:before { .icon-register:before {
content: "\e607"; content: "\e611";
} }
.icon-clear:before { .icon-brackets:before {
content: "\e619"; content: "\e613";
}
.icon-axis:before {
content: "\ed1f";
}
.icon-add-line:before {
content: "\e7b0";
}
.icon-arrow-to-previous:before {
content: "\e616";
}
.icon-arrow-to-next:before {
content: "\e615";
}
.icon-beginning:before {
content: "\e60e";
}
.icon-ending:before {
content: "\e60f";
}
.icon-line-analog:before {
content: "\e662";
}
.icon-ladder-analog:before {
content: "\e87b";
}
.icon-common-digital:before {
content: "\e606";
}
.icon-delete:before {
content: "\e684";
}
.icon-empty:before {
content: "\e617";
}
.icon-expand:before {
content: "\e658";
}
.icon-collapse:before {
content: "\e676";
}
.icon-group:before {
content: "\e70c";
}
.icon-cancel-group:before {
content: "\e65f";
}
.icon-delete-group:before {
content: "\e675";
}
.icon-choose:before {
content: "\e63b";
}
.icon-thin-arrow-right:before {
content: "\e622";
}
.icon-change-color:before {
content: "\e6fb";
}
.icon-join-group:before {
content: "\e914";
}
.icon-arrow-right:before {
content: "\eb08";
}
.icon-arrow-left:before {
content: "\eb09";
}
.icon-arrow-down:before {
content: "\eb0a";
}
.icon-arrow-up:before {
content: "\eb0b";
}
.icon-command:before {
content: "\e604";
}
.icon-minus:before {
content: "\e656";
}
.icon-equal:before {
content: "\e701";
}
.icon-ctrl:before {
content: "\e605";
}
.icon-shift:before {
content: "\e626";
}
.icon-mouse:before {
content: "\e69e";
}
.icon-left-right:before {
content: "\e61c";
}
.icon-up-down:before {
content: "\e61d";
}
.icon-help:before {
content: "\e87a";
} }
.icon-parameter:before { .icon-parameter:before {
@ -203,31 +71,175 @@
content: "\e614"; content: "\e614";
} }
.icon-brackets:before { .icon-help:before {
content: "\e613"; content: "\e87a";
} }
.icon-register:before { .icon-ctrl:before {
content: "\e611"; content: "\e605";
} }
.icon-about:before { .icon-shift:before {
content: "\e601"; content: "\e626";
} }
.icon-setting:before { .icon-mouse:before {
content: "\e657"; content: "\e69e";
} }
.icon-collections:before { .icon-left-right:before {
content: "\e689"; content: "\e61c";
} }
.icon-memory-chip:before { .icon-up-down:before {
content: "\e600"; content: "\e61d";
} }
.icon-wave-square:before { .icon-command:before {
content: "\ebd0"; content: "\e604";
}
.icon-minus:before {
content: "\e656";
}
.icon-equal:before {
content: "\e701";
}
.icon-arrow-right:before {
content: "\eb08";
}
.icon-arrow-left:before {
content: "\eb09";
}
.icon-arrow-down:before {
content: "\eb0a";
}
.icon-arrow-up:before {
content: "\eb0b";
}
.icon-change-color:before {
content: "\e6fb";
}
.icon-join-group:before {
content: "\e914";
}
.icon-thin-arrow-right:before {
content: "\e622";
}
.icon-choose:before {
content: "\e63b";
}
.icon-cancel-group:before {
content: "\e65f";
}
.icon-delete-group:before {
content: "\e675";
}
.icon-expand:before {
content: "\e658";
}
.icon-collapse:before {
content: "\e676";
}
.icon-group:before {
content: "\e70c";
}
.icon-empty:before {
content: "\e617";
}
.icon-delete:before {
content: "\e684";
}
.icon-line-analog:before {
content: "\e662";
}
.icon-ladder-analog:before {
content: "\e87b";
}
.icon-common-digital:before {
content: "\e606";
}
.icon-arrow-to-next:before {
content: "\e615";
}
.icon-beginning:before {
content: "\e60e";
}
.icon-ending:before {
content: "\e60f";
}
.icon-arrow-to-previous:before {
content: "\e616";
}
.icon-add-line:before {
content: "\e7b0";
}
.icon-axis:before {
content: "\ed1f";
}
.icon-clear:before {
content: "\e619";
}
.icon-menu:before {
content: "\e607";
}
.icon-gou:before {
content: "\e84b";
}
.icon-i18n:before {
content: "\e678";
}
.icon-single-click:before {
content: "\e664";
}
.icon-wheel-change:before {
content: "\e6ad";
}
.icon-double-click:before {
content: "\e6fc";
}
.icon-connection-style-slice:before {
content: "\e608";
}
.icon-connection-style-concat:before {
content: "\e6e9";
}
.icon-connection-style-connect:before {
content: "\e693";
} }

Binary file not shown.

View File

@ -12,6 +12,13 @@
--toolbar-height: 50px; --toolbar-height: 50px;
--toolbar-item-height: 32px; --toolbar-item-height: 32px;
/* 渲染相关的颜色设置 */
--instance-color: #CB81DA;
--instance-fill-color: rgba(203, 129, 218, 0.1);
--wire-color: var(--foreground);
--port-color: rgb(70, 70, 222);
--port-fill-color: rgba(70, 70, 222, 0.1);
/* css 动画属性 */ /* css 动画属性 */
--animation-7s: .7s cubic-bezier(0.23,1,0.32,1); --animation-7s: .7s cubic-bezier(0.23,1,0.32,1);
--animation-5s: .5s cubic-bezier(0.23,1,0.32,1); --animation-5s: .5s cubic-bezier(0.23,1,0.32,1);

View File

@ -11,7 +11,7 @@ headers = {
'sec-fetch-mode': 'navigate' 'sec-fetch-mode': 'navigate'
} }
url = 'https://www.iconfont.cn/api/project/download.zip?spm=a313x.manage_type_myprojects.i1.d7543c303.125e3a81q6VMOU&pid=4440655&ctoken=Ku-GfnHTFQU6ObMjjX4rrwYn' url = 'https://www.iconfont.cn/api/project/download.zip?spm=a313x.manage_type_myprojects.i1.d7543c303.96213a81OjUDfb&pid=4797805&ctoken=QcRJGHx0m7kL39pW1Slgy_E8'
res = r.get(url, headers=headers) res = r.get(url, headers=headers)
if res.status_code: if res.status_code:

View File

@ -36,11 +36,17 @@ onMounted(async () => {
} }
.grab { .grab {
cursor: grab; /* TODO: finish */
/* cursor: grab; */
}
.pointer {
cursor: pointer;
} }
.grabbing { .grabbing {
cursor: grabbing; /* TODO: finish */
/* cursor: grabbing; */
} }
.port-caption { .port-caption {

View File

@ -0,0 +1,85 @@
import { reactive } from 'vue';
import i18n from '@/i18n';
import { parseColor } from '@/hook/color';
const { t } = i18n.global;
export const colorManager = reactive({
currentGerneralIndex: 0,
generals: [
{
value: 0,
type: 'wire',
label: t('common.line'),
color: 'white',
},
{
value: 1,
type: 'port',
label: t('common.port'),
color: 'white',
},
{
value: 2,
type: 'instance',
label: t('common.instance'),
color: 'white',
}
],
currentCell: 'binary',
cells: [
{
value: '',
text: ''
},
{
},
{
},
{
},
{
}
],
initColor() {
const rootStyles = getComputedStyle(document.documentElement);
for (const item of this.generals) {
const optionName = `--${item.type}-color`;
const colorString = rootStyles.getPropertyValue(optionName);
console.log(optionName, colorString);
item.color = colorString;
}
}
});
/**
* @description 通用颜色设置发生变时
* @param {string} colorString 用户选择的颜色的字符串
*/
export function onGeneralColorChange(colorString) {
const { r, g, b } = parseColor(colorString);
const index = colorManager.currentGerneralIndex;
const item = colorManager.generals[index];
const borderColor = `rgb(${r}, ${g}, ${b})`;
const fillColor = `rgba(${r}, ${g}, ${b}, 0.1)`;
const rootStyles = getComputedStyle(document.documentElement);
document.documentElement.style.setProperty(`--${item.type}-color`, borderColor);
document.documentElement.style.setProperty(`--${item.type}-fill-color`, fillColor);
}
export const predefinedColors = [
'#ff4500',
'#ff8c00',
'#ffd700',
'#90ee90',
'#00ced1',
'#1e90ff',
'#c71585'
];

View File

@ -0,0 +1,27 @@
import { pinkLog } from '@/hook/utils';
import { reactive } from 'vue';
export const connectionStyles = reactive({
currentStyle: 'connect',
options: [
{
value: 'slice',
text: '拆分符',
icon: 'iconfont icon-connection-style-slice'
},
{
value: 'connect',
text: '直连符',
icon: 'iconfont icon-connection-style-connect'
},
{
value: 'concat',
text: '合并符',
icon: 'iconfont icon-connection-style-concat'
}
]
});
export function onConnectStyleChange(style) {
pinkLog('连接样式修改为: ' + style);
}

View File

@ -3,10 +3,9 @@
<el-scrollbar height="98vh"> <el-scrollbar height="98vh">
<div class="setting-section"> <div class="setting-section">
<h2>{{ t('general-setting') }}</h2> <h2>{{ t('general-setting') }}</h2>
<div class="setting-option" style="width: 220px;"> <div class="setting-option">
<span> <span>
<span class="iconfont icon-i18n"></span> <span class="iconfont icon-i18n"></span>
&ensp;
<span class="option-title">{{ t('language-setting') }}</span> <span class="option-title">{{ t('language-setting') }}</span>
</span> </span>
<div style="width: 100px;"> <div style="width: 100px;">
@ -45,15 +44,94 @@
<div class="setting-option"> <div class="setting-option">
<span class="option-title"> <span class="option-title">
{{ t('render-animation') }} {{ t('render-animation') }}
</span> </span>
<el-switch <el-switch
v-model="globalSetting.renderAnimation" v-model="globalSetting.renderAnimation"
active-text="ON" active-text="ON"
inactive-text="OFF" inactive-text="OFF"
/> />
</div> </div>
</div>
<div class="setting-section">
<h2>{{ t('appearance-setting') }}</h2>
<div class="setting-option">
<span class="option-title">
{{ t('render-arrow') }}
</span>
<el-switch
v-model="globalSetting.renderArrow"
active-text="ON"
inactive-text="OFF"
/>
</div>
<br>
<div class="setting-option">
<span class="option-title">
{{ t('bold-multi-width-wire') }}
</span>
<el-switch
v-model="globalSetting.boldMultiWidthWire"
active-text="ON"
inactive-text="OFF"
/>
</div>
<br>
<div class="setting-option">
<span class="option-title">
{{ t('cross-dot-style') }}
</span>
<div style="width: 100px;">
<el-select
name="language-setting"
class="language-setting"
v-model="connectionStyles.currentStyle"
@change="onConnectStyleChange"
>
<el-option
v-for="option in connectionStyles.options"
:value="option.value"
:label="option.text"
:key="option.value">
<span class="option-group">
<span :class="option.icon" class="connection-icon"></span>
<span>{{ option.text }}</span>
</span>
</el-option>
</el-select>
</div>
</div>
<br>
<div class="setting-option">
<span class="option-title">
{{ t('setting.general-color-setting') }}
</span>
<div class="option-group">
<div style="width: 100px;">
<el-select
v-model="colorManager.currentGerneralIndex"
collapse-tags
collapse-tags-tooltip
placeholder="Select"
>
<el-option v-for="option in colorManager.generals" :key="option.value"
:label="option.label" :value="option.value" />
</el-select>
</div>
<div style="height: 20px; width: 20px;"></div>
<el-color-picker
v-model="colorManager.generals[colorManager.currentGerneralIndex].color"
@change="onGeneralColorChange"
:predefine="predefinedColors"
/>
</div>
</div>
</div> </div>
</el-scrollbar> </el-scrollbar>
@ -62,8 +140,11 @@
<script setup> <script setup>
import { globalSetting } from '@/hook/global'; import { globalSetting } from '@/hook/global';
import { reactive, defineComponent, watch, ref } from 'vue'; import { reactive, defineComponent, watch, ref, onMounted } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { languageSetting } from './language';
import { connectionStyles, onConnectStyleChange } from './connect-style';
import { colorManager, onGeneralColorChange, predefinedColors } from './color';
defineComponent({ name: "dide-setting" }); defineComponent({ name: "dide-setting" });
const { t, locale } = useI18n(); const { t, locale } = useI18n();
@ -90,46 +171,9 @@ function onlanguagechange(code) {
languageDialogShow.value = true; languageDialogShow.value = true;
} }
const languageSetting = reactive({ onMounted(() => {
options: [ colorManager.initColor();
{ })
value: 'en',
text: 'English'
},
{
value: 'zh',
text: '简体中文'
},
{
value: 'zhTw',
text: '繁體中文'
},
{
value: 'ja',
text: '日本語'
},
{
value: 'ko',
text: '한국어'
},
{
value: 'de',
text: 'Deutsch'
},
{
value: 'fr',
text: 'Français'
},
{
value: 'ru',
text: 'Русский'
},
{
value: 'ar',
text: 'العربية'
}
]
});
</script> </script>
@ -215,4 +259,16 @@ const languageSetting = reactive({
color: var(--vscode-foreground) !important; color: var(--vscode-foreground) !important;
} }
.setting-option .icon-i18n {
margin-right: 8px;
}
.connection-icon {
width: 12px;
margin-right: 8px;
display: flex;
justify-content: center;
font-size: 10px;
}
</style> </style>

View File

@ -0,0 +1,42 @@
import { reactive } from 'vue';
export const languageSetting = reactive({
options: [
{
value: 'en',
text: 'English'
},
{
value: 'zh',
text: '简体中文'
},
{
value: 'zhTw',
text: '繁體中文'
},
{
value: 'ja',
text: '日本語'
},
{
value: 'ko',
text: '한국어'
},
{
value: 'de',
text: 'Deutsch'
},
{
value: 'fr',
text: 'Français'
},
{
value: 'ru',
text: 'Русский'
},
{
value: 'ar',
text: 'العربية'
}
]
});

View File

@ -8,7 +8,12 @@ export const emitter = mitt();
export const globalSetting = reactive({ export const globalSetting = reactive({
language: 'zh', language: 'zh',
renderAnimation: true // 开启渲染动画
renderAnimation: true,
// 绘制箭头
renderArrow: false,
// 加粗多位宽的线
boldMultiWidthWire: true
}); });
export const globalLookup = reactive({ export const globalLookup = reactive({

View File

@ -48,28 +48,22 @@ export class CellRender {
const id2manager = this.id2manager; const id2manager = this.id2manager;
const _this = this; const _this = this;
console.log(data);
let cellSelections = this.parentSelection.selectAll('svg') let cellSelections = this.parentSelection.selectAll('svg')
.data(data) .data(data)
.enter() .enter()
.append(data => { .append(data => {
const element = data.element; const element = data.element;
console.log(data);
element.setAttribute('x', data.x); element.setAttribute('x', data.x);
element.setAttribute('y', data.y); element.setAttribute('y', data.y);
if (globalSetting.renderAnimation) { if (globalSetting.renderAnimation) {
element.setAttribute('stroke-opacity', 0); element.setAttribute('opacity', 0);
} }
return element; return element;
}) })
.each(function (data) { .each(function (data) {
const cellSelection = d3.select(this); const cellSelection = d3.select(this);
const manager = _this.createDataManager(cellSelection, data); const manager = _this.createDataManager(cellSelection, data);
// TODO: 实现拖拽 // TODO: 实现拖拽
// registerDragEvent(manager, rootRender); // registerDragEvent(manager, rootRender);
}); });
@ -78,7 +72,7 @@ export class CellRender {
cellSelections = cellSelections cellSelections = cellSelections
.transition() .transition()
.duration(1000) .duration(1000)
.attr('stroke-opacity', 1) .attr('opacity', 1)
.attr('class', 'grab'); .attr('class', 'grab');
} else { } else {
cellSelections = cellSelections cellSelections = cellSelections

View File

@ -2,6 +2,7 @@ import * as d3 from 'd3';
import { NetlistRender } from '.'; import { NetlistRender } from '.';
import { globalSetting } from '../global'; import { globalSetting } from '../global';
import { LAYOUT_CONSTANT } from './layout'; import { LAYOUT_CONSTANT } from './layout';
import { svgResource } from '../skin/draw';
export class InstantiationRender { export class InstantiationRender {
/** /**
@ -32,52 +33,20 @@ export class InstantiationRender {
addAsD3DataItem(node) { addAsD3DataItem(node) {
const nodeModule = this.rootRender.nameToModule.get(node.renderName); const nodeModule = this.rootRender.nameToModule.get(node.renderName);
const view = nodeModule.view; const view = nodeModule.view;
const textPadding = 5;
const portnames = []; const portnames = [];
let inputCount = 0;
let outputCount = 0;
const instanceWidth = LAYOUT_CONSTANT.INSTANTIATION_WIDTH + 2 * LAYOUT_CONSTANT.PORT_INNER_PADDING;
// 统计出两侧 port 字符串最长的 for (const port of node.ports || []) {
let inputPortMaxLength = 0; const isInput = port.x < LAYOUT_CONSTANT.INSTANTIATION_WIDTH;
let outputPortMaxLength = 0; const align = isInput ? 'left': 'end';
const portX = isInput ? port.x + textPadding : port.x - textPadding;
for (const portName of view.nameToPort.keys()) { portnames.push({
const port = view.nameToPort.get(portName); name: port.renderName,
if (port.direction === 'input') { x: portX,
inputPortMaxLength = Math.max(portName.length, inputPortMaxLength); y: port.y,
} else { align
outputPortMaxLength = Math.max(portName.length, outputPortMaxLength); });
}
}
for (const portName of view.nameToPort.keys()) {
const port = view.nameToPort.get(portName);
if (port.direction === 'input') {
inputCount ++;
const offsetY = inputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN +
(inputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT +
LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT;
portnames.push({
name: portName,
x: 5,
y: offsetY,
align: 'left'
});
} else {
outputCount ++;
const offsetY = outputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN +
(outputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT +
LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT;
portnames.push({
name: portName,
x: instanceWidth - 5,
y: offsetY,
align: 'end'
});
}
} }
this.data.push({ this.data.push({
@ -88,12 +57,11 @@ export class InstantiationRender {
name: node.name, name: node.name,
width: node.width, width: node.width,
height: node.height, height: node.height,
fill: 'var(--main-dark-color)', fill: 'var(--instance-fill-color)',
text: node.renderName, text: node.renderName,
portnames, portnames,
rx: 3, rx: 3,
ry: 3, ry: 3,
expandText: '📌',
_self: node _self: node
}); });
} }
@ -104,6 +72,7 @@ export class InstantiationRender {
const id2manager = this.id2manager; const id2manager = this.id2manager;
const _this = this; const _this = this;
// 外部控制主体的 g
let instantiationSelections = this.parentSelection.selectAll('g.instance') let instantiationSelections = this.parentSelection.selectAll('g.instance')
.data(data) .data(data)
.enter() .enter()
@ -111,74 +80,142 @@ export class InstantiationRender {
.attr('class', 'instance') .attr('class', 'instance')
.attr("transform", d => `translate(${d.x}, ${d.y})`); .attr("transform", d => `translate(${d.x}, ${d.y})`);
// 例化模块的方块
let instances = instantiationSelections.append('rect') let instances = instantiationSelections.append('rect')
.attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT) .attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT)
.attr('width', data => data.width) .attr('width', data => data.width)
.attr('height', data => data.height - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT) .attr('height', data => data.height - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT);
.attr('fill', d => {
const children = d._self.children || [];
return children.length > 0 ? 'rgba(203, 129, 218, 0.1)' : d.fill;
});
// 说明文字
let texts = instantiationSelections.append('text') let texts = instantiationSelections.append('text')
.attr('x', 0) .attr('x', 0)
.attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - 8) .attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - 8)
.attr('dominant-baseline', 'middle') .attr('dominant-baseline', 'middle')
.attr('text-anchor', 'left') .attr('text-anchor', 'left')
.attr('fill', 'var(--main-dark-color)') .attr('fill', 'var(--foreground)')
.attr('font-size', '0') .attr('font-size', '14px')
.attr('font-size', '12px')
.attr('class', 'port-caption') .attr('class', 'port-caption')
.text(data => data.name + ' ' + data.expandText) .text(data => data.name)
.each(function(data) { .each(function(data) {
const text = d3.select(this); const text = d3.select(this);
const bbox = text.node().getBBox(); const bbox = text.node().getBBox();
instantiationSelections.insert('rect', 'text') data.textX = (data.width - bbox.width) / 2;
.attr('x', -1)
.attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - bbox.height - 5)
.attr('width', bbox.width + 10)
.attr('height', bbox.height + 5)
.attr('fill', 'var(--main-color)');
}) })
.on('click', function(event) { .attr('x', d => d.textX)
// 渲染 portnames
instantiationSelections.each(function(node) {
d3.select(this)
.selectAll('.port-name')
.data(node.portnames)
.enter()
.append('text')
.attr('class', 'port-name')
.attr('x', d => d.x)
.attr('y', d => d.y)
.attr('dominant-baseline', 'middle')
.attr('text-anchor', d => d.align)
.attr('fill', 'var(--foreground)')
.attr('font-size', '11px')
.text(d => d.name);
});
// 增加一个背景方块,防止 svg 点不到
let bgFullScreenSelections = instantiationSelections.append('rect')
.attr('x', 5)
.attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5)
.attr('width', 20)
.attr('height', 20)
.attr('opacity', 0)
.attr('class', 'pointer')
.on('click', function(data) {
const selection = d3.select(this); const selection = d3.select(this);
const d = selection.datum(); const d = selection.datum();
const children = d._self.children || []; const children = d._self.children || [];
if (children.length > 0) { if (children.length > 0) {
rootRender.collapseInstance(selection); rootRender.collapseInstance(selection);
} else { } else {
rootRender.expandInstance(selection); rootRender.expandInstance(selection);
} }
}); });
const id2element = new Map();
// 渲染左上角的放大缩小图标,并注册对应的展开/收起事件
let fullSreenSelections = instantiationSelections.append(data => {
// 获取全屏图标
const element = svgResource.get('full-screen');
element.setAttribute('x', 5);
element.setAttribute('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5);
element.setAttribute('width', 20);
element.setAttribute('height', 20);
element.setAttribute('class', 'pointer');
// 获取 port 相关的信息 return element;
instantiationSelections.each(function(node) { })
d3.select(this) // 选择当前节点 .each(function(data) {
.selectAll('.port-name') // 选择所有端口名称元素 const svgElement = d3.select(this);
.data(node.portnames) // 绑定端口名称数据 id2element.set(data.id, svgElement);
.enter() })
.append('text') // 创建文本元素 .on('mouseenter', function() {
.attr('class', 'port-name') const svgElement = d3.select(this);
.attr('x', d => d.x) // 使用端口的相对 x 坐标 svgElement.selectAll("*")
.attr('y', d => d.y) // 使用端口的相对 y 坐标 .attr("fill", "var(--instance-color)");
.attr('dominant-baseline', 'middle') // 文本垂直居中 })
.attr('text-anchor', d => d.align) .on('mouseleave', function() {
.attr('fill', 'var(--foreground)') // 文本颜色 const svgElement = d3.select(this);
.attr('font-size', '10px') // 设置字体大小 svgElement.selectAll("*")
.text(d => d.name); // 设置文本内容 .attr("fill", "var(--foreground)");
})
.on('click', function(data) {
const selection = d3.select(this);
const d = selection.datum();
const children = d._self.children || [];
if (children.length > 0) {
rootRender.collapseInstance(selection);
} else {
rootRender.expandInstance(selection);
}
}); });
console.log(id2element);
bgFullScreenSelections
.on('mouseenter', function(_, data) {
const svgElement = id2element.get(data.id);
svgElement.selectAll("*")
.attr("fill", "var(--instance-color)");
})
.on('mouseleave', function(_, data) {
const svgElement = id2element.get(data.id);
svgElement.selectAll("*")
.attr("fill", "var(--foreground)");
});
if (globalSetting.renderAnimation) { if (globalSetting.renderAnimation) {
instances.transition() instances
.transition()
.duration(1000) .duration(1000)
.attr('stroke', 'var(--main-color)') .attr('fill', d => {
.attr('stroke-width', 2) const children = d._self.children || [];
return children.length > 0 ? 'rgba(203, 129, 218, 0.1)' : d.fill;
})
.attr('stroke', 'var(--instance-color)')
.attr('stroke-width', 2);
} else { } else {
instances.attr('stroke', 'var(--main-color)') instances
.attr('stroke-width', 2) .attr('fill', d => {
const children = d._self.children || [];
return children.length > 0 ? 'rgba(203, 129, 218, 0.1)' : d.fill;
})
.attr('stroke', 'var(--instance-color)')
.attr('stroke-width', 2)
} }
instantiationSelections instantiationSelections

View File

@ -32,6 +32,7 @@ export const LAYOUT_CONSTANT = {
// 例化模块上部分的空缺区域 // 例化模块上部分的空缺区域
INSTANCE_TITLE_HEIGHT: 10, INSTANCE_TITLE_HEIGHT: 10,
INSTANCE_TOP_PADDING: 20,
// 常数 // 常数
CONSTANT_WIDTH: 50, CONSTANT_WIDTH: 50,
@ -271,7 +272,7 @@ export class Module {
inputCount ++; inputCount ++;
const offsetY = inputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN + const offsetY = inputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN +
(inputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT + (inputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT +
LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT; LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + LAYOUT_CONSTANT.INSTANCE_TOP_PADDING;
ports.push({ ports.push({
id: connection.id, id: connection.id,
@ -286,7 +287,7 @@ export class Module {
outputCount ++; outputCount ++;
const offsetY = outputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN + const offsetY = outputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN +
(outputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT + (outputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT +
LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT; LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + LAYOUT_CONSTANT.INSTANCE_TOP_PADDING;
ports.push({ ports.push({
id: connection.id, id: connection.id,
@ -306,7 +307,7 @@ export class Module {
renderName: cell.type, renderName: cell.type,
renderType: 'cell', renderType: 'cell',
width: instanceWidth, width: instanceWidth,
height: instanceHeight + LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT, height: instanceHeight + LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + LAYOUT_CONSTANT.INSTANCE_TOP_PADDING,
ports, ports,
layoutOptions: { layoutOptions: {
// 强制固定 port 的方向 // 强制固定 port 的方向

View File

@ -36,7 +36,7 @@ export class PortRender {
y: node.y, y: node.y,
width: node.width, width: node.width,
height: node.height, height: node.height,
fill: 'var(--main-dark-color)', fill: 'var(--port-fill-color)',
text: node.renderName, text: node.renderName,
rx: 3, rx: 3,
ry: 3 ry: 3
@ -78,12 +78,12 @@ export class PortRender {
if (globalSetting.renderAnimation) { if (globalSetting.renderAnimation) {
ports.transition() ports.transition()
.duration(1000) .duration(1000)
.attr('stroke', 'var(--main-color)') .attr('stroke', 'var(--port-color)')
.attr('stroke-width', 2) .attr('stroke-width', 2)
.attr('rx', d => d.rx) .attr('rx', d => d.rx)
.attr('ry', d => d.ry); .attr('ry', d => d.ry);
} else { } else {
ports.attr('stroke', 'var(--main-color)') ports.attr('stroke', 'var(--port-color)')
.attr('stroke-width', 2) .attr('stroke-width', 2)
.attr('rx', d => d.rx) .attr('rx', d => d.rx)
.attr('ry', d => d.ry); .attr('ry', d => d.ry);

View File

@ -38,7 +38,7 @@ export class WireRender {
x2: points[i + 1].x, x2: points[i + 1].x,
y2: points[i + 1].y, y2: points[i + 1].y,
strokeWidth: 2, strokeWidth: 2,
color: 'var(--foreground)' color: 'var(--wire-color)'
}); });
} }
} }

38
src/hook/skin/draw.js Normal file
View File

@ -0,0 +1,38 @@
// 一些和绘制相关的 svg 资源
export const DIDE_DRAW_SVG_STRINGS = [
// 放大
{
name: 'full-screen',
source: '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1735474395064" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3925" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M0.042667 749.792759v164.515811A110.075414 110.075414 0 0 0 109.691431 1023.957335h164.515812a54.867047 54.867047 0 1 0 0-109.648765H109.691431V749.792759a54.867047 54.867047 0 1 0-109.648764 0zM329.07429 54.867047A54.867047 54.867047 0 0 0 274.207243 0H109.691431A110.075414 110.075414 0 0 0 0.042667 109.648765v164.515811a54.867047 54.867047 0 1 0 109.648764 0V109.648765h164.515812a54.867047 54.867047 0 0 0 54.867047-54.781718z m365.894088 0c0 30.292071 24.574976 54.781717 54.867047 54.781718h164.515812v164.515811a54.867047 54.867047 0 0 0 109.648765 0V109.648765A110.075414 110.075414 0 0 0 914.351237 0H749.835425a54.867047 54.867047 0 0 0-54.867047 54.867047z m0 914.223241c0 30.292071 24.574976 54.867047 54.867047 54.867047h164.515812A110.075414 110.075414 0 0 0 1024.000002 914.30857V749.792759a54.867047 54.867047 0 1 0-109.648765 0v164.515811H749.835425a54.867047 54.867047 0 0 0-54.867047 54.781718z" fill="#000000" p-id="3926"></path><path d="M512.021334 261.36511A250.698888 250.698888 0 1 0 729.612268 387.397192a50.08858 50.08858 0 1 0-87.036374 49.83259A150.436398 150.436398 0 1 1 512.021334 361.542269a50.173909 50.173909 0 0 0 0-100.262489z" fill="#000000" p-id="3927"></path></svg>'
}
];
class SvgResource {
constructor() {
/**
* @type {Map<string, Document>}
*/
this.nameToSvgDoc = new Map();
const parser = new DOMParser();
for (const item of DIDE_DRAW_SVG_STRINGS) {
let svgString = item.source;
let name = item.name;
// 填充颜色
svgString = svgString.replace(/#000000/g, 'var(--foreground)');
const svgDoc = parser.parseFromString(svgString, 'image/svg+xml');
this.nameToSvgDoc.set(name, svgDoc);
}
}
get(svgName) {
const svg = this.nameToSvgDoc.get(svgName);
if (!svg) {
return undefined;
}
const element = svg.documentElement.cloneNode(true);
return element;
}
}
export const svgResource = new SvgResource();

View File

@ -3,7 +3,6 @@
"general-setting": "عام", "general-setting": "عام",
"appearance-setting": "المظهر", "appearance-setting": "المظهر",
"current-version": "الإصدار الحالي", "current-version": "الإصدار الحالي",
"copyright": "حقوق النشر مملوكة لفريق مشروع <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a>، نرحب بـ <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"confirm": "تأكيد", "confirm": "تأكيد",
"cancel": "إلغاء", "cancel": "إلغاء",
"tips": "نصائح", "tips": "نصائح",
@ -16,5 +15,13 @@
"usermanual.scale-view": "تكبير/تصغير العرض", "usermanual.scale-view": "تكبير/تصغير العرض",
"usermanual.scale-view-more": "تكبير العرض (مقياس أكبر)", "usermanual.scale-view-more": "تكبير العرض (مقياس أكبر)",
"loading": "جاري التحميل", "loading": "جاري التحميل",
"module": "وحدة" "module": "وحدة",
"render-arrow": "تقديم سهم نقطة الاتصال",
"bold-multi-width-wire": "خطوط اتصال متعددة العرض بخط عريض",
"copyright": "حقوق النشر مملوكة لفريق مشروع <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a>، نرحب بـ <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"cross-dot-style": "نمط التقاطع",
"common.line": "خط",
"common.port": "المنفذ",
"common.instance": "تجهيز الوحدة",
"setting.general-color-setting": "إعدادات الألوان العامة"
} }

View File

@ -3,7 +3,6 @@
"general-setting": "Allgemein", "general-setting": "Allgemein",
"appearance-setting": "Aussehen", "appearance-setting": "Aussehen",
"current-version": "Aktuelle Version", "current-version": "Aktuelle Version",
"copyright": "Dieses Software gehört dem <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> Projektteam, willkommen <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"confirm": "Bestätigen", "confirm": "Bestätigen",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"tips": "Tipps", "tips": "Tipps",
@ -16,5 +15,13 @@
"usermanual.scale-view": "Ansicht zoomen", "usermanual.scale-view": "Ansicht zoomen",
"usermanual.scale-view-more": "Ansicht vergrößern (größerer Maßstab)", "usermanual.scale-view-more": "Ansicht vergrößern (größerer Maßstab)",
"loading": "Laden", "loading": "Laden",
"module": "Modul" "module": "Modul",
"render-arrow": "Rendern des Verbindungspfeils",
"bold-multi-width-wire": "Fettgedruckte mehrfach breite Verbindungslinien",
"copyright": "Dieses Software gehört dem <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> Projektteam, willkommen <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"cross-dot-style": "Kreuzungsstil",
"common.line": "Linie",
"common.port": "Port",
"common.instance": "Modul instanziieren",
"setting.general-color-setting": "Allgemeine Farbeinstellungen"
} }

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,6 @@
"general-setting": "Général", "general-setting": "Général",
"appearance-setting": "Apparence", "appearance-setting": "Apparence",
"current-version": "Version actuelle", "current-version": "Version actuelle",
"copyright": "Les droits d'auteur appartiennent au groupe de projet <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a>, bienvenue <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"confirm": "Confirmer", "confirm": "Confirmer",
"cancel": "Annuler", "cancel": "Annuler",
"tips": "Conseils", "tips": "Conseils",
@ -16,5 +15,13 @@
"usermanual.scale-view": "Zoom de la vue", "usermanual.scale-view": "Zoom de la vue",
"usermanual.scale-view-more": "Zoom de la vue (échelle plus grande)", "usermanual.scale-view-more": "Zoom de la vue (échelle plus grande)",
"loading": "Chargement", "loading": "Chargement",
"module": "Module" "module": "Module",
"render-arrow": "Rendu de la flèche du point de connexion",
"bold-multi-width-wire": "Lignes de connexion multi-largeur en gras",
"copyright": "Les droits d'auteur appartiennent au groupe de projet <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a>, bienvenue <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"cross-dot-style": "Style d'intersection",
"common.line": "ligne",
"common.port": "Port",
"common.instance": "Instancier le module",
"setting.general-color-setting": "Paramètres de couleur généraux"
} }

View File

@ -3,7 +3,6 @@
"general-setting": "一般", "general-setting": "一般",
"appearance-setting": "外観", "appearance-setting": "外観",
"current-version": "現在のバージョン", "current-version": "現在のバージョン",
"copyright": "このソフトウェアの著作権は <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> プロジェクトチームに帰属します。<a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a> を歓迎します。",
"confirm": "確認", "confirm": "確認",
"cancel": "キャンセル", "cancel": "キャンセル",
"tips": "ヒント", "tips": "ヒント",
@ -16,5 +15,13 @@
"usermanual.scale-view": "ビューのズーム", "usermanual.scale-view": "ビューのズーム",
"usermanual.scale-view-more": "ビューのズーム(より大きなスケール)", "usermanual.scale-view-more": "ビューのズーム(より大きなスケール)",
"loading": "読み込み中", "loading": "読み込み中",
"module": "モジュール" "module": "モジュール",
"render-arrow": "接続点矢印のレンダリング",
"bold-multi-width-wire": "太字の多幅接続線",
"copyright": "このソフトウェアの著作権は <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> プロジェクトチームに帰属します。<a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a> を歓迎します。",
"cross-dot-style": "交差点スタイル",
"common.line": "線",
"common.port": "ポート",
"common.instance": "モジュールのインスタンス化",
"setting.general-color-setting": "一般的な色設定"
} }

View File

@ -3,7 +3,6 @@
"general-setting": "일반", "general-setting": "일반",
"appearance-setting": "외관", "appearance-setting": "외관",
"current-version": "현재 버전", "current-version": "현재 버전",
"copyright": "이 소프트웨어의 저작권은 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 프로젝트 팀에 있으며, <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>를 환영합니다.",
"confirm": "확인", "confirm": "확인",
"cancel": "취소", "cancel": "취소",
"tips": "팁", "tips": "팁",
@ -16,5 +15,13 @@
"usermanual.scale-view": "보기 확대/축소", "usermanual.scale-view": "보기 확대/축소",
"usermanual.scale-view-more": "보기 확대 (더 큰 스케일)", "usermanual.scale-view-more": "보기 확대 (더 큰 스케일)",
"loading": "로딩 중", "loading": "로딩 중",
"module": "모듈" "module": "모듈",
"render-arrow": "연결점 화살표 렌더링",
"bold-multi-width-wire": "굵은 다중 너비 연결선",
"copyright": "이 소프트웨어의 저작권은 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 프로젝트 팀에 있으며, <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>를 환영합니다.",
"cross-dot-style": "교차로 스타일",
"common.line": "선",
"common.port": "포트",
"common.instance": "모듈 인스턴스화",
"setting.general-color-setting": "일반 색상 설정"
} }

View File

@ -3,7 +3,6 @@
"general-setting": "Общие", "general-setting": "Общие",
"appearance-setting": "Внешний вид", "appearance-setting": "Внешний вид",
"current-version": "Текущая версия", "current-version": "Текущая версия",
"copyright": "Авторские права принадлежат проектной группе <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a>, приветствуем <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"confirm": "Подтвердить", "confirm": "Подтвердить",
"cancel": "Отменить", "cancel": "Отменить",
"tips": "Советы", "tips": "Советы",
@ -16,5 +15,13 @@
"usermanual.scale-view": "Масштабирование вида", "usermanual.scale-view": "Масштабирование вида",
"usermanual.scale-view-more": "Масштабирование вида (больший масштаб)", "usermanual.scale-view-more": "Масштабирование вида (больший масштаб)",
"loading": "Загрузка", "loading": "Загрузка",
"module": "Модуль" "module": "Модуль",
"render-arrow": "Рендеринг стрелки точки соединения",
"bold-multi-width-wire": "Жирные многожильные соединительные линии",
"copyright": "Авторские права принадлежат проектной группе <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a>, приветствуем <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>.",
"cross-dot-style": "Стиль пересечения",
"common.line": "линия",
"common.port": "Порт",
"common.instance": "Создание экземпляра модуля",
"setting.general-color-setting": "Общие настройки цвета"
} }

View File

@ -3,7 +3,6 @@
"general-setting": "通用", "general-setting": "通用",
"appearance-setting": "外观", "appearance-setting": "外观",
"current-version": "当前版本", "current-version": "当前版本",
"copyright": "本软件版权归 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 项目组所有,欢迎 <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>。",
"confirm": "确定", "confirm": "确定",
"cancel": "取消", "cancel": "取消",
"tips": "提示", "tips": "提示",
@ -16,5 +15,13 @@
"usermanual.scale-view": "视图缩放", "usermanual.scale-view": "视图缩放",
"usermanual.scale-view-more": "视图缩放(尺度更大)", "usermanual.scale-view-more": "视图缩放(尺度更大)",
"loading": "加载中", "loading": "加载中",
"module": "模块" "module": "模块",
"render-arrow": "渲染连接点箭头",
"bold-multi-width-wire": "加粗多位宽连接线",
"copyright": "本软件版权归 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 项目组所有,欢迎 <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>。",
"cross-dot-style": "交叉点样式",
"common.line": "线",
"common.port": "端口",
"common.instance": "例化模块",
"setting.general-color-setting": "通用颜色设置"
} }

View File

@ -3,7 +3,6 @@
"general-setting": "通用", "general-setting": "通用",
"appearance-setting": "外觀", "appearance-setting": "外觀",
"current-version": "當前版本", "current-version": "當前版本",
"copyright": "本軟件版權歸 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 項目組所有,歡迎 <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>。",
"confirm": "確定", "confirm": "確定",
"cancel": "取消", "cancel": "取消",
"tips": "提示", "tips": "提示",
@ -16,5 +15,13 @@
"usermanual.scale-view": "視圖縮放", "usermanual.scale-view": "視圖縮放",
"usermanual.scale-view-more": "視圖縮放(尺度更大)", "usermanual.scale-view-more": "視圖縮放(尺度更大)",
"loading": "加載中", "loading": "加載中",
"module": "模塊" "module": "模塊",
"render-arrow": "渲染連接點箭頭",
"bold-multi-width-wire": "加粗多位寬連接線",
"copyright": "本軟件版權歸 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 項目組所有,歡迎 <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>。",
"cross-dot-style": "交叉點樣式",
"common.line": "線",
"common.port": "端口",
"common.instance": "實例化模組",
"setting.general-color-setting": "通用顏色設定"
} }