refactor: re1.0
@ -0,0 +1,5 @@
|
||||
*.md
|
||||
.vscode
|
||||
.idea
|
||||
dist
|
||||
node_modules
|
@ -0,0 +1,59 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
parser: '@typescript-eslint/parser',
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
jsxPragma: 'React',
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
}
|
||||
},
|
||||
extends: [
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier',
|
||||
'plugin:prettier/recommended' // 一定要放在最后。因为 extends 中后引入的规则会覆盖前面的规则。
|
||||
],
|
||||
rules: {
|
||||
// @typescript-eslint
|
||||
'@typescript-eslint/explicit-function-return-type': 'off', // 需要函数和类方法的显式返回类型
|
||||
'@typescript-eslint/no-explicit-any': 'off', // 禁止使用该 any 类型
|
||||
'@typescript-eslint/no-var-requires': 'off', // 不允许使用 require 语句,除了在 import 语句中
|
||||
'@typescript-eslint/no-empty-function': 'off', // 禁止空函数
|
||||
'@typescript-eslint/no-use-before-define': 'off', // 在定义之前禁止使用变量
|
||||
'@typescript-eslint/ban-ts-comment': 'off', // 禁止 @ts-<directive> 使用评论或在指令后要求描述
|
||||
'@typescript-eslint/ban-types': 'off', // 禁止使用特定类型
|
||||
'@typescript-eslint/no-non-null-assertion': 'off', // '!'不允许使用后缀运算符的非空断言
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off', // 需要导出函数和类的公共类方法的显式返回和参数类型
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_'
|
||||
}
|
||||
], // 禁止未使用的变量
|
||||
// vue
|
||||
'vue/custom-event-name-casing': 'off', // 为自定义事件名称强制使用特定大小写
|
||||
'vue/attributes-order': 'off', // 强制执行属性顺序
|
||||
'vue/one-component-per-file': 'off', // 强制每个组件都应该在自己的文件中
|
||||
'vue/html-closing-bracket-newline': 'off', // 在标签的右括号之前要求或禁止换行
|
||||
'vue/multiline-html-element-content-newline': 'off', // 在多行元素的内容之前和之后需要换行符
|
||||
'vue/singleline-html-element-content-newline': 'off', // 在单行元素的内容之前和之后需要换行符
|
||||
'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式
|
||||
'vue/require-default-prop': 'off', // 需要 props 的默认值
|
||||
'vue/html-indent': ['error', 2], // 在<template>中强制一致缩进
|
||||
'vue/html-self-closing': 'off', // 执行自闭合的风格
|
||||
'vue/max-attributes-per-line': 'off', // 强制每行属性的最大数量
|
||||
'vue/multi-word-component-names': 'off', // 是否开启组件命名规则校验(强制多个单词以驼峰或'-'链接的命名规则)
|
||||
// ESLint
|
||||
'no-use-before-define': 'off', // 禁止在变量定义之前使用它们
|
||||
'space-before-function-paren': 'off' // 强制在 function的左括号之前使用一致的空格
|
||||
}
|
||||
};
|
@ -1,5 +1,22 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
@ -0,0 +1 @@
|
||||
_
|
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint --edit $1
|
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
command_exists () {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Workaround for Windows 10, Git Bash and Yarn
|
||||
if command_exists winpty && test -t 1; then
|
||||
exec < /dev/tty
|
||||
fi
|
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
npx lint-staged
|
@ -0,0 +1,3 @@
|
||||
/node_modules/**
|
||||
/dist*
|
||||
/public/*
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"recommendations": ["johnsoncodehk.volar"]
|
||||
"recommendations": ["Vue.volar"]
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
{
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true,
|
||||
"eslint.autoFixOnSave": true
|
||||
},
|
||||
"files.eol": "\n"
|
||||
}
|
@ -0,0 +1 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.4 KiB |
@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 153 KiB |
After Width: | Height: | Size: 589 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 476 KiB |
@ -1,77 +0,0 @@
|
||||
/**
|
||||
* @description: 数据结构
|
||||
* @param {*} commonComponentList 常规组件列表
|
||||
* @param {*} drawComponentList 绘制组件列表
|
||||
* @param {*} chartComponentList 图表组件列表
|
||||
* @return {*}
|
||||
*/
|
||||
export interface ILeftImgLists {
|
||||
commonComponentList?: Array<IComponentInfo>,
|
||||
drawComponentList?: Array<IComponentInfo>,
|
||||
chartComponentList?: Array<IComponentInfo>
|
||||
}
|
||||
/**
|
||||
* @description: 画好的组件数据列表
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
export interface ISvgDataLists {
|
||||
id: string,
|
||||
type?: string,
|
||||
title?: string,
|
||||
svgPositionX: number,
|
||||
svgPositionY: number,
|
||||
angle?: number,
|
||||
size?: number,
|
||||
extend_attr?: any
|
||||
}
|
||||
export interface ISvgCanvas {
|
||||
width: number,
|
||||
height: number
|
||||
}
|
||||
/**
|
||||
* @description: 组件信息格式
|
||||
* @param {*} type 组件类型
|
||||
* @param {*} title 组件显示标题
|
||||
* @param {*} panel_class 面板显示类型 拖放 绘制
|
||||
* @param {*} template 组件渲染模板
|
||||
* @param {*} props 组件传值
|
||||
* @param {*} extend_attr 组件拓展属性
|
||||
* @param {*} create_type 组件创建类型
|
||||
* @param {*} priview_img 组件预览图片
|
||||
* @return {*}
|
||||
*/
|
||||
export interface IComponentInfo {
|
||||
type?: string,
|
||||
title?: string,
|
||||
panel_class?: string,
|
||||
template?: string,//
|
||||
props?: Array<string>,
|
||||
extend_attr?: any,
|
||||
create_type?: string,
|
||||
priview_img?: string
|
||||
}
|
||||
/**
|
||||
* @description: 鼠标信息
|
||||
* @param {*} status 1按下 0弹起
|
||||
* @param {*} mPositionX 鼠标x轴坐标
|
||||
* @param {*} mPositionY 鼠标y轴坐标
|
||||
* @return {*}
|
||||
*/
|
||||
export interface IMouseInfo {
|
||||
status: number,
|
||||
mPositionX: number
|
||||
mPositionY: number
|
||||
}
|
||||
/**
|
||||
* @description: 选中的svg属性
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
export interface ISelectSvg {
|
||||
id: string,
|
||||
index: number,
|
||||
sPositionX: number,
|
||||
sPositionY: number,
|
||||
create_type: string,
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/* 正向流动效果 */
|
||||
.svg_ani_flow {
|
||||
stroke-dasharray: 1000;
|
||||
stroke-dashoffset: 1000;
|
||||
animation: ani_flow 10s linear infinite;
|
||||
animation-fill-mode: forwards;
|
||||
-webkit-animation: ani_flow 10s linear infinite;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes ani_flow {
|
||||
from {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dasharray: 13, 5;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ani_flow {
|
||||
from {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dasharray: 13, 5;
|
||||
}
|
||||
}
|
||||
|
||||
/* 停止流动效果 */
|
||||
.svg_ani_flow_stop {
|
||||
stroke-dasharray: 1000;
|
||||
stroke-dashoffset: 1000;
|
||||
animation: ani_flow_stop 10s linear infinite;
|
||||
animation-fill-mode: forwards;
|
||||
-webkit-animation: ani_flow_stop 10s linear infinite;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes ani_flow_stop {
|
||||
from {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ani_flow_stop {
|
||||
from {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
}
|
||||
/* 反向流动效果 */
|
||||
.svg_ani_flow_back {
|
||||
stroke-dasharray: 1000;
|
||||
stroke-dashoffset: 1000;
|
||||
animation: ani_flow_back 10s linear infinite;
|
||||
animation-fill-mode: forwards;
|
||||
-webkit-animation: ani_flow_back 10s linear infinite;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes ani_flow_back {
|
||||
from {
|
||||
stroke-dasharray: 13, 5;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ani_flow_stop {
|
||||
from {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
}
|
||||
/* 以最大40高度填充 */
|
||||
.svg_ani_fill_h40 {
|
||||
animation: ani_fill_h40 5s linear infinite;
|
||||
animation-fill-mode: forwards;
|
||||
-webkit-animation: ani_fill_h40 5s linear infinite;
|
||||
-webkit-animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes ani_fill_h40 {
|
||||
from {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
to {
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ani_flow_stop {
|
||||
from {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dasharray: 10, 5;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M9 10V44H39V10H9Z" fill="none" />
|
||||
<path d="M20 20V33" />
|
||||
<path d="M28 20V33" />
|
||||
<path d="M4 10H44" />
|
||||
<path d="M16 10L19.289 4H28.7771L32 10H16Z" fill="none" />
|
||||
</g>
|
||||
|
||||
</svg>
|
After Width: | Height: | Size: 451 B |
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1024">
|
||||
<path d="M888.3 757.4h-53.8c-4.2 0-7.7 3.5-7.7 7.7v61.8H197.1V197.1h629.8v61.8c0 4.2 3.5 7.7 7.7 7.7h53.8c4.2 0 7.7-3.4 7.7-7.7V158.7c0-17-13.7-30.7-30.7-30.7H158.7c-17 0-30.7 13.7-30.7 30.7v706.6c0 17 13.7 30.7 30.7 30.7h706.6c17 0 30.7-13.7 30.7-30.7V765.1c0-4.3-3.5-7.7-7.7-7.7zm18.6-251.7L765 393.7c-5.3-4.2-13-.4-13 6.3v76H438c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h314v76c0 6.7 7.8 10.5 13 6.3l141.9-112a8 8 0 0 0 0-12.6z" fill="currentColor"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 576 B |
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 4H4V12H12V4Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M44 36H36V44H44V36Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M12 36H4V44H12V36Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M44 4H36V12H44V4Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M8 36V12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M40 36V12" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12 8H36" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12 40H36" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 16H25.6V22.4H32V32H22.4V25.6H16V16Z" fill="none" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1024">
|
||||
<path d="M888.3 757.4h-53.8c-4.2 0-7.7 3.5-7.7 7.7v61.8H197.1V197.1h629.8v61.8c0 4.2 3.5 7.7 7.7 7.7h53.8c4.2 0 7.7-3.4 7.7-7.7V158.7c0-17-13.7-30.7-30.7-30.7H158.7c-17 0-30.7 13.7-30.7 30.7v706.6c0 17 13.7 30.7 30.7 30.7h706.6c17 0 30.7-13.7 30.7-30.7V765.1c0-4.3-3.5-7.7-7.7-7.7zM902 476H588v-76c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 0 0 0 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-76h314c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z" fill="currentColor"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 575 B |
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="6" y="22" width="36" height="22" rx="2" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M14 22V14C14 8.47715 18.4772 4 24 4C29.5228 4 34 8.47715 34 14V22" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M24 30V36" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 531 B |
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 10.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M24 19.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M24 28.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 37.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 19L16 24L8 29V19Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 671 B |
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 10.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M24 19.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M24 28.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 37.5H40" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M16 19L8 24L16 29V19Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 672 B |
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24 36C35.0457 36 44 24 44 24C44 24 35.0457 12 24 12C12.9543 12 4 24 4 24C4 24 12.9543 36 24 36Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M24 29C26.7614 29 29 26.7614 29 24C29 21.2386 26.7614 19 24 19C21.2386 19 19 21.2386 19 24C19 26.7614 21.2386 29 24 29Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 528 B |
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M36.728 36.728A17.943 17.943 0 0 1 24 42c-9.941 0-18-8.059-18-18S14.059 6 24 6c4.97 0 9.47 2.015 12.728 5.272C38.386 12.93 42 17 42 17"></path>
|
||||
<path d="M42 8v9h-9"></path>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 438 B |
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.9998 8L6 14L12.9998 21" stroke="#333" stroke-width="4" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<path
|
||||
d="M6 14H28.9938C35.8768 14 41.7221 19.6204 41.9904 26.5C42.2739 33.7696 36.2671 40 28.9938 40H11.9984"
|
||||
stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
After Width: | Height: | Size: 482 B |
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44C30.9566 44 37.0836 40.4483 40.6667 35.0593" stroke="#333" stroke-width="4" stroke-linecap="round"/><path d="M44 24H30" stroke="#333" stroke-width="4" stroke-linecap="round"/><circle cx="24" cy="24" r="6" fill="#333" stroke="#333" stroke-width="4"/></svg>
|
After Width: | Height: | Size: 481 B |
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g stroke="#ffffff" stroke-width="4">
|
||||
<path d="M39.3 6.00012H8.7C7.20883 6.00012 6 7.20895 6 8.70012V39.3001C6 40.7913 7.20883 42.0001 8.7 42.0001H39.3C40.7912 42.0001 42 40.7913 42 39.3001V8.70012C42 7.20895 40.7912 6.00012 39.3 6.00012Z" fill="none" stroke-linejoin="round" />
|
||||
<path d="M32 6V24H15V6H32Z" fill="none" stroke-linejoin="round" />
|
||||
<path d="M26 13.0001V17.0001" stroke-linecap="round" />
|
||||
<path d="M10.9969 6.00012H35.9985" stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 653 B |
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M38 20H18V28H38V20Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M32 6H18V14H32V6Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M44 34H18V42H44V34Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M17 10H5" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M17 24H5" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M17 38H5" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5 44V4" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 863 B |
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11.2721 36.7279C14.5294 39.9853 19.0294 42 24 42C33.9411 42 42 33.9411 42 24C42 14.0589 33.9411 6 24 6C19.0294 6 14.5294 8.01472 11.2721 11.2721C9.61407 12.9301 6 17 6 17"/>
|
||||
<path d="M6 9V17H14" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 460 B |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.2727 4H4V11.2727H11.2727V4Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M43.9998 36.7271H36.7271V43.9998H43.9998V36.7271Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M11.2727 24H4V31.2727H11.2727V24Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M23.9998 36.7271H16.7271V43.9998H23.9998V36.7271Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M31.2727 4H24V11.2727H31.2727V4Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M43.9998 16.7271H36.7271V23.9998H43.9998V16.7271Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M11.2729 7.63623H24.0002" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M24 40.3638H36.7273" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.2729 27.6366H27.6366V11.2729" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M28.8275 20.3633H36.7269M20.3633 36.7269V27.6282V36.7269Z" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7.63672 11.2725V23.9997" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M40.3633 24V36.7273" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="7" y="22.0476" width="34" height="22" rx="2" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/>
|
||||
<path d="M14 22V14.0047C13.9948 8.87022 17.9227 4.56718 23.0859 4.05117C28.249 3.53516 32.9673 6.97408 34 12.0059" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M24 30V36" stroke="#333" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 575 B |
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
|
||||
<path d="M512 273.194667A238.805333 238.805333 0 1 1 273.194667 512 238.805333 238.805333 0 0 1 512 273.194667M512 234.666667a277.333333 277.333333 0 1 0 277.333333 277.333333 277.333333 277.333333 0 0 0-277.333333-277.333333z"></path>
|
||||
<path d="M675.157333 556.928a14.677333 14.677333 0 0 0-12.8 7.445333 96 96 0 0 1-137.109333 24.661334 125.098667 125.098667 0 0 0-188.032 24.149333 14.208 14.208 0 0 0-1.28 2.133333 5.802667 5.802667 0 0 0-0.661333 1.408 14.656 14.656 0 0 0 24.149333 15.68 6.272 6.272 0 0 0 1.28-1.493333 96.832 96.832 0 0 1 13.248-16.490667 95.765333 95.765333 0 0 1 124.629333-9.301333 125.077333 125.077333 0 0 0 189.269334-26.176 5.824 5.824 0 0 0 0.682666-1.493333 14.634667 14.634667 0 0 0-13.44-20.437334z"></path>
|
||||
<path d="M593.834667 444.778667l-12.8 1.557333c-0.192 13.674667-0.384 27.733333-0.384 43.2v9.621333a89.6 89.6 0 0 1-47.296 12.8 76.16 76.16 0 0 1 1.173333-152.277333 81.066667 81.066667 0 0 1 42.666667 10.666667l-0.405334 33.813333h-11.648l-8.213333-32.426667a41.088 41.088 0 0 0-18.965333-4.117333c-29.333333 0-50.837333 23.104-50.837334 68.053333 0 42.666667 20.714667 68.266667 49.642667 68.266667a65.088 65.088 0 0 0 17.792-2.304v-12.8c0-14.272-0.192-27.946667-0.597333-42.026667l-21.461334-2.133333v-6.848h61.376z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,11 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="200"
|
||||
height="200">
|
||||
<path
|
||||
d="M600.7,404.1v-16.7c0-13-5.5-25.9-16.4-33.3l-54.8-44.5c-5.5-5.6-9.1-13-9.1-20.4v-66.7c0-13-11-24.1-23.7-24.1
|
||||
H260.9c-12.8,0-23.7,11.1-23.7,24.1v607.5c0,13,11,24.1,23.7,24.1h235.7c12.8,0,23.7-11.1,23.7-24.1v-35.2c0-14.8,11-25.9,25.6-25.9
|
||||
h12.8c23.7,0,43.8-20.4,43.8-44.5V656c62.1-7.4,111.4-61.1,111.4-125.9c0-29.6-9.1-57.4-27.4-77.8
|
||||
C675.4,430,626.2,407.8,600.7,404.1z M576.9,726.4h-1.8c0,9.3-7.3,18.5-18.3,18.5H544c-27.4,0-51.2,24.1-51.2,51.9v33.3H262.7V378.2
|
||||
h124.2v231.5c0,7.4,5.5,13,12.8,13s12.8-5.6,12.8-13V365.2c0-7.4-5.5-13-12.8-13h-137V224.4h232v64.8c0,16.7,7.3,31.5,20.1,40.7
|
||||
l54.8,44.5c3.7,3.7,7.3,9.3,7.3,13V726.4z M600.7,630.1V430c49.3,5.6,85.9,48.2,85.9,100C686.5,581.9,648.2,624.5,600.7,630.1z" fill-opacity="1"/>
|
||||
<polygon points="854.5,400.6 693.6,461.2 703,490.5 863.9,430"/>
|
||||
</svg>
|
After Width: | Height: | Size: 970 B |
@ -0,0 +1,5 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
|
||||
<text x="250" y="700" font-family="Microsoft YaHei" font-size="505" >文</text>
|
||||
</svg>
|
After Width: | Height: | Size: 244 B |
@ -0,0 +1,7 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M746.666667 213.333333h-469.333334C243.2 213.333333 213.333333 243.2 213.333333 277.333333v469.333334c0 34.133333 29.866667 64 64 64h469.333334c34.133333 0 64-29.866667 64-64v-469.333334c0-34.133333-29.866667-64-64-64zM256 439.466667h140.8v140.8H256v-140.8z m21.333333 328.533333c-12.8 0-21.333333-8.533333-21.333333-21.333333v-119.466667h140.8V768H277.333333z m307.2 0h-140.8v-140.8h140.8V768z m0-183.466667h-140.8v-140.8h140.8v140.8z m183.466667 162.133334c0 12.8-8.533333 21.333333-21.333333 21.333333h-119.466667v-140.8H768v119.466667z m0-162.133334h-140.8v-140.8H768v140.8z m0-187.733333H256V277.333333c0-12.8 8.533333-21.333333 21.333333-21.333333h469.333334c12.8 0 21.333333 8.533333 21.333333 21.333333v119.466667z"
|
||||
fill="#1296db"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 937 B |
@ -0,0 +1,10 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="3587" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M883.3 745H142.7c-41.9 0-76-34.1-76-76V351.6c0-41.9 34.1-76 76-76h740.6c41.9 0 76 34.1 76 76V669c0 41.9-34.1 76-76 76zM142.7 321.8c-16.4 0-29.8 13.3-29.8 29.8V669c0 16.4 13.3 29.8 29.8 29.8h740.6c16.4 0 29.8-13.3 29.8-29.8V351.6c0-16.4-13.3-29.8-29.8-29.8H142.7z"
|
||||
fill="#7D7D7D"></path>
|
||||
<path
|
||||
d="M191.3 576c-10.1 0-13.9 0.1-19.6 0.4 0.8-5.7 1.1-10.2 1.1-19.4v-72.4c0-7-0.3-12.7-1.1-19 6.7 0.4 8.6 0.4 19.4 0.4h34.7c21.4 0 34 10.3 34 27.8 0 8.1-2.6 14.4-7.7 18.9-2.9 2.5-5.3 3.8-10.7 5.8 6.5 1.5 9.9 3 13.8 6.4 5.7 5 8.6 12.2 8.6 20.9 0 19-13.5 30.3-36.5 30.3h-36z m30.6-67.6c7 0 11.4-4.1 11.4-10.6s-4.1-10.2-11.6-10.2h-23v20.8h23.2z m-23.2 45.8H223c8.3 0 13.4-4.6 13.4-12.4 0-7.7-5-12.2-13.5-12.2h-24.2v24.6z m186.2-88.3c-0.8 5.7-1.1 10.4-1.1 20v45.5c0 30.2-18.1 47.2-50 47.2-16.4 0-29.8-4.6-37.7-13-7.7-8.2-11.6-19.7-11.6-34.5v-45.2c0-9.1-0.3-14.9-1.1-20H312c-0.8 4.9-1.1 10.2-1.1 20v45.5c0 16.7 7.5 24.6 23 24.6 15.9 0 23.4-7.9 23.4-24.6v-45.5c0-9.9-0.3-14-1.1-20h28.7z m79.2 90.1c0 7.9 0.3 13.8 1.1 20H436c0.8-6.2 1.1-11.6 1.1-20v-66.7h-15.6c-8.3 0-10.6 0.1-20 0.9V465c4.4 0.5 11.6 0.9 19.7 0.9H479c9.3 0 14.5-0.3 20.6-0.9v25.3c-6-0.7-11.1-0.9-20.6-0.9h-14.9V556z m108.8 0c0 7.9 0.3 13.8 1.1 20h-29.2c0.8-6.2 1.1-11.6 1.1-20v-66.7h-15.6c-8.3 0-10.6 0.1-20 0.9V465c4.4 0.5 11.6 0.9 19.7 0.9h57.9c9.3 0 14.5-0.3 20.6-0.9v25.3c-6-0.7-11.1-0.9-20.6-0.9H573V556z m155.8-35.6c0 34.9-21.3 58.1-53.4 58.1-32.4 0-53.3-22.6-53.3-57.7 0-34.9 20.9-57.3 53.4-57.3 32.6 0 53.3 22.3 53.3 56.9z m-27.5 0.3c0-21.4-9.8-34.4-25.8-34.4-16.1 0-26.1 13.1-26.1 34.4 0 21.6 9.9 34.9 26.1 34.9 16 0 25.8-13.2 25.8-34.9z m110.6-0.7c3.8 5.7 6.3 9.9 9.5 15.7-0.5-6.1-0.8-12.2-0.8-19.6V486c0-8.7-0.3-14-1.1-20.1h28.2c-0.8 6-1.1 11.5-1.1 20.1v70.2c0 8.1 0.4 14.2 1.1 19.7h-29c-2.4-5-5.4-9.9-9.9-16.8l-24.5-36.9c-3.6-5.3-5.8-9.3-9.5-16.3 0.7 6 0.9 13.2 0.9 19.7v29.6c0 9.1 0.3 14.9 1.1 20.6h-28.2c0.8-5.2 1.1-11 1.1-20.8v-69.6c0-7.7-0.3-13.6-1.1-19.7h28.7c1.3 3.6 4.2 8.9 9.4 16.5l25.2 37.8z"
|
||||
fill="#7D7D7D"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,13 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="4650" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M767.1 292.6c-0.2-19-15.6-34.4-34.6-34.6l-202.2-2.5c-9.5-0.1-18.6 3.6-25.2 10.3l-35.4 35.4c48.4 138.5 72.4 282.3 42.1 433.8-1.7 10.4-3.9 21.1-6.4 31.9 6-1.5 11.7-4.4 16.3-9.1l237.6-237.6c6.7-6.7 10.4-15.8 10.3-25.2l-2.5-202.4zM664.3 429c-17.1 17.1-44.9 17.1-62 0s-17.1-44.9 0-62 44.9-17.1 62 0 17.2 44.8 0 62z"
|
||||
fill="#FFDE55"></path>
|
||||
<path
|
||||
d="M779.6 292.5c-0.2-12.5-5.1-24.2-13.9-33.1-8.8-8.8-20.6-13.8-33.1-13.9L530.4 243c-12.7-0.1-25.2 4.9-34.2 13.9L258.6 494.6c-9 9-13.9 20.9-13.9 33.6 0 12.7 4.9 24.7 13.9 33.6l204.7 204.7c9 9 20.9 13.9 33.6 13.9 12.7 0 24.7-4.9 33.6-13.9l237.6-237.6c9-9 14.1-21.5 13.9-34.2l-2.4-202.2z m-29.1 218.7L512.9 748.8c-4.3 4.3-9.9 6.6-16 6.6-6 0-11.7-2.3-16-6.6L276.3 544.2c-4.3-4.3-6.6-9.9-6.6-16s2.3-11.7 6.6-16l237.6-237.6c4.2-4.2 10-6.6 16-6.6h0.3l202.2 2.5c12.4 0.2 22.2 9.9 22.3 22.3l2.5 202.2c0 6-2.4 11.9-6.7 16.2z"
|
||||
fill=""></path>
|
||||
<path
|
||||
d="M593.5 358.1c-22 22-22 57.7 0 79.7 10.6 10.6 24.8 16.5 39.8 16.5s29.2-5.9 39.8-16.5c22-22 22-57.7 0-79.7-21.9-22-57.6-22-79.6 0z m62 62c-5.9 5.9-13.8 9.2-22.2 9.2s-16.2-3.3-22.2-9.2c-12.2-12.2-12.2-32.1 0-44.3 6.1-6.1 14.1-9.2 22.2-9.2 8 0 16.1 3.1 22.2 9.2 12.2 12.2 12.2 32.1 0 44.3z"
|
||||
fill=""></path>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,10 @@
|
||||
<svg t="1673874136249" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M538.4 504.4l280.9 144.3c9.9 5.1 22.2 0.5 26-10 14.3-38.7 22.1-80.6 22.1-124.3 0-186.2-141.6-339.3-323-357.5-7.9-0.8-14.7 5.3-14.7 13.3v320.1c0 5.9 3.4 11.4 8.7 14.1z"
|
||||
fill="#64B5F6"></path>
|
||||
<path
|
||||
d="M492.5 514.5V172.3c0-9.3-8-16.6-17.3-15.8C289 173.4 143.7 332.3 148.7 524.1c5 190.9 161.5 346.1 352.4 349.7 131.3 2.5 246.8-65.5 311.5-168.7 4.6-7.3 2-17-5.7-21L499.8 526.4c-4.5-2.3-7.3-6.9-7.3-11.9z"
|
||||
fill="#1E88E5"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 665 B |
@ -0,0 +1,10 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="200"
|
||||
height="200">
|
||||
<rect transform="rotate(180,427,410)" x="0" y="0" width="680" height="400" stroke="none">
|
||||
<animate attributeName="height" from="0" to="400" dur="5s" repeatCount="indefinite" />
|
||||
</rect>
|
||||
<polygon
|
||||
points="283.2,131 87.7,129.1 85.1,911.2 938.9,911.2 938.9,131 740.8,131 740.8,241.3 849,245.4 853.1,807.1
|
||||
177.1,799.2 181.1,246.6 283.2,245 "
|
||||
stroke-width="10" />
|
||||
</svg>
|
After Width: | Height: | Size: 478 B |
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
|
||||
<path d="M500.181333 308.757333a118.421333 118.421333 0 1 1-118.421333 118.421334 118.421333 118.421333 0 0 1 118.421333-118.421334m0-19.2a137.514667 137.514667 0 1 0 137.514667 137.514667 137.514667 137.514667 0 0 0-137.514667-137.514667z"></path>
|
||||
<path d="M500.181333 478.741333a118.421333 118.421333 0 1 1-118.421333 118.421334 118.421333 118.421333 0 0 1 118.421333-118.421334m0-19.2a137.514667 137.514667 0 1 0 137.514667 137.514667 137.514667 137.514667 0 0 0-137.514667-137.514667z"></path>
|
||||
<path d="M500.266667 234.666667a9.557333 9.557333 0 0 1 9.557333 9.557333v54.869333a9.557333 9.557333 0 0 1-9.557333 9.557334 9.557333 9.557333 0 0 1-9.557334-9.557334v-54.848A9.557333 9.557333 0 0 1 500.266667 234.666667z"></path>
|
||||
<path d="M500.266667 715.349333a9.557333 9.557333 0 0 1 9.557333 9.557334v54.890666a9.557333 9.557333 0 0 1-9.557333 9.557334 9.557333 9.557333 0 0 1-9.557334-9.557334v-54.869333a9.557333 9.557333 0 0 1 9.557334-9.578667z"></path>
|
||||
<path d="M500.266667 446.357333a10.666667 10.666667 0 0 1-10.218667-6.186666l-36.053333-77.312a10.666667 10.666667 0 0 1 5.205333-14.186667 10.666667 10.666667 0 0 1 14.101333 5.205333l26.986667 57.728 26.922667-57.728a10.666667 10.666667 0 0 1 14.186666-5.205333 10.666667 10.666667 0 0 1 5.12 14.186667l-36.053333 77.312a10.666667 10.666667 0 0 1-9.664 6.208z"></path>
|
||||
<path d="M500.266667 681.024a10.666667 10.666667 0 0 1-10.218667-6.186667l-36.053333-77.312a10.666667 10.666667 0 0 1 5.205333-14.186666 10.666667 10.666667 0 0 1 14.101333 5.205333l26.986667 57.728 26.922667-57.728a10.666667 10.666667 0 0 1 14.186666-5.205333 10.666667 10.666667 0 0 1 5.12 14.186666l-36.053333 77.312a10.666667 10.666667 0 0 1-9.664 6.208z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -1,20 +0,0 @@
|
||||
<template>
|
||||
<n-card title="操作说明" embedded :bordered="false">
|
||||
<ul>
|
||||
<li>常规组件和图表组件用鼠标左键选中并按住可拖动至画布</li>
|
||||
<li>绘制组件需先选中 再将鼠标移至画布中按住左键开始绘制 松开左键结束绘制</li>
|
||||
<li>在画布上单击左键并按住可以拖动组件改变位置</li>
|
||||
<li>当组件选中时会有选中效果 此时右侧面板弹出 可使用快捷键和编辑右侧面板属性更改组件</li>
|
||||
<li>鼠标右键点击组件可以进行一些快捷操作</li>
|
||||
<li>键盘↑↓←→可移动选中组件 ctrl+c复制当前选中组件 deleted删除当前选中组件</li>
|
||||
<li>ctrl+键盘↑↓←→可移动组件图层</li>
|
||||
<li>点击画布空白处可以取消选中组件 并关闭属性面板</li>
|
||||
<li>点击《 符号可以显示或隐藏左侧面板</li>
|
||||
<li>如果使用我的在线体验地址 请先保存绘制再切换到预览界面</li>
|
||||
<li>更多使用帮助请参考<a href="https://github.com/yaolunmao/vue-webtopo-svgeditor">github</a>或<a href="https://gitee.com/yaolunmao/vue-webtopo-svgeditor">gitee</a></li>
|
||||
</ul>
|
||||
</n-card>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { NCard } from "naive-ui";
|
||||
</script>
|
@ -1,155 +0,0 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { ChevronDoubleLeft20Regular, ChevronDoubleRight20Regular } from '@vicons/fluent';
|
||||
import { NIcon, NCollapse, NCollapseItem, useMessage } from "naive-ui";
|
||||
import { ILeftImgLists, IComponentInfo } from "../Model";
|
||||
const emit = defineEmits(['setCreatSvgInfo'])
|
||||
const message = useMessage();
|
||||
const props = defineProps({
|
||||
left_imglists: {
|
||||
type: Object as () => ILeftImgLists,
|
||||
default: []
|
||||
},
|
||||
//选中的左侧工具图标
|
||||
select_toolbar: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const leftnav = reactive({
|
||||
navclass: 'leftnavDisplay',
|
||||
navopen: true
|
||||
});
|
||||
const clickHandleIcon = () => {
|
||||
leftnav.navopen = !leftnav.navopen;
|
||||
leftnav.navclass = leftnav.navclass == 'leftnavDisplay' ? 'leftnavNone' : 'leftnavDisplay'
|
||||
};
|
||||
const dragStartEvent = (leftImgItem: IComponentInfo, e: DragEvent) => {
|
||||
//设置要创建的svg组件信息
|
||||
emit('setCreatSvgInfo', leftImgItem);
|
||||
}
|
||||
const dragEndEvent = (leftImgItem: IComponentInfo, e: DragEvent) => {
|
||||
//拖动时记录拖动的svg信息
|
||||
if (e.dataTransfer?.dropEffect !== 'copy') {
|
||||
message.error('请将组件拖到画布中!');
|
||||
//清空已选择的信息
|
||||
emit('setCreatSvgInfo', {});
|
||||
return;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div :class="leftnav.navclass">
|
||||
<div class="svgimg" v-show="leftnav.navopen">
|
||||
<n-collapse default-expanded-names="1" accordion>
|
||||
<n-collapse-item title="常规组件" name="1" style="margin-top: 15px;">
|
||||
<ul class="leftImgUl">
|
||||
<li v-for="leftImgItem in props.left_imglists.commonComponentList">
|
||||
<img
|
||||
:title="leftImgItem.title"
|
||||
:src="leftImgItem.priview_img"
|
||||
draggable="true"
|
||||
@dragstart="dragStartEvent(leftImgItem, $event)"
|
||||
@dragend="dragEndEvent(leftImgItem, $event)"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</n-collapse-item>
|
||||
<n-collapse-item title="绘制组件" name="2">
|
||||
<ul class="leftImgUl">
|
||||
<li v-for="leftImgItem in props.left_imglists.drawComponentList">
|
||||
<img
|
||||
:class="props.select_toolbar == leftImgItem.type ? 'svg-selected' : ''"
|
||||
:title="leftImgItem.title"
|
||||
:src="leftImgItem.priview_img"
|
||||
@click="() => { emit('setCreatSvgInfo', leftImgItem) }"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</n-collapse-item>
|
||||
<n-collapse-item title="图表组件" name="3">
|
||||
<ul class="leftImgUl">
|
||||
<li v-for="leftImgItem in props.left_imglists.chartComponentList">
|
||||
<img
|
||||
:title="leftImgItem.title"
|
||||
:src="leftImgItem.priview_img"
|
||||
draggable="true"
|
||||
@dragstart="dragStartEvent(leftImgItem, $event)"
|
||||
@dragend="dragEndEvent(leftImgItem, $event)"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
</div>
|
||||
<div class="handlehidden">
|
||||
<n-icon class="handleicon" size="10" @click="clickHandleIcon">
|
||||
<chevron-double-left20-regular v-if="leftnav.navopen" />
|
||||
<chevron-double-right20-regular v-else />
|
||||
</n-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.leftnavDisplay,
|
||||
.leftnavNone {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
.leftnavDisplay {
|
||||
width: 210px;
|
||||
}
|
||||
.leftnavNone {
|
||||
width: 10px;
|
||||
}
|
||||
.svgimg {
|
||||
/* background-color: green; */
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: overlay;
|
||||
}
|
||||
.svgimg::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.handlehidden {
|
||||
height: 100%;
|
||||
width: 10px;
|
||||
background-color: grey;
|
||||
}
|
||||
.handleicon {
|
||||
top: 50%;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.leftImgUl {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.leftImgUl li {
|
||||
width: calc(33.33% - 30px);
|
||||
margin: 0 15px 15px 15px;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
box-shadow: 1px 1px 5px #ddd;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
}
|
||||
.leftImgUl li :hover {
|
||||
box-shadow: 1px 1px 10px #ccc;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.leftImgUl img {
|
||||
width: 100%;
|
||||
}
|
||||
.svg-selected {
|
||||
outline: 1px solid #0cf;
|
||||
}
|
||||
</style>
|
@ -1,81 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue";
|
||||
import { NForm, NFormItem, NInput, NInputNumber, NColorPicker, NRadioGroup, NSpace, NRadio,NSelect } from "naive-ui";
|
||||
import { ISvgDataLists } from "../Model";
|
||||
|
||||
const props = defineProps({
|
||||
set_svg_info: {
|
||||
type: Object as () => ISvgDataLists,
|
||||
default: {}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="rightnav">
|
||||
<div style="margin-left: 2rem;margin-top: 1rem;">
|
||||
<n-form size="small" label-placement="left">
|
||||
<n-form-item label="标识">
|
||||
<span>{{ props.set_svg_info.id }}</span>
|
||||
</n-form-item>
|
||||
<n-form-item label="类型">
|
||||
<span>{{ props.set_svg_info.type }}</span>
|
||||
</n-form-item>
|
||||
<n-form-item label="名称">
|
||||
<n-input placeholder="请输入名称" v-model:value="props.set_svg_info.title" />
|
||||
</n-form-item>
|
||||
<n-form-item label="x轴坐标">
|
||||
<n-input-number v-model:value="props.set_svg_info.svgPositionX" :min="0" />
|
||||
</n-form-item>
|
||||
<n-form-item label="y轴坐标">
|
||||
<n-input-number v-model:value="props.set_svg_info.svgPositionY" :min="0" />
|
||||
</n-form-item>
|
||||
<n-form-item label="大小">
|
||||
<n-input-number v-model:value="props.set_svg_info.size" :min="1" :step="0.1" />
|
||||
</n-form-item>
|
||||
<n-form-item label="旋转">
|
||||
<n-input-number v-model:value="props.set_svg_info.angle" />
|
||||
</n-form-item>
|
||||
<n-form-item v-for="item in props.set_svg_info.extend_attr" :label="item.title">
|
||||
<n-input-number v-if="item.type == 'numberinputbox'" v-model:value="item.val" />
|
||||
<n-color-picker
|
||||
v-else-if="item.type == 'colorinputbox'"
|
||||
:modes="['hex']"
|
||||
v-model:value="item.val"
|
||||
/>
|
||||
<n-input
|
||||
v-else-if="item.type == 'textinputbox'"
|
||||
:placeholder="`请输入${item.title}`"
|
||||
v-model:value="item.val"
|
||||
/>
|
||||
<n-input
|
||||
v-else-if="item.type == 'textareainputbox'"
|
||||
:placeholder="`请输入${item.title}`"
|
||||
type="textarea"
|
||||
v-model:value="item.val"
|
||||
/>
|
||||
<n-radio-group v-model:value="item.val.selectval" v-else-if="item.type == 'radiogroup'">
|
||||
<n-space>
|
||||
<n-radio
|
||||
v-for="ridioitem in item.val.ridiogroup"
|
||||
:key="ridioitem.value"
|
||||
:value="ridioitem.value"
|
||||
>{{ ridioitem.label }}</n-radio>
|
||||
</n-space>
|
||||
</n-radio-group>
|
||||
<n-select v-else-if="item.type == 'select'" v-model:value="item.val.selectval" :options="item.val.selectgroup" />
|
||||
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.rightnav {
|
||||
width: 250px;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
.rightnav::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
@ -1,50 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, createApp, markRaw,provide } from "vue";
|
||||
import { use } from "echarts/core";
|
||||
import { SVGRenderer } from "echarts/renderers";
|
||||
import { PieChart,BarChart } from "echarts/charts";
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
GridComponent
|
||||
} from "echarts/components";
|
||||
import { THEME_KEY } from "vue-echarts";
|
||||
use([
|
||||
SVGRenderer,
|
||||
PieChart,
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
LegendComponent,
|
||||
GridComponent,
|
||||
BarChart
|
||||
]);
|
||||
provide(THEME_KEY, "default")
|
||||
const props = defineProps({
|
||||
component_type: {
|
||||
type: String as () => any,
|
||||
default: ''
|
||||
},
|
||||
component_template: {
|
||||
type: String as () => any,
|
||||
default: ''
|
||||
},
|
||||
component_props: {
|
||||
type: Array as () => Array<any>,
|
||||
default: ''
|
||||
},
|
||||
component_attr: {
|
||||
type: Object as () => any,
|
||||
default: {}
|
||||
},
|
||||
});
|
||||
const component_info = markRaw({
|
||||
template: props.component_template,
|
||||
props: ['prop_data']
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="component_info" :prop_data="props.component_attr"></component>
|
||||
</template>
|
||||
|
@ -1,555 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, Ref, ref, watch } from 'vue';
|
||||
import TopToolBar from './TopBar.vue';
|
||||
import LeftToolBar from './LeftToolBar.vue';
|
||||
import RightToolBar from './RightToolBar.vue';
|
||||
import BottomBar from './BottomBar.vue';
|
||||
import { NMessageProvider } from "naive-ui";
|
||||
import { IComponentInfo, ISvgDataLists, ISvgCanvas, ILeftImgLists, IMouseInfo, ISelectSvg } from "../Model";
|
||||
import SvgDynamic from "./SvgDynamic.vue";
|
||||
import "../assets/css/svgAnimation/index.css";
|
||||
import { moveUp, moveDown, moveLeft, moveRight, hotkeyCopy, hotkeyDel, hotkeyPutOnTop, hotkeyPutOnButtom, hotkeyPutOnUp, hotkeyPutOnDown } from "../func/HotkeyFunc";
|
||||
const emit = defineEmits(['saveSvgInfo']);
|
||||
const props = defineProps({
|
||||
//组件的json格式
|
||||
component_infos: {
|
||||
type: Array as () => Array<IComponentInfo>,
|
||||
required: true,
|
||||
default: []
|
||||
},
|
||||
svgCanvas: {
|
||||
type: Object as () => ISvgCanvas,
|
||||
default: { width: 1520, height: 720 }
|
||||
}
|
||||
});
|
||||
const svg_dom_ref = ref<null | HTMLElement>(null);
|
||||
const contextMenuRef = ref<HTMLElement>();
|
||||
const svgLists: ISvgDataLists[] = reactive([]);
|
||||
const topbar_dom_ref = ref(null);
|
||||
//显示右键菜单
|
||||
const display_contextmenu = ref(false);
|
||||
//右键菜单数据
|
||||
const contextmenu_data = reactive([{
|
||||
name: "复制",
|
||||
hotkey: "Ctrl+C",
|
||||
enable: true,
|
||||
fun: function () {
|
||||
if (!this.enable) {
|
||||
return;
|
||||
}
|
||||
hotkeyCopy(svgLists, select_svg);
|
||||
display_contextmenu.value = false;
|
||||
}
|
||||
}, {
|
||||
name: "删除",
|
||||
hotkey: "Delete",
|
||||
enable: false,
|
||||
fun: function () {
|
||||
if (!this.enable) {
|
||||
return;
|
||||
}
|
||||
hotkeyDel(svgLists, select_svg);
|
||||
display_contextmenu.value = false;
|
||||
}
|
||||
}, {
|
||||
name: "置于顶层",
|
||||
hotkey: "Ctrl+→",
|
||||
enable: true,
|
||||
fun: function () {
|
||||
if (!this.enable) {
|
||||
return;
|
||||
}
|
||||
hotkeyPutOnTop(svgLists, select_svg);
|
||||
display_contextmenu.value = false;
|
||||
}
|
||||
}, {
|
||||
name: "置于底层",
|
||||
hotkey: "Ctrl+←",
|
||||
enable: true,
|
||||
fun: function () {
|
||||
if (!this.enable) {
|
||||
return;
|
||||
}
|
||||
hotkeyPutOnButtom(svgLists, select_svg);
|
||||
display_contextmenu.value = false;
|
||||
}
|
||||
}, {
|
||||
name: "置于上一层",
|
||||
hotkey: "Ctrl+↑",
|
||||
enable: true,
|
||||
fun: function () {
|
||||
if (!this.enable) {
|
||||
return;
|
||||
}
|
||||
hotkeyPutOnUp(svgLists, select_svg);
|
||||
display_contextmenu.value = false;
|
||||
}
|
||||
}, {
|
||||
name: "置于下一层",
|
||||
hotkey: "Ctrl+↓",
|
||||
enable: true,
|
||||
fun: function () {
|
||||
if (!this.enable) {
|
||||
return;
|
||||
}
|
||||
hotkeyPutOnDown(svgLists, select_svg);
|
||||
display_contextmenu.value = false;
|
||||
}
|
||||
}]);
|
||||
const set_svg_info: Ref<ISvgDataLists> = ref({
|
||||
id: '', title: '', svgPositionX: 0, svgPositionY: 0
|
||||
});
|
||||
//选中的svg
|
||||
const select_svg: ISelectSvg = reactive({
|
||||
id: '',
|
||||
index: 0,
|
||||
sPositionX: 0,
|
||||
sPositionY: 0,
|
||||
create_type: ''
|
||||
});
|
||||
//选中的左侧工具栏的svg
|
||||
const select_lefttool: Ref<IComponentInfo> = ref({});
|
||||
//左侧工具栏svg列表
|
||||
const leftimg_lists: Ref<ILeftImgLists> = ref({
|
||||
commonComponentList: [],
|
||||
drawComponentList: [],
|
||||
chartComponentList: []
|
||||
});
|
||||
//选中的左侧工具栏
|
||||
const select_toolbar: Ref<string | undefined> = ref('');
|
||||
//记录鼠标信息
|
||||
const mouseInfo: IMouseInfo = reactive({
|
||||
status: 0,
|
||||
mPositionX: 0,
|
||||
mPositionY: 0
|
||||
});
|
||||
const rightnav_open = ref(false);
|
||||
/**
|
||||
* @description: 从左侧工具栏拖动组件到画布触发的事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const dropEvent = (e: DragEvent) => {
|
||||
//当左侧工具栏拖动到此处时在画布上创建该组件
|
||||
if (Object.keys(select_lefttool.value).length < 1) {
|
||||
//未选择任何组件
|
||||
return;
|
||||
}
|
||||
//在鼠标位置创建当前组件
|
||||
const create_svg: ISvgDataLists = {
|
||||
id: `${new Date().getTime()}`,
|
||||
type: select_lefttool.value.type,
|
||||
title: select_lefttool.value.title,
|
||||
svgPositionX: e.offsetX,
|
||||
svgPositionY: e.offsetY,
|
||||
angle: 0,
|
||||
size: 1,
|
||||
extend_attr: JSON.parse(JSON.stringify(select_lefttool.value.extend_attr))
|
||||
}
|
||||
svgLists.push(create_svg);
|
||||
//清空左侧工具选中
|
||||
select_lefttool.value = {};
|
||||
|
||||
}
|
||||
const dragEnterEvent = (e: DragEvent) => {
|
||||
//dragenter和dragover一定要阻止浏览器默认行为 不然不会触发drop
|
||||
rightnav_open.value = false;
|
||||
e.preventDefault();
|
||||
}
|
||||
const dragOverEvent = (e: DragEvent) => {
|
||||
//dragenter和dragover一定要阻止浏览器默认行为 不然不会触发drop
|
||||
e.preventDefault();
|
||||
}
|
||||
/**
|
||||
* @description: 设置要创建组件的信息
|
||||
* @param {*} createsvg_info 选中的组件信息
|
||||
* @return {*}
|
||||
*/
|
||||
const setCreatSvgInfo = (createsvg_info: IComponentInfo) => {
|
||||
select_lefttool.value = createsvg_info;
|
||||
select_toolbar.value = createsvg_info.type;
|
||||
}
|
||||
/**
|
||||
* @description: 保存绘制组件后的数据和svgdom
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const saveSvgInfo = () => {
|
||||
if (svgLists.length == 0) {
|
||||
(topbar_dom_ref.value as any).saveSvgInfoRes({ code: 2, msg: '请先绘制图像!' });
|
||||
return;
|
||||
}
|
||||
(topbar_dom_ref.value as any).saveSvgInfoRes(svgLists.length > 0 ? { code: 1, msg: '保存成功!' } : { code: 0, msg: '保存失败!' });
|
||||
emit('saveSvgInfo', svgLists, svg_dom_ref.value)
|
||||
}
|
||||
/**
|
||||
* @description: 鼠标点击画布上svg触发事件
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const mouseDownEvent = (selectsvg: ISvgDataLists, index: number, e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.cancelBubble = true;
|
||||
//清空左侧工具选中
|
||||
select_lefttool.value = {};
|
||||
//鼠标在画布上的组件按下记录选中的组件信息和鼠标位置信息等
|
||||
({ id: select_svg.id, svgPositionX: select_svg.sPositionX, svgPositionY: select_svg.sPositionY } = selectsvg);
|
||||
rightnav_open.value = false;
|
||||
select_svg.index = index;
|
||||
select_svg.create_type = "draggable"
|
||||
mouseInfo.status = 1;
|
||||
mouseInfo.mPositionX = e.clientX;
|
||||
mouseInfo.mPositionY = e.clientY;
|
||||
}
|
||||
const mouseMoveEvent = (e: MouseEvent) => {
|
||||
//如果鼠标不是按下状态或者没有选择组件
|
||||
if (mouseInfo.status != 1 || !select_svg.id) {
|
||||
return;
|
||||
}
|
||||
const { clientX, clientY } = e;
|
||||
if (select_svg.create_type == "draggable") {
|
||||
let new_select_svg = { ...select_svg };
|
||||
new_select_svg.sPositionX += clientX - mouseInfo.mPositionX;
|
||||
new_select_svg.sPositionY += clientY - mouseInfo.mPositionY;
|
||||
//更新视图
|
||||
({ sPositionX: svgLists[select_svg.index].svgPositionX, sPositionY: svgLists[select_svg.index].svgPositionY } = new_select_svg);
|
||||
}
|
||||
else if (select_svg.create_type == "draw") {
|
||||
//拓展属性里未配置的属性不进行赋值
|
||||
if (svgLists[select_svg.index].extend_attr?.startpoint_x?.val != null) {
|
||||
svgLists[select_svg.index].extend_attr.startpoint_x.val = 0;
|
||||
}
|
||||
if (svgLists[select_svg.index].extend_attr?.startpoint_y?.val != null) {
|
||||
svgLists[select_svg.index].extend_attr.startpoint_y.val = 0;
|
||||
}
|
||||
if (svgLists[select_svg.index].extend_attr?.endpoint_x?.val != null) {
|
||||
svgLists[select_svg.index].extend_attr.endpoint_x.val = clientX - mouseInfo.mPositionX;
|
||||
}
|
||||
if (svgLists[select_svg.index].extend_attr?.endpoint_y?.val != null) {
|
||||
svgLists[select_svg.index].extend_attr.endpoint_y.val = clientY - mouseInfo.mPositionY;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const mouseUpEvent = (e: MouseEvent) => {
|
||||
//如果鼠标不是按下状态或者没有选择组件
|
||||
if (mouseInfo.status != 1 || !select_svg.id) {
|
||||
return;
|
||||
}
|
||||
mouseInfo.status = 0;
|
||||
rightnav_open.value = true;
|
||||
set_svg_info.value = svgLists[select_svg.index];
|
||||
//清空左侧工具选中
|
||||
select_lefttool.value = {};
|
||||
select_toolbar.value = '';
|
||||
|
||||
}
|
||||
/**
|
||||
* @description: 鼠标点击画布
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const mouseDownCanvasEvent = (e: MouseEvent) => {
|
||||
//判断当前是否有选中的工具栏
|
||||
if (Object.keys(select_lefttool.value).length < 1) {
|
||||
rightnav_open.value = false;
|
||||
select_svg.id = '';
|
||||
return;
|
||||
}
|
||||
//在当前位置创建要绘制的组件
|
||||
const create_svg: ISvgDataLists = {
|
||||
id: `${new Date().getTime()}`,
|
||||
type: select_lefttool.value.type,
|
||||
title: select_lefttool.value.title,
|
||||
svgPositionX: e.offsetX,
|
||||
svgPositionY: e.offsetY,
|
||||
angle: 0,
|
||||
size: 1,
|
||||
extend_attr: JSON.parse(JSON.stringify(select_lefttool.value.extend_attr))//这个响应式对象我治不了了 所以只能写两次转换
|
||||
}
|
||||
svgLists.push(create_svg);
|
||||
//设置全局选中的组件信息
|
||||
({ id: select_svg.id, svgPositionX: select_svg.sPositionX, svgPositionY: select_svg.sPositionY } = create_svg);
|
||||
rightnav_open.value = false;
|
||||
select_svg.index = svgLists.length - 1;
|
||||
select_svg.create_type = "draw"
|
||||
mouseInfo.status = 1;
|
||||
mouseInfo.mPositionX = e.clientX;
|
||||
mouseInfo.mPositionY = e.clientY;
|
||||
}
|
||||
/**
|
||||
* @description: 鼠标右键
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const contextmenuEvent = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
display_contextmenu.value = true;
|
||||
(contextMenuRef.value as any).style.left = e.pageX + 'px';
|
||||
(contextMenuRef.value as any).style.top = e.pageY + 'px';
|
||||
contextmenu_data.map(m => m.enable = true);
|
||||
//判断当前选中组件的index
|
||||
if (svgLists.length === 1) {
|
||||
//禁用下移
|
||||
contextmenu_data[3].enable = false;
|
||||
contextmenu_data[5].enable = false;
|
||||
//禁用上移
|
||||
contextmenu_data[2].enable = false;
|
||||
contextmenu_data[4].enable = false;
|
||||
}
|
||||
else if (select_svg.index === 0) {
|
||||
//禁用下移
|
||||
contextmenu_data[3].enable = false;
|
||||
contextmenu_data[5].enable = false;
|
||||
|
||||
}
|
||||
else if (select_svg.index === svgLists.length - 1) {
|
||||
//禁用上移
|
||||
contextmenu_data[2].enable = false;
|
||||
contextmenu_data[4].enable = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 点击页面其他位置隐藏右键菜单
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
const documentClickEvent = (e: MouseEvent) => {
|
||||
if (e.button !== 2) {
|
||||
display_contextmenu.value = false;
|
||||
|
||||
}
|
||||
}
|
||||
watch(() => [...props.component_infos], (newval, oldval) => {
|
||||
leftimg_lists.value = {
|
||||
commonComponentList: newval.filter(f => f.panel_class == 'common'),
|
||||
drawComponentList: newval.filter(f => f.panel_class == 'draw'),
|
||||
chartComponentList: newval.filter(f => f.panel_class == 'chart')
|
||||
};
|
||||
});
|
||||
//监听键盘
|
||||
document.onkeydown = function (e) {
|
||||
//如果没选中组件
|
||||
if (!select_svg.id) {
|
||||
return;
|
||||
}
|
||||
if (!e.ctrlKey && e.key == 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
moveUp(svgLists, select_svg);
|
||||
} else if (!e.ctrlKey && e.key == 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
moveDown(svgLists, select_svg);
|
||||
} else if (!e.ctrlKey && e.key == 'ArrowLeft') {
|
||||
e.preventDefault();
|
||||
moveLeft(svgLists, select_svg);
|
||||
} else if (!e.ctrlKey && e.key == 'ArrowRight') {
|
||||
e.preventDefault();
|
||||
moveRight(svgLists, select_svg);
|
||||
}
|
||||
//ctrl c
|
||||
else if (e.ctrlKey && e.key.toLowerCase() == 'c') {
|
||||
e.preventDefault();
|
||||
hotkeyCopy(svgLists, select_svg);
|
||||
}
|
||||
//deleted
|
||||
else if (e.key == 'Delete') {
|
||||
e.preventDefault();
|
||||
hotkeyDel(svgLists, select_svg);
|
||||
rightnav_open.value = false;
|
||||
}
|
||||
//上移一层
|
||||
else if (e.ctrlKey && e.key == 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
hotkeyPutOnUp(svgLists, select_svg);
|
||||
}
|
||||
//下移一层
|
||||
else if (e.ctrlKey && e.key == 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
hotkeyPutOnDown(svgLists, select_svg);
|
||||
}
|
||||
//置于底层
|
||||
else if (e.ctrlKey && e.key == 'ArrowLeft') {
|
||||
e.preventDefault();
|
||||
hotkeyPutOnButtom(svgLists, select_svg);
|
||||
}
|
||||
//置于顶层
|
||||
else if (e.ctrlKey && e.key == 'ArrowRight') {
|
||||
e.preventDefault();
|
||||
hotkeyPutOnTop(svgLists, select_svg);
|
||||
}
|
||||
}
|
||||
const setSvgLists = (new_val: ISvgDataLists[]) => {
|
||||
svgLists.length = 0;
|
||||
svgLists.push(...new_val);
|
||||
emit('saveSvgInfo', svgLists, svg_dom_ref.value)
|
||||
}
|
||||
defineExpose({
|
||||
setSvgLists
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="navtop">
|
||||
<n-message-provider>
|
||||
<top-tool-bar @saveSvgInfo="saveSvgInfo" ref="topbar_dom_ref"></top-tool-bar>
|
||||
</n-message-provider>
|
||||
</div>
|
||||
<div class="ancestors" @mousedown="documentClickEvent">
|
||||
<div class="navleft">
|
||||
<n-message-provider>
|
||||
<left-tool-bar
|
||||
:left_imglists="leftimg_lists"
|
||||
:select_toolbar="select_toolbar"
|
||||
@setCreatSvgInfo="setCreatSvgInfo"
|
||||
></left-tool-bar>
|
||||
</n-message-provider>
|
||||
</div>
|
||||
<div
|
||||
class="warp"
|
||||
@drop="dropEvent"
|
||||
@dragenter="dragEnterEvent"
|
||||
@dragover="dragOverEvent"
|
||||
@mousemove="mouseMoveEvent"
|
||||
@mouseup="mouseUpEvent"
|
||||
@mousedown="mouseDownCanvasEvent"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style="background-color:#000000;"
|
||||
:width="svgCanvas.width"
|
||||
:height="svgCanvas.height"
|
||||
:viewBox="`0 0 ${svgCanvas.width} ${svgCanvas.height}`"
|
||||
ref="svg_dom_ref"
|
||||
>
|
||||
<defs />
|
||||
<filter x="0" y="0" width="1" height="1" id="solid">
|
||||
<feFlood flood-color="rgb(255,255,255)" />
|
||||
<feComposite in="SourceGraphic" />
|
||||
</filter>
|
||||
<g
|
||||
style="cursor:pointer"
|
||||
:class="item.id == select_svg.id ? 'svg-selected' : ''"
|
||||
v-for="(item,index) in svgLists"
|
||||
:key="item.id"
|
||||
:id="item.id"
|
||||
:transform="'translate(' + (item.svgPositionX) + ',' + (item.svgPositionY) + ')' + 'rotate(' + item.angle + ')' + 'scale(' + item.size + ')'"
|
||||
@mousedown="mouseDownEvent(item, index, $event)"
|
||||
@contextmenu.stop="contextmenuEvent"
|
||||
>
|
||||
<svg-dynamic
|
||||
:component_type="item.type"
|
||||
:component_template="props.component_infos.filter(f => f.type == item.type)[0].template"
|
||||
:component_props="props.component_infos.filter(f => f.type == item.type)[0].props"
|
||||
:component_attr="item"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="navright" v-show="rightnav_open">
|
||||
<right-tool-bar :set_svg_info="set_svg_info"></right-tool-bar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navbuttom">
|
||||
<bottom-bar></bottom-bar>
|
||||
</div>
|
||||
<!-- 右键菜单 -->
|
||||
<ul ref="contextMenuRef" class="contextMenu" v-show="display_contextmenu">
|
||||
<li v-for="(item,index) in contextmenu_data" :key="index" @click="item.fun()">
|
||||
<p :class="item.enable ? '' : 'disabled'">
|
||||
{{ item.name }}
|
||||
<span class="shortcut">{{ item.hotkey }}</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.contextMenu {
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
background: #ffffff;
|
||||
padding: 5px 0;
|
||||
margin: 0px;
|
||||
display: block;
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 5px 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.contextMenu li {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.contextMenu .shortcut {
|
||||
width: 115px;
|
||||
text-align: right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.contextMenu p {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 0px 15px 1px 20px;
|
||||
margin: 0;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.contextMenu p:hover {
|
||||
background-color: #0cf;
|
||||
color: #ffffff;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.contextMenu .disabled {
|
||||
color: #999;
|
||||
}
|
||||
.contextMenu .disabled:hover {
|
||||
color: #999;
|
||||
background-color: transparent;
|
||||
}
|
||||
.contextMenu li.separator {
|
||||
border-top: solid 1px #e3e3e3;
|
||||
padding-top: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.ancestors {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.ancestors .navleft {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
/* border-left: solid 1px rgb(239, 239, 245); */
|
||||
}
|
||||
.ancestors .warp {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.ancestors .navright {
|
||||
width: auto;
|
||||
height: 100%;
|
||||
/*background-color: aqua;*/
|
||||
}
|
||||
.navtop {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
border-bottom: solid 1px rgb(239, 239, 245);
|
||||
}
|
||||
.navbuttom {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
}
|
||||
.svg-selected {
|
||||
outline: 1px solid #0cf;
|
||||
}
|
||||
.warp::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
@ -1,46 +0,0 @@
|
||||
<template>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style="background-color:#000000;"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:viewBox="`0 0 ${props.svgCanvas.width} ${props.svgCanvas.height}`"
|
||||
>
|
||||
<g
|
||||
v-for="(item,index) in props.svg_data"
|
||||
:key="item.id"
|
||||
:id="item.id"
|
||||
:transform="'translate(' + (item.svgPositionX) + ',' + (item.svgPositionY) + ')' + 'rotate(' + item.angle + ')' + 'scale(' + item.size + ')'"
|
||||
>
|
||||
<svg-dynamic
|
||||
:component_type="item.type"
|
||||
:component_template="props.component_infos.filter(f => f.type == item.type)[0].template"
|
||||
:component_props="props.component_infos.filter(f => f.type == item.type)[0].props"
|
||||
:component_attr="item"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import SvgDynamic from "./SvgDynamic.vue";
|
||||
import { ISvgDataLists, ISvgCanvas, IComponentInfo } from "../Model";
|
||||
import "../assets/css/svgAnimation/index.css";
|
||||
const props = defineProps({
|
||||
//组件的json格式
|
||||
component_infos: {
|
||||
type: Array as () => Array<IComponentInfo>,
|
||||
required: true,
|
||||
default: []
|
||||
},
|
||||
//要渲染的数据
|
||||
svg_data: {
|
||||
type: Array as () => Array<ISvgDataLists>,
|
||||
required: true,
|
||||
default: []
|
||||
},
|
||||
svgCanvas: {
|
||||
type: Object as () => ISvgCanvas,
|
||||
default: { width: 1520, height: 720 }
|
||||
}
|
||||
});
|
||||
</script>
|
@ -1,68 +0,0 @@
|
||||
<template>
|
||||
<div style="padding: 10px;display: flex;">
|
||||
<img title="基于vue3+ts+svg的web组件编辑器" class="logoimg" src="../assets/logo.png" />
|
||||
<span class="logotext">vue-webtopo-svgeditor</span>
|
||||
<div style="display: flex;width: 100%;flex-direction: row-reverse;">
|
||||
<a href="https://www.cnblogs.com/Hero-/p/14784744.html" target="_blank" class="a-link">
|
||||
<n-button text>帮助</n-button>
|
||||
</a>
|
||||
<a href="https://github.com/yaolunmao/vue-webtopo-svgeditor" target="_blank" class="a-link">
|
||||
<n-button text>Github</n-button>
|
||||
</a>
|
||||
<n-popover trigger="hover">
|
||||
<template #trigger>
|
||||
<n-button text class="button-class">v3.0</n-button>
|
||||
</template>
|
||||
<div>这个点了没什么用 不过会变色</div>
|
||||
<div>说实话 这个版本号就是瞎写的 一点都不严谨</div>
|
||||
</n-popover>
|
||||
<n-button type="primary" class="button-class" @click="() => { emit('saveSvgInfo') }">保存</n-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { NButton, useMessage, NPopover } from "naive-ui";
|
||||
const message = useMessage();
|
||||
const emit = defineEmits(['saveSvgInfo']);
|
||||
defineExpose({
|
||||
/**
|
||||
* @description: 保存svg结果 父组件调用用
|
||||
* @param {*}type 0失败 1成功 2警告
|
||||
* @return {*}
|
||||
*/
|
||||
saveSvgInfoRes(type: any) {
|
||||
if (type?.code == 0) {
|
||||
message.error(type?.msg);
|
||||
}
|
||||
else if (type?.code == 1) {
|
||||
message.success(type?.msg);
|
||||
}
|
||||
else if (type?.code == 2) {
|
||||
message.warning(type?.msg);
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
.logoimg {
|
||||
height: 2rem;
|
||||
min-width: 2rem;
|
||||
margin-right: 0.1rem;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
.logotext {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
color: #2c3e50;
|
||||
margin-top: 0.7rem;
|
||||
width: 30%;
|
||||
}
|
||||
.a-link {
|
||||
text-decoration: none;
|
||||
margin-right: 1.5rem;
|
||||
align-self: center;
|
||||
}
|
||||
.button-class {
|
||||
margin-right: 1.5rem;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<svg aria-hidden="true">
|
||||
<use :xlink:href="symbolId" v-bind="props.props" />
|
||||
</svg>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
props: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
const symbolId = computed(() => `#svg-${props.name}`);
|
||||
</script>
|
@ -0,0 +1,10 @@
|
||||
<!-- eslint-disable vue/html-indent -->
|
||||
<template>
|
||||
<div class="flex justify-center items-center pt-2">
|
||||
<div> Copyright (c) 2022</div>
|
||||
<a class="mx-2 hover:text-blue-400" href="https://github.com/yaolunmao" target="_blank"
|
||||
>咬轮猫</a
|
||||
></div
|
||||
>
|
||||
</template>
|
||||
<script lang="ts" setup></script>
|
@ -0,0 +1,874 @@
|
||||
<!-- eslint-disable vue/html-indent -->
|
||||
<template>
|
||||
<div
|
||||
class="canvas"
|
||||
tabindex="0"
|
||||
ref="canvasRef"
|
||||
@drop="dropEvent"
|
||||
@dragenter="dragEnterEvent"
|
||||
@dragover="dragOverEvent"
|
||||
@mousedown="onCanvasMouseDown"
|
||||
@mousemove="onCanvasMouseMove"
|
||||
@mouseup="onCanvasMouseUp"
|
||||
@contextmenu="onCanvasContextMenuEvent"
|
||||
@keydown="onHandleKeyDown"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
:style="{ backgroundColor: configStore.svg.background_color }"
|
||||
width="100%"
|
||||
height="100%"
|
||||
>
|
||||
<defs>
|
||||
<pattern id="pattern_grid" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10">
|
||||
<rect width="1" height="1" rx="1" ry="1" fill="#aaaaaa" />
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect v-if="configStore.svg.grid" width="100%" height="100%" fill="url(#pattern_grid)" />
|
||||
<g
|
||||
:transform="`translate(${
|
||||
configStore.svg.position_center.x + svgEditLayoutStore.center_offset.x
|
||||
},${
|
||||
configStore.svg.position_center.y + svgEditLayoutStore.center_offset.y
|
||||
})rotate(${0})scale(${configStore.svg.scale})`"
|
||||
>
|
||||
<g
|
||||
v-for="(item, index) in globalStore.done_json"
|
||||
:key="item.id"
|
||||
:transform="`translate(${item.x},${item.y})rotate(0)scale(1)`"
|
||||
v-show="item.display"
|
||||
>
|
||||
<g
|
||||
:transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
|
||||
item.actual_bound.y + item.actual_bound.height / 2
|
||||
})rotate(${item.rotate}) scale(1) translate(${-(
|
||||
item.actual_bound.x +
|
||||
item.actual_bound.width / 2
|
||||
)},${-(item.actual_bound.y + item.actual_bound.height / 2)})`"
|
||||
@mousedown="onSvgMouseDown(item, index, $event)"
|
||||
@mouseenter="onSvgMouseEnter(item, index, $event)"
|
||||
@mouseleave="onSvgMouseLeave(item, index, $event)"
|
||||
@contextmenu="onSvgContextMenuEvent(item, index, $event)"
|
||||
>
|
||||
<connection-line
|
||||
v-if="item.type === EDoneJsonType.ConnectionLine"
|
||||
:item-info="item"
|
||||
:point-visiable="
|
||||
visiable_info.connection_line && visiable_info.select_item.info?.id == item.id
|
||||
"
|
||||
></connection-line>
|
||||
<use
|
||||
v-else-if="item.type === EDoneJsonType.File"
|
||||
:xlink:href="`#svg-${item.name}`"
|
||||
v-bind="prosToVBind(item)"
|
||||
width="100"
|
||||
height="100"
|
||||
:id="item.id"
|
||||
:transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
|
||||
item.actual_bound.y + item.actual_bound.height / 2
|
||||
}) scale(${item.scale_x},${item.scale_y}) translate(${-(
|
||||
item.actual_bound.x +
|
||||
item.actual_bound.width / 2
|
||||
)},${-(item.actual_bound.y + item.actual_bound.height / 2)})`"
|
||||
></use>
|
||||
<component
|
||||
v-else-if="item.type === EDoneJsonType.CustomSvg"
|
||||
:is="item.tag"
|
||||
v-bind="prosToVBind(item)"
|
||||
width="100"
|
||||
height="100"
|
||||
:id="item.id"
|
||||
:transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
|
||||
item.actual_bound.y + item.actual_bound.height / 2
|
||||
}) scale(${item.scale_x},${item.scale_y}) translate(${-(
|
||||
item.actual_bound.x +
|
||||
item.actual_bound.width / 2
|
||||
)},${-(item.actual_bound.y + item.actual_bound.height / 2)})`"
|
||||
></component>
|
||||
<foreignObject
|
||||
v-else-if="item.type === EDoneJsonType.Vue"
|
||||
v-bind="getActualBoundScale(item.actual_bound, item.scale_x, item.scale_y)"
|
||||
:id="`foreign-object${item.id}`"
|
||||
>
|
||||
<component
|
||||
:is="item.tag"
|
||||
v-bind="prosToVBind(item)"
|
||||
:id="item.id"
|
||||
:transform="`translate(${item.actual_bound.x + item.actual_bound.width / 2},${
|
||||
item.actual_bound.y + item.actual_bound.height / 2
|
||||
}) scale(${item.scale_x},${item.scale_y}) translate(${-(
|
||||
item.actual_bound.x +
|
||||
item.actual_bound.width / 2
|
||||
)},${-(item.actual_bound.y + item.actual_bound.height / 2)})`"
|
||||
>{{ item.tag_slot }}</component
|
||||
>
|
||||
</foreignObject>
|
||||
|
||||
<line
|
||||
v-else-if="item.type === EDoneJsonType.StraightLine"
|
||||
:id="item.id"
|
||||
:x1="item.props.start_x.val"
|
||||
:y1="item.props.start_y.val"
|
||||
:x2="item.props.end_x.val"
|
||||
:y2="item.props.end_y.val"
|
||||
fill="#FF0000"
|
||||
stroke="#FF0000"
|
||||
stroke-width="2"
|
||||
></line>
|
||||
<rect
|
||||
v-if="item.config.actual_rect"
|
||||
:id="`rect${item.id}`"
|
||||
fill="black"
|
||||
fill-opacity="0"
|
||||
v-bind="getActualBoundScale(item.actual_bound, item.scale_x, item.scale_y)"
|
||||
style="stroke: none; stroke-width: 2; stroke-miterlimit: 10"
|
||||
:class="`${
|
||||
globalStore.intention == EGlobalStoreIntention.None ||
|
||||
globalStore.intention == EGlobalStoreIntention.Select
|
||||
? 'svg-item-none'
|
||||
: ''
|
||||
}
|
||||
${
|
||||
globalStore.intention == EGlobalStoreIntention.Move &&
|
||||
globalStore.handle_svg_info?.info.id == item.id
|
||||
? 'svg-item-move'
|
||||
: ''
|
||||
} ${
|
||||
globalStore.intention == EGlobalStoreIntention.Select &&
|
||||
globalStore.handle_svg_info?.info.id == item.id
|
||||
? 'svg-item-select'
|
||||
: ''
|
||||
}`"
|
||||
></rect>
|
||||
<handle-panel
|
||||
v-if="
|
||||
globalStore.handle_svg_info?.info.id === item.id &&
|
||||
visiable_info.handle_panel &&
|
||||
item.config.can_zoom
|
||||
"
|
||||
:item-info="item"
|
||||
></handle-panel>
|
||||
<connection-panel
|
||||
v-if="
|
||||
visiable_info.select_item.info?.id == item.id &&
|
||||
visiable_info.connection_panel &&
|
||||
item.config.have_anchor &&
|
||||
(globalStore.intention === EGlobalStoreIntention.Select
|
||||
? item.id !== globalStore.handle_svg_info?.info.id
|
||||
? true
|
||||
: false
|
||||
: true)
|
||||
"
|
||||
:item-info="item"
|
||||
></connection-panel>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<!-- 右键菜单 -->
|
||||
<ul ref="contextMenuRef" class="contextMenu" v-show="contextMenuStore.display">
|
||||
<li
|
||||
v-for="(item, key) in contextMenuStore.info"
|
||||
:key="item.title"
|
||||
@click="contextMenuStore.onContextMenuClick(key)"
|
||||
>
|
||||
<p :class="item.enable ? '' : 'disabled'">
|
||||
{{ item.title }}
|
||||
<span class="shortcut">{{ item.hot_key }}</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed, getCurrentInstance, onMounted, reactive, ref } from 'vue';
|
||||
import { useConfigStore } from '@/store/config';
|
||||
import { useGlobalStore } from '@/store/global';
|
||||
import {
|
||||
EGlobalStoreIntention,
|
||||
EMouseInfoState,
|
||||
EScaleInfoType,
|
||||
IDoneJson
|
||||
} from '@/store/global/types';
|
||||
import { useSvgEditLayoutStore } from '@/store/svgedit-layout';
|
||||
import {
|
||||
getCenterPoint,
|
||||
randomString,
|
||||
getSvgNowPosition,
|
||||
setSvgActualInfo,
|
||||
prosToVBind,
|
||||
objectDeepClone
|
||||
} from '@/utils';
|
||||
import {
|
||||
calculateBottom,
|
||||
calculateLeft,
|
||||
calculateLeftBottom,
|
||||
calculateLeftTop,
|
||||
calculateRight,
|
||||
calculateRightBottom,
|
||||
calculateRightTop,
|
||||
calculateTop
|
||||
} from '@/utils/scale-core';
|
||||
import HandlePanel from '@/components/webtopo-svg-edit/components/handle-panel/index.vue';
|
||||
import ConnectionPanel from '@/components/webtopo-svg-edit/components/connection-panel/index.vue';
|
||||
import { EDoneJsonType, IConfigItem } from '@/config-center/types';
|
||||
import ConnectionLine from '@/components/webtopo-svg-edit/components/connection-line/index.vue';
|
||||
import { IVisiableInfo } from './types';
|
||||
import { ComponentImport } from '@/config-center';
|
||||
import { useContextMenuStore, useEditPrivateStore } from '@/store/system';
|
||||
import { EContextMenuInfoType } from '@/store/system/types';
|
||||
import { useHistoryRecord } from '@/hooks';
|
||||
// import HandlePanel from '../handle-panel/index.vue';
|
||||
//注册所有组件
|
||||
const instance = getCurrentInstance();
|
||||
Object.keys(ComponentImport).forEach((key) => {
|
||||
if (!Object.keys(instance?.appContext?.components as any).includes(key)) {
|
||||
instance?.appContext.app.component(key, ComponentImport[key]);
|
||||
}
|
||||
});
|
||||
const globalStore = useGlobalStore();
|
||||
const configStore = useConfigStore();
|
||||
const svgEditLayoutStore = useSvgEditLayoutStore();
|
||||
const editPrivateStore = useEditPrivateStore();
|
||||
const contextMenuStore = useContextMenuStore();
|
||||
const contextMenuRef = ref<HTMLElement>();
|
||||
const canvasRef = ref<HTMLElement>();
|
||||
const cursor_style = computed(() =>
|
||||
globalStore.intention == EGlobalStoreIntention.MoveCanvas
|
||||
? 'grab'
|
||||
: globalStore.intention == EGlobalStoreIntention.Rotate
|
||||
? "url('/src/assets/icons/rotate.svg') 12 12, auto"
|
||||
: 'default'
|
||||
);
|
||||
const visiable_info: IVisiableInfo = reactive({
|
||||
handle_panel: computed(
|
||||
() =>
|
||||
globalStore.intention === EGlobalStoreIntention.Select ||
|
||||
globalStore.intention === EGlobalStoreIntention.Zoom ||
|
||||
globalStore.intention === EGlobalStoreIntention.Rotate
|
||||
),
|
||||
connection_panel: false,
|
||||
connection_line: false,
|
||||
select_item: {
|
||||
info: null,
|
||||
index: -1
|
||||
}
|
||||
});
|
||||
const dropEvent = (e: DragEvent) => {
|
||||
if (globalStore.intention == EGlobalStoreIntention.None) {
|
||||
return;
|
||||
} else if (globalStore.intention == EGlobalStoreIntention.Create) {
|
||||
if (!globalStore.create_svg_info) {
|
||||
console.error('要创建的数据获取失败');
|
||||
return;
|
||||
}
|
||||
const done_item_json: IDoneJson = {
|
||||
id: globalStore.create_svg_info.name + randomString(),
|
||||
x: e.clientX - svgEditLayoutStore.center_offset.x,
|
||||
y: e.clientY - svgEditLayoutStore.center_offset.y,
|
||||
client: {
|
||||
x: e.clientX - svgEditLayoutStore.center_offset.x,
|
||||
y: e.clientY - svgEditLayoutStore.center_offset.y
|
||||
},
|
||||
scale_x: 1,
|
||||
scale_y: 1,
|
||||
rotate: 0,
|
||||
actual_bound: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
},
|
||||
point_coordinate: {
|
||||
tl: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
tc: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
tr: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
l: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
r: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
bl: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
bc: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
br: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
...objectDeepClone<IConfigItem>(globalStore.create_svg_info)
|
||||
};
|
||||
globalStore.setHandleSvgInfo(done_item_json, globalStore.done_json.length);
|
||||
globalStore.setDoneJson(done_item_json);
|
||||
globalStore.intention = EGlobalStoreIntention.None;
|
||||
}
|
||||
canvasRef.value?.focus();
|
||||
};
|
||||
const dragEnterEvent = (e: DragEvent) => {
|
||||
//dragenter和dragover一定要阻止浏览器默认行为 不然不会触发drop
|
||||
e.preventDefault();
|
||||
};
|
||||
const dragOverEvent = (e: DragEvent) => {
|
||||
//dragenter和dragover一定要阻止浏览器默认行为 不然不会触发drop
|
||||
e.preventDefault();
|
||||
};
|
||||
const onSvgMouseDown = (select_item: IDoneJson, index: number, e: MouseEvent) => {
|
||||
canvasRef.value?.focus();
|
||||
if (globalStore.intention === EGlobalStoreIntention.Connection) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
//鼠标在画布上的组件按下记录选中的组件信息和鼠标位置信息等
|
||||
globalStore.intention = EGlobalStoreIntention.Select;
|
||||
globalStore.setHandleSvgInfo(select_item, index);
|
||||
globalStore.setMouseInfo({
|
||||
state: EMouseInfoState.Down,
|
||||
position_x: e.clientX,
|
||||
position_y: e.clientY,
|
||||
now_position_x: select_item.x,
|
||||
now_position_y: select_item.y,
|
||||
new_position_x: select_item.x,
|
||||
new_position_y: select_item.y
|
||||
});
|
||||
};
|
||||
const onSvgMouseEnter = (select_item: IDoneJson, index: number, e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
visiable_info.connection_panel = true;
|
||||
visiable_info.connection_line = true;
|
||||
if (
|
||||
(globalStore.intention === EGlobalStoreIntention.Connection ||
|
||||
globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) &&
|
||||
select_item.type === EDoneJsonType.ConnectionLine
|
||||
) {
|
||||
return;
|
||||
}
|
||||
visiable_info.select_item.info = select_item;
|
||||
visiable_info.select_item.index = index;
|
||||
};
|
||||
const onSvgMouseLeave = (select_item: IDoneJson, index: number, e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (
|
||||
(globalStore.intention === EGlobalStoreIntention.Connection ||
|
||||
globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode) &&
|
||||
select_item.type === EDoneJsonType.ConnectionLine
|
||||
) {
|
||||
return;
|
||||
}
|
||||
visiable_info.connection_panel = false;
|
||||
visiable_info.connection_line = false;
|
||||
visiable_info.select_item.info = null;
|
||||
visiable_info.select_item.index = -1;
|
||||
};
|
||||
const onCanvasMouseMove = (e: MouseEvent) => {
|
||||
//如果鼠标不是按下状态 连线除外
|
||||
if (
|
||||
globalStore.mouse_info.state != EMouseInfoState.Down &&
|
||||
globalStore.intention !== EGlobalStoreIntention.Connection
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const { clientX, clientY } = e;
|
||||
globalStore.mouse_info.new_position_x =
|
||||
globalStore.mouse_info.now_position_x + clientX - globalStore.mouse_info.position_x;
|
||||
globalStore.mouse_info.new_position_y =
|
||||
globalStore.mouse_info.now_position_y + clientY - globalStore.mouse_info.position_y;
|
||||
if (
|
||||
globalStore.handle_svg_info?.info &&
|
||||
(globalStore.intention == EGlobalStoreIntention.Select ||
|
||||
globalStore.intention == EGlobalStoreIntention.Move)
|
||||
) {
|
||||
//有选中组件 移动组件
|
||||
globalStore.handle_svg_info.info.x = globalStore.mouse_info.new_position_x;
|
||||
globalStore.handle_svg_info.info.y = globalStore.mouse_info.new_position_y;
|
||||
globalStore.handle_svg_info.info.client = {
|
||||
x: globalStore.mouse_info.new_position_x,
|
||||
y: globalStore.mouse_info.new_position_y
|
||||
};
|
||||
globalStore.intention = EGlobalStoreIntention.Move;
|
||||
} else if (globalStore.intention == EGlobalStoreIntention.MoveCanvas) {
|
||||
//移动画布
|
||||
svgEditLayoutStore.center_offset.x = globalStore.mouse_info.new_position_x;
|
||||
svgEditLayoutStore.center_offset.y = globalStore.mouse_info.new_position_y;
|
||||
} else if (globalStore.intention === EGlobalStoreIntention.Zoom) {
|
||||
if (!globalStore.handle_svg_info) {
|
||||
return;
|
||||
}
|
||||
//当前鼠标坐标
|
||||
const curPositon = {
|
||||
x: e.clientX - svgEditLayoutStore.center_offset.x,
|
||||
y: e.clientY - svgEditLayoutStore.center_offset.y
|
||||
};
|
||||
let new_length = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
is_old_width: false,
|
||||
is_old_height: false
|
||||
};
|
||||
if (globalStore.scale_info.type === EScaleInfoType.TopLeft) {
|
||||
new_length = calculateLeftTop(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate
|
||||
);
|
||||
} else if (globalStore.scale_info.type === EScaleInfoType.TopRight) {
|
||||
new_length = calculateRightTop(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate
|
||||
);
|
||||
} else if (globalStore.scale_info.type === EScaleInfoType.BottomRight) {
|
||||
new_length = calculateRightBottom(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate
|
||||
);
|
||||
} else if (globalStore.scale_info.type === EScaleInfoType.BottomLeft) {
|
||||
new_length = calculateLeftBottom(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate
|
||||
);
|
||||
} else if (globalStore.scale_info.type === EScaleInfoType.TopCenter) {
|
||||
new_length = calculateTop(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate,
|
||||
globalStore.handle_svg_info.info.client
|
||||
);
|
||||
} else if (globalStore.scale_info.type === EScaleInfoType.Right) {
|
||||
new_length = calculateRight(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate,
|
||||
globalStore.handle_svg_info.info.client
|
||||
);
|
||||
} else if (globalStore.scale_info.type === EScaleInfoType.BottomCenter) {
|
||||
new_length = calculateBottom(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate,
|
||||
globalStore.handle_svg_info.info.client
|
||||
);
|
||||
} else if (globalStore.scale_info.type === EScaleInfoType.Left) {
|
||||
new_length = calculateLeft(
|
||||
curPositon,
|
||||
globalStore.scale_info.symmetric_point,
|
||||
globalStore.handle_svg_info.info.rotate,
|
||||
globalStore.handle_svg_info.info.client
|
||||
);
|
||||
}
|
||||
|
||||
//缩放
|
||||
// const move_length_x =
|
||||
// globalStore.scale_info.type === EScaleInfoType.TopLeft ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.Left ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.BottomLeft
|
||||
// ? -(newTopLeftPoint.x - globalStore.mouse_info.now_position_x)
|
||||
// : globalStore.scale_info.type === EScaleInfoType.TopRight ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.Right ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.BottomRight
|
||||
// ? globalStore.mouse_info.now_position_x - newTopLeftPoint.x
|
||||
// : 0;
|
||||
// const move_length_y =
|
||||
// globalStore.scale_info.type === EScaleInfoType.TopLeft ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.TopCenter ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.TopRight
|
||||
// ? newTopLeftPoint.y - globalStore.mouse_info.now_position_y
|
||||
// : globalStore.scale_info.type === EScaleInfoType.BottomLeft ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.BottomCenter ||
|
||||
// globalStore.scale_info.type === EScaleInfoType.BottomRight
|
||||
// ? globalStore.mouse_info.now_position_y - newTopLeftPoint.y
|
||||
// : 0;
|
||||
//算出缩放倍数
|
||||
if (globalStore.handle_svg_info && new_length.width > 0 && new_length.height > 0) {
|
||||
const scale_x = !new_length.is_old_width
|
||||
? new_length.width / globalStore.handle_svg_info.info.actual_bound.width
|
||||
: 1;
|
||||
const scale_y = !new_length.is_old_height
|
||||
? new_length.height / globalStore.handle_svg_info.info.actual_bound.height
|
||||
: 1;
|
||||
const newCenterPoint = getCenterPoint(curPositon, globalStore.scale_info.symmetric_point);
|
||||
if (
|
||||
scale_x > 0 &&
|
||||
globalStore.scale_info.type !== EScaleInfoType.TopCenter &&
|
||||
globalStore.scale_info.type !== EScaleInfoType.BottomCenter
|
||||
) {
|
||||
globalStore.handle_svg_info.info.scale_x = scale_x;
|
||||
globalStore.handle_svg_info.info.x = getSvgNowPosition(
|
||||
globalStore.handle_svg_info.info.client.x,
|
||||
newCenterPoint.x,
|
||||
globalStore.scale_info.scale_item_info.x
|
||||
);
|
||||
}
|
||||
if (
|
||||
scale_y > 0 &&
|
||||
globalStore.scale_info.type !== EScaleInfoType.Left &&
|
||||
globalStore.scale_info.type !== EScaleInfoType.Right
|
||||
) {
|
||||
globalStore.handle_svg_info.info.scale_y = scale_y;
|
||||
globalStore.handle_svg_info.info.y = getSvgNowPosition(
|
||||
globalStore.handle_svg_info.info.client.y,
|
||||
newCenterPoint.y,
|
||||
globalStore.scale_info.scale_item_info.y
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (globalStore.intention === EGlobalStoreIntention.Rotate) {
|
||||
if (!globalStore.handle_svg_info) {
|
||||
return;
|
||||
}
|
||||
const rotateDegreeBefore =
|
||||
Math.atan2(
|
||||
globalStore.mouse_info.position_y - globalStore.handle_svg_info.info.client.y,
|
||||
globalStore.mouse_info.position_x - globalStore.handle_svg_info.info.client.x
|
||||
) /
|
||||
(Math.PI / 180);
|
||||
const rotateDegreeAfter =
|
||||
Math.atan2(
|
||||
clientY - svgEditLayoutStore.center_offset.y - globalStore.handle_svg_info.info.client.y,
|
||||
clientX - svgEditLayoutStore.center_offset.x - globalStore.handle_svg_info.info.client.x
|
||||
) /
|
||||
(Math.PI / 180);
|
||||
globalStore.handle_svg_info.info.rotate =
|
||||
globalStore.rotate_info.angle + rotateDegreeAfter - rotateDegreeBefore;
|
||||
} else if (
|
||||
globalStore.intention === EGlobalStoreIntention.Connection &&
|
||||
globalStore.handle_svg_info
|
||||
) {
|
||||
globalStore.handle_svg_info.info.props.point_position.val[
|
||||
globalStore.handle_svg_info?.info.props.point_position.val.length - 1
|
||||
] = {
|
||||
x: getSvgNowPosition(
|
||||
globalStore.mouse_info.position_x,
|
||||
clientX,
|
||||
globalStore.handle_svg_info?.info.props.point_position.val[0].x
|
||||
),
|
||||
y: getSvgNowPosition(
|
||||
globalStore.mouse_info.position_y,
|
||||
clientY,
|
||||
globalStore.handle_svg_info?.info.props.point_position.val[0].y
|
||||
)
|
||||
};
|
||||
// console.log('连线', start_x, start_y, end_x, end_y, clientX, clientY);
|
||||
} else if (
|
||||
globalStore.intention === EGlobalStoreIntention.SetConnectionLineNode &&
|
||||
globalStore.handle_svg_info
|
||||
) {
|
||||
globalStore.handle_svg_info.info.props.point_position.val[
|
||||
globalStore.connection_line_node_info.point_index
|
||||
] = {
|
||||
x: getSvgNowPosition(
|
||||
globalStore.mouse_info.position_x,
|
||||
clientX,
|
||||
globalStore.connection_line_node_info.init_pos.x
|
||||
),
|
||||
y: getSvgNowPosition(
|
||||
globalStore.mouse_info.position_y,
|
||||
clientY,
|
||||
globalStore.connection_line_node_info.init_pos.y
|
||||
)
|
||||
};
|
||||
}
|
||||
};
|
||||
const onCanvasMouseUp = () => {
|
||||
//如果鼠标不是按下状态
|
||||
if (globalStore.mouse_info.state != EMouseInfoState.Down) {
|
||||
return;
|
||||
}
|
||||
if (globalStore.handle_svg_info?.info && globalStore.intention == EGlobalStoreIntention.Move) {
|
||||
globalStore.done_json[globalStore.handle_svg_info.index].x =
|
||||
globalStore.mouse_info.new_position_x;
|
||||
globalStore.done_json[globalStore.handle_svg_info.index].y =
|
||||
globalStore.mouse_info.new_position_y;
|
||||
// globalStore.setDoneJson(globalStore.done_json);
|
||||
setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index]);
|
||||
globalStore.intention = EGlobalStoreIntention.None;
|
||||
//记录历史记录
|
||||
globalStore.setDoneJson(globalStore.done_json);
|
||||
// globalStore.setHandleSvgInfo(undefined, 0);
|
||||
} else if (
|
||||
globalStore.handle_svg_info?.info &&
|
||||
globalStore.intention == EGlobalStoreIntention.Zoom
|
||||
) {
|
||||
//缩放完成后重置中点 新版本中点就是组件坐标
|
||||
// const newCenterPoint = getCenterPoint(
|
||||
// { x: e.clientX, y: e.clientY },
|
||||
// globalStore.scale_info.symmetric_point
|
||||
// );
|
||||
globalStore.handle_svg_info.info.client = {
|
||||
x: globalStore.handle_svg_info.info.x,
|
||||
y: globalStore.handle_svg_info.info.y
|
||||
};
|
||||
globalStore.intention = EGlobalStoreIntention.None;
|
||||
setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index]);
|
||||
//记录历史记录
|
||||
globalStore.setDoneJson(globalStore.done_json);
|
||||
} else if (
|
||||
globalStore.intention === EGlobalStoreIntention.Rotate &&
|
||||
globalStore.handle_svg_info?.info
|
||||
) {
|
||||
setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index]);
|
||||
//记录历史记录
|
||||
globalStore.setDoneJson(globalStore.done_json);
|
||||
} else if (globalStore.intention === EGlobalStoreIntention.Connection) {
|
||||
return;
|
||||
} else if (globalStore.intention != EGlobalStoreIntention.Select) {
|
||||
globalStore.intention = EGlobalStoreIntention.None;
|
||||
}
|
||||
globalStore.setMouseInfo({
|
||||
state: EMouseInfoState.Up,
|
||||
position_x: 0,
|
||||
position_y: 0,
|
||||
now_position_x: 0,
|
||||
now_position_y: 0,
|
||||
new_position_x: 0,
|
||||
new_position_y: 0
|
||||
});
|
||||
contextMenuStore.display = false;
|
||||
};
|
||||
const onCanvasMouseDown = (e: MouseEvent) => {
|
||||
const { clientX, clientY } = e;
|
||||
if (globalStore.intention === EGlobalStoreIntention.Connection && globalStore.handle_svg_info) {
|
||||
if (e.button === 0) {
|
||||
//鼠标左键创建新线段
|
||||
globalStore.handle_svg_info.info.props.point_position.val.push({
|
||||
x: getSvgNowPosition(
|
||||
globalStore.mouse_info.position_x,
|
||||
clientX,
|
||||
globalStore.handle_svg_info?.info.props.point_position.val[0].x
|
||||
),
|
||||
y: getSvgNowPosition(
|
||||
globalStore.mouse_info.position_y,
|
||||
clientY,
|
||||
globalStore.handle_svg_info?.info.props.point_position.val[0].y
|
||||
)
|
||||
});
|
||||
}
|
||||
if (e.button === 2) {
|
||||
//鼠标右键结束线段绘制
|
||||
globalStore.intention = EGlobalStoreIntention.None;
|
||||
setSvgActualInfo(globalStore.done_json[globalStore.handle_svg_info.index]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//点击画布 未选中组件 拖动画布
|
||||
globalStore.intention = EGlobalStoreIntention.MoveCanvas;
|
||||
globalStore.setMouseInfo({
|
||||
state: EMouseInfoState.Down,
|
||||
position_x: clientX,
|
||||
position_y: clientY,
|
||||
now_position_x: svgEditLayoutStore.center_offset.x,
|
||||
now_position_y: svgEditLayoutStore.center_offset.y,
|
||||
new_position_x: svgEditLayoutStore.center_offset.x,
|
||||
new_position_y: svgEditLayoutStore.center_offset.y
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 鼠标右键事件
|
||||
* @param select_component
|
||||
* @param e
|
||||
* @returns
|
||||
*/
|
||||
const onCanvasContextMenuEvent = (e: MouseEvent) => {
|
||||
e.preventDefault(); //禁用浏览器右键
|
||||
};
|
||||
const onSvgContextMenuEvent = (select_item: IDoneJson, index: number, e: MouseEvent) => {
|
||||
if (globalStore.intention === EGlobalStoreIntention.Connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (contextMenuRef.value) {
|
||||
globalStore.intention = EGlobalStoreIntention.ContextMenu;
|
||||
globalStore.setHandleSvgInfo(select_item, index);
|
||||
contextMenuRef.value.style.left = e.pageX + 'px';
|
||||
contextMenuRef.value.style.top = e.pageY + 'px';
|
||||
contextMenuStore.info.MoveUpOneLevel.enable =
|
||||
contextMenuStore.info.MoveUpTopLevel.enable =
|
||||
contextMenuStore.info.MoveDownOneLevel.enable =
|
||||
contextMenuStore.info.MoveDownTopLevel.enable =
|
||||
true;
|
||||
if (index === globalStore.done_json.length - 1) {
|
||||
contextMenuStore.info.MoveUpOneLevel.enable = contextMenuStore.info.MoveUpTopLevel.enable =
|
||||
false;
|
||||
}
|
||||
if (index === 0) {
|
||||
contextMenuStore.info.MoveDownOneLevel.enable =
|
||||
contextMenuStore.info.MoveDownTopLevel.enable = false;
|
||||
}
|
||||
contextMenuStore.display = true;
|
||||
}
|
||||
};
|
||||
const getActualBoundScale = (
|
||||
actual_bound: {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
},
|
||||
scale_x: number,
|
||||
scale_y: number
|
||||
) => {
|
||||
return {
|
||||
x: actual_bound.x - (actual_bound.width / 2) * scale_x + actual_bound.width / 2,
|
||||
y: actual_bound.y - (actual_bound.height / 2) * scale_y + actual_bound.height / 2,
|
||||
width: actual_bound.width * scale_x,
|
||||
height: actual_bound.height * scale_y
|
||||
};
|
||||
};
|
||||
const onHandleKeyDown = (e: KeyboardEvent) => {
|
||||
console.log(e, 733);
|
||||
e.preventDefault();
|
||||
if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowUp') {
|
||||
globalStore.done_json[globalStore.handle_svg_info.index].y -= 1;
|
||||
useHistoryRecord(globalStore.done_json);
|
||||
} else if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowDown') {
|
||||
globalStore.handle_svg_info.info.y += 1;
|
||||
useHistoryRecord(globalStore.done_json);
|
||||
} else if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowLeft') {
|
||||
globalStore.handle_svg_info.info.x -= 1;
|
||||
useHistoryRecord(globalStore.done_json);
|
||||
} else if (globalStore.handle_svg_info && !e.ctrlKey && e.key == 'ArrowRight') {
|
||||
globalStore.handle_svg_info.info.x += 1;
|
||||
useHistoryRecord(globalStore.done_json);
|
||||
}
|
||||
//ctrl c
|
||||
else if (e.ctrlKey && e.key.toLowerCase() == 'c') {
|
||||
contextMenuStore.onContextMenuClick(EContextMenuInfoType.Copy);
|
||||
}
|
||||
//deleted
|
||||
else if (!e.ctrlKey && e.key == 'Delete') {
|
||||
contextMenuStore.onContextMenuClick(EContextMenuInfoType.Delete);
|
||||
}
|
||||
//上移一层
|
||||
else if (e.ctrlKey && e.key == 'ArrowUp') {
|
||||
contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveUpOneLevel);
|
||||
}
|
||||
//下移一层
|
||||
else if (e.ctrlKey && e.key == 'ArrowDown') {
|
||||
contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveDownOneLevel);
|
||||
}
|
||||
//置于底层
|
||||
else if (e.ctrlKey && e.key == 'ArrowLeft') {
|
||||
contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveDownTopLevel);
|
||||
}
|
||||
//置于顶层
|
||||
else if (e.ctrlKey && e.key == 'ArrowRight') {
|
||||
contextMenuStore.onContextMenuClick(EContextMenuInfoType.MoveUpTopLevel);
|
||||
}
|
||||
//ctrl+shift+z
|
||||
else if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() == 'z') {
|
||||
editPrivateStore.topRedoBtnClick();
|
||||
}
|
||||
//ctrl+z
|
||||
else if (e.ctrlKey && e.key.toLowerCase() == 'z') {
|
||||
editPrivateStore.topUndoBtnClick();
|
||||
}
|
||||
//ctrl+delete
|
||||
else if (e.ctrlKey && e.key.toLowerCase() == 'delete') {
|
||||
globalStore.done_json.length <= 0 || globalStore.setDoneJson([]);
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
canvasRef.value?.focus();
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: v-bind('cursor_style');
|
||||
&:focus-visible {
|
||||
outline: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.svg-item-none {
|
||||
cursor: move;
|
||||
|
||||
&:hover {
|
||||
outline: 1px solid #0cf;
|
||||
}
|
||||
}
|
||||
|
||||
.svg-item-move {
|
||||
cursor: move;
|
||||
outline: 1px dashed rgb(23, 222, 30);
|
||||
}
|
||||
|
||||
.svg-item-select {
|
||||
cursor: move;
|
||||
outline: 1px solid rgb(23, 222, 30);
|
||||
}
|
||||
.contextMenu {
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
background: #ffffff;
|
||||
padding: 5px 0;
|
||||
margin: 0px;
|
||||
display: block;
|
||||
border-radius: 5px;
|
||||
box-shadow: 2px 5px 10px rgba(0, 0, 0, 0.3);
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
width: 115px;
|
||||
text-align: right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
p {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
padding: 0px 15px 1px 20px;
|
||||
margin: 0;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
p:hover {
|
||||
background-color: #0cf;
|
||||
color: #ffffff;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.disabled:hover {
|
||||
color: #999;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
li.separator {
|
||||
border-top: solid 1px #e3e3e3;
|
||||
padding-top: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,11 @@
|
||||
import { IDoneJson } from '@/store/global/types';
|
||||
|
||||
export interface IVisiableInfo {
|
||||
handle_panel: boolean;
|
||||
connection_panel: boolean;
|
||||
connection_line: boolean;
|
||||
select_item: {
|
||||
info: null | IDoneJson;
|
||||
index: number;
|
||||
};
|
||||
}
|