注册
web

因为美工小妹妹天还没亮就下班,我做了一版可以把svg文件转成web组态组件的svg编辑器

自我介绍


本猫生活在东北的一个四线小城市,目前在一家小单位任职前端工程师的职位。早八晚五,生活充实,好不快活!


噩耗


Ctrl+c,Ctrl+vCtrl+c,Ctrl+v。新的一天开始了,本猫正在努力的工作着。看着旁边的美工小妹妹,我的口水止不住的往下流,别误会,是因为公司没有几个人,所以我们每天中午都在一起吃饭,而且我本来身为一个吃货,想到午饭就会流口水,很合理吧。


正当我沉迷在幻想之际,手机的一声震动把我拽回到现实。


“来我办公室一趟!”

竟然是老板给我发的消息!!!

难不成是我每天辛苦的工作被他发现了?要给我涨工资?

我一溜烟的从工位冲了出去,直奔老板的办公室。

这一路上我想了很多:想我这么多年的辛劳付出终于达到了回报、想我迎娶白富美的现场何其壮观、想我出任ceo之后回村又是多么的风光......

终于在三秒之后,我来到了老板的办公室,见到了我最敬爱的老板。


“猫啊,听说你最近表现不错”

还没等我说话,老板又接着说到:

“咱们公司最近新接了一个项目要交给你完成,你有没有信心啊?”

我拍了拍胸脯:

“必须的!老板您说让我做什么我就做什么”

然后老板对我展开了需求攻势:

“巴拉巴拉,如此如此,这般这般,巴巴拉拉加班拉拉巴巴”

“什么?加班!”

其实老板说了那么多我是左耳听,右耳冒,但是加班这两个重重的砸在了我心上。我突然感觉一股热流冲到了头顶,双腿也止不住的颤抖,随即我双手用力的支撑在了老板的办公桌上,才勉强地站稳脚跟。

老板似乎也看出了我的不适,继续说道:

“小猫啊!你年龄这么小,正是应该努力奋斗的时候,我像你这么大的时候每天只睡十分钟,才有了今天的成就。巴拉巴拉。。。。”

听着老板的经历,我不由得留下了感动的泪水。原来老板是如此的器重我,耐心的劝导我只为了让我成长,想到我刚才还想向老板提涨工资的事,我的脸唰的一下就红了。我赶紧向老板鞠了一躬,猫着腰往办公室外面跑。

“谢谢老板关心,我一定完美完成任务!”

“公司就你一个前端,一定得好好做啊!”

随着老板的声音越来越小,我知道我已经离开了老板的办公室,我挺起胸膛,这一刻我仿佛重生了一般,浑身充满了干劲。迈着自信的步伐,我回到了我的工位。


打开电脑,老板已经把项目需求文档发给了我,打开1个Gdoc文件,首页赫然印着几个大字:项目工期一个月


我眼前一黑,晕了过去


曙光


“醒醒!醒醒!你怎么睡着了呢?”

我闻到一股淡淡的清香味,原来是我旁边的美工小妹妹在叫我。

“老板发你的新需求的项目文档你看了吧?老板让我们一起做这个项目”

“看到了看到了”

我惊喜着大叫一声,丝毫不顾忌周围同事的目光。我把头发往后捋了捋,望向我旁边的美工小妹妹:

“放心吧,包在我身上!”

“好的吧,那我先回去了,需要我做什么跟我说吖!”

我比了一个ok的手势,目送美工小妹妹转身回到了她的工位上。


需求分析


于是乎,我赶紧打开了文档,细心的分析了这个项目的需求。

原来这个项目是希望完成一个web端的拓扑图,要求使用svg技术实现,布局大概是长这样:


布局.png


功能呢,也不复杂,可以从左侧的节点区把节点拖到画布,在画布上选中绘制的节点可以缩放旋转,在右侧属性区可以快捷的更改节点的一些属性


美工小妹妹就负责配合我去设计svg的图形


我冷笑一声,这还不简单?真是小看了我这个代码吸血鬼。我打开搜索引擎,用出了我的绝招



“无敌暴龙cv大法”



不出半天,上面的布局就被我给做好了。


根据项目需求还需要去实现拖动的功能,凭借我多年的工作经验,我很快便找到了如下可以进行参考的文章:


一个低代码(可视化拖拽)教学项目


详细的拖拽需求以及缩放旋转的操作这篇文章里都有讲,我这里就不重复赘述了,经过了几天没日没夜的开发,主要说下我遇到的问题吧!


上面文章包含的项目实际上是采用定位来实现的,本身也是支持集成svg文件的,我们先看一下svg文件如何集成:


svg节点定义:


<template>
   <div class="svg-star-container">
       <svg xmlns="http://www.w3.org/2000/svg" version="1.1">
           <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" :fill="fill" />
       </svg>
   </div>
</template>

<script>
export default {
   props: {
       fill: {
           type: String,
           require: true,
           default: '#ff0000',
      },
  },
}
</script>

右侧属性面板定义:


<template>
   <div>
       <el-form>
           <el-form-item label="填充色">
               <el-color-picker v-model="curComponent.fill" />
           </el-form-item>
       </el-form>
   </div>
</template>

上面这是我新集成的一个svg图形,里面只有一个圆形,我这里希望可以在右侧改变圆形的填充(fill)颜色,集成之后的效果就是这样的:


集成效果.png


其实本质上是可以满足我们的需求的,因为我们也就是想改改svgfill或者是stroke这些基本属性的,但是我们的项目大概有300多个组件,这样一来我需要写600多vue文件。上面的示例我只是演示了如何更改svgfill属性,没做缩放适配效果是这样的:


未适配.png


所以我还需要手动调整每个文件去适配缩放,这个工作量堪比吨级,我的脑中顿时思绪万千:


想起来这几日美工小妹妹准时下班向我发我来的甜蜜问候


美工下班.png


想起来昨天向公司申请换键盘的尴尬经历


申请键盘.png


望着手机屏幕反射出连续高强度加班憔悴的我,看着我新换回来CV按键清晰可见的键盘,看着美工小妹妹键盘上那纤细的手指,我不由得感叹道:这么好看的手,不多做几个图可惜了。于是乎我的脑海里萌生了一个大胆的想法:



我要写个逻辑自动把svg文件转成组件,每个svg文件写个配置文件就能在右侧属性区动态的设置svgfillstroke等属性!!!



理想很丰满,现实很骨感


开始我是打算用viteraw以字符串的方式加载svg文件,再用v-html指令将字符串渲染成html


<script setup lang="ts">
import testSvgString from '../assets/vue.svg?raw'
</script>

<template>
 <div>
   <div v-html="testSvgString"></div>
   <div v-html="testSvgString"></div>
 </div>
</template>



效果是这样的:


raw效果.png


这个方案确实行得通,不过如果真正绘制图像的话,会导致dom节点变的很多很多。


dom节点.png


而且现在还没有考虑怎么适应svg节点的实际大小,怎么动态的改变节点fill等基本属性。。。


越想头越大,迷迷糊糊中我仿佛身处在一片森林中,映入我眼帘的是一个正在从我面前河里飘出来的白发老人


“少年哟,你掉的是这个<symbol>标签呢?还是这个<use>标签呢?”


我猛然惊醒


皇天不负有心人


对啊,之前我们用过的一个项目里面的icon图标就是一个个文件,当时是用的这个插件vite-plugin-svg-icons


它可以把svg文件加载成symbol标签,然后在需要的地方用use标签引用就可以了


说干就干,于是我赶紧熟练的打开了搜索引擎,开始了我的求知之路


终于


这个基于 vue3.2+ts 实现的 svg 可视化 web 组态编辑器项目诞生了!


项目介绍


svg文件即组件,引入并编写好配置文件后之后无需进行额外配置,编辑器会自适应解析加载组件。
同时支持自定义svg组件和传统的vue组件


开源地址


github


gitee


在线预览


绘画


选中左侧的组件库,按住鼠标左键即可把组件拖动到画布中


绘画.gif


操作


选中绘制好的节点后会出现锚点,可以直接进行移动、缩放、旋转等功能,右侧属性面板可以设置配置好的节点的属性,鼠标右键可以进行一些快捷操作


操作.gif


连线


鼠标移动到组件上时会出现连线锚点,左键点击锚点创建线段,继续左键点击画布会连续创建线段,右键停止创建线段,鼠标放在线段上会出现线段端点提示,拖动即可重新设置连线,选中线段后还可以在右侧的动画面板设置线段的动画效果


连线.gif


支持集成到已有项目


脚手架项目


# 创建项目(已有项目跳过此步骤)
npm init vite@latest

# 进入项目目录
cd projectname

# 安装插件
pnpm i webtopo-svg-edit

# 安装pinia
pnpm i pinia

# 修改main.ts 注册pinia
import { createPinia } from 'pinia';
const app = createApp(App);
app.use(createPinia());
app.mount('#app')

#在需要的页面引入插件
import { WebtopoSvgEdit,WebtopoSvgPreview } from 'webtopo-svg-edit';
import 'webtopo-svg-edit/dist/style.css'

umd方式集成


<!DOCTYPE html>
<html>
 <head>
   <title>webtopo-svg-edit Example</title>
   <link href="https://unpkg.com/webtopo-svg-edit@0.0.8/dist/style.css" rel="stylesheet" />
   <script src="https://unpkg.com/vue@3.2.6/dist/vue.global.prod.js"></script>
   <script src="https://unpkg.com/vue-demi@0.13.11/lib/index.iife.js"></script>
   <script src="https://unpkg.com/pinia@2.0.33/dist/pinia.iife.prod.js"></script>
   <script src="https://unpkg.com/webtopo-svg-edit@0.0.8/dist/webtopo-svg-edit.umd.js"></script>
 </head>
 <body>
   <div id="app"></div>
   <script>
     const pinia = Pinia.createPinia()
     const app = Vue.createApp(WebtopoYLM.WebtopoSvgEdit)
     app.use(pinia)
     app.mount('#app')
   
</script>
 </body>
</html>


es module方式集成


<!DOCTYPE html>
<html>
 <head>
   <title>webtopo-svg-edit Example</title>
   <link href="https://unpkg.com/webtopo-svg-edit@0.0.8/dist/style.css" rel="stylesheet" />
 </head>
 <body>
   <div id="app"></div>
 </body>
</html>
<script type="importmap">
{
  "imports": {
    "vue": "https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.prod.js",
    "@vue/devtools-api": "https://cdn.jsdelivr.net/npm/@vue/devtools-api/lib/esm/index.min.js",
    "vue-demi": "https://unpkg.com/vue-demi@0.13.11/lib/index.mjs",
    "pinia": "https://unpkg.com/pinia@2.0.29/dist/pinia.esm-browser.js",
    "WebtopoYLM": "https://unpkg.com/webtopo-svg-edit@0.0.8/dist/webtopo-svg-edit.es.js"
  }
}
</script>
<script type="module">
 import { createApp } from 'vue'
 import { createPinia } from 'pinia'
 import { WebtopoSvgEdit } from 'WebtopoYLM'
 const app = createApp(WebtopoSvgEdit)
 app.use(createPinia())
 app.mount('#app')
</script>


后记


“报告老板,以前一个月的工作,现在7天就能做完!”


“小伙子你很有前途,等公司赚钱了一定不会忘了你的!”


“老板这是哪里话,牛马的命也是命,当牛做马是我的荣幸!”


“行了,没什么事就去忙吧,7天之后等你们的好消息!”


凌晨三点,我看着美工小妹妹忙碌的身影,不由得嘴角上扬


嘿嘿!天

作者:咬轮猫
来源:juejin.cn/post/7260126013111812153
还没亮,谁也别想走!

0 个评论

要回复文章请先登录注册