本系列教程是用Vue.js + Nuxt.js + Element + Vuex + 開源js繪圖庫,打造一個屬於本身的在線繪圖軟件,最終效果:http://topology.le5le.com 。若是你以爲好,歡迎給文章和開源庫點贊,讓咱們更有動力去作好!css
本系列教程源碼地址:Github前端
yarn create nuxt-app topology-vue // 注意在後面提示中,上移下移,按空格選中 Element
選擇Element後,在plugins文件夾下會自帶添加Element的插件配置vue
完成後,在nuxt.config.js中配置head相關信息,主要有兩個阿里字體文件:
左側工具欄字體文件:
//at.alicdn.com/t/font_1113798_0532l8oa6jqp.css node
右側屬性字體圖標:
//at.alicdn.com/t/font_1331132_5lvbai88wkb.cssgit
head: { title: '樂吾樂 Topology - 開源免費繪圖工具', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: '一個基於typescript + canvas的好用開源繪圖工具和繪圖引擎。易集成到本身的前端項目、還能夠方便自定義圖形庫,支持微服務架構圖、流程圖、時序圖、活動圖、類圖等' } ], link: [ { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, { rel: 'stylesheet', href: '//at.alicdn.com/t/font_1113798_0532l8oa6jqp.css' }, { rel: 'stylesheet', href: '//at.alicdn.com/t/font_1331132_5lvbai88wkb.css' } ] },
2.1 安裝scss的依賴包github
yarn add node-sass sass-loader -D
2.2 給style標籤加上lang="scss"標記vuex
<style lang="scss"> .page { width: 100%; height: 100%; } </style>
3.1 在asstes/css文件夾下新建一個base.scss公用全局樣式文件
typescript
3.2 導入
在layouts/default.vue的script腳本中導入:canvas
import '~/assets/css/base.scss'
修改layouts/default.vue爲導航欄 + body兩部分
sass
其中:<nuxt /> 爲Nuxt.js框架中對應頁面路由的視圖部分。
修改pages/index.vue爲左中右三欄佈局
yarn add topology-core topology-class-diagram topology-activity-diagram topology-flow-diagram topology-sequence-diagram -D
其中,topology-core爲核心庫引擎,其餘的爲圖形庫。具體參考:開發文檔
咱們單獨寫個pages/canvas.server.js服務,用來提供topology相關服務
這裏主要提供註冊和左側工具欄數據。
3.1 準備canvas相關數據
data() { return { // 左側工具欄 tools: Tools, // 圖形庫 canvas: {}, // 圖形庫選項:https://www.yuque.com/alsmile/topology/canvas#hOupV canvasOptions: { rotateCursor: '/img/rotate.cur' }, // 右側屬性欄數據 props: { node: null, line: null, multi: false } } }
3.2 註冊圖形庫
created() { canvasRegister() }
3.3 在父節點已經渲染後,new建立畫布
mounted() { this.canvasOptions.on = this.onMessage this.canvas = new Topology('topology-canvas', this.canvasOptions) }
其中,onMessage 表示接受畫布的消息回調函數
3.4 左側工具欄支持鼠標拖放
<a v-for="(btn, i) in item.children" :key="i" :title="btn.name" :draggable="btn.data" @dragstart="onDrag($event, btn)" > <i :class="`iconfont ${btn.icon}`"></i> </a>
methods: { onDrag(event, node) { event.dataTransfer.setData('Text', JSON.stringify(node.data)) } }
只須要給拖放數據設置節點格式的字符串便可(畫布自帶支持拖放接收處理),節點數據格式文檔:https://www.yuque.com/alsmile...
3.5 右側屬性欄
在components下建立CanvasProps.vue
<template> <div> <!-- 選中爲空 --> <div v-if="!props.node && !props.line && !props.multi"> <div class="title">歡迎使用le5le-topology!</div> <div class="group"> <a class="star" href="https://github.com/le5le-com/topology" target="_blank">喜歡,點擊這裏打個star吧</a> <a href="https://www.yuque.com/alsmile/topology" target="_blank">使用教程</a> <br /> <a href="http://topology.le5le.com/assets/img/topology_wechat.jpg?t=1" target="_blank" >微信交流羣(大羣)</a> <br /> <a href="http://topology.le5le.com/assets/img/topology_wechat2.jpg" target="_blank">微信交流羣2</a> <br /> <a href="https://www.yuque.com/alsmile/topology/faq#EVbCgt" target="_blank">聯繫咱們</a> </div> <div class="title">[Todo] 將來規劃</div> <ul class="group"> <li>Github issues</li> <li>React demo</li> <li>Vue3 demo</li> <li>系列教程</li> </ul> <div class="bottom"> <div class="title">小提示</div> <ul class="group"> <li>方向鍵:控制節點移動5個像素</li> <li>Ctrl + 方向鍵:控制節點移動1個像素</li> <li>Ctrl + 鼠標移動:移動整個畫布</li> <li>Ctrl + 鼠標滾輪:縮放</li> <li>添加或選中節點,右側屬性支持上傳各類圖片哦</li> </ul> </div> </div> <!-- 選中節點 --> <div v-if="props.node"> <div class="title">位置和大小</div> <div class="items"> <div class="flex grid"> <div>X(px)</div> <div class="ml5">Y(px)</div> </div> <div class="flex grid"> <div> <el-input-number v-model="props.node.rect.x" controls-position="right" @change="onChange" ></el-input-number> </div> <div class="ml5"> <el-input-number v-model="props.node.rect.y" controls-position="right" @change="onChange" ></el-input-number> </div> </div> </div> <div class="items"> <div class="flex grid"> <div>寬(px)</div> <div class="ml5">高(px)</div> </div> <div class="flex grid"> <div> <el-input-number v-model="props.node.rect.width" controls-position="right" @change="onChange" ></el-input-number> </div> <div class="ml5"> <el-input-number v-model="props.node.rect.height" controls-position="right" @change="onChange" ></el-input-number> </div> </div> </div> </div> </div> </template> <script > export default { data() { return {} }, props: { props: { type: Object, require: true } }, methods: { onChange(value) { this.$emit('change', this.props.node) } } } </script>
其中,props.node、line、multi分別表示是否選中節點、連線、多個對象。
這裏咱們暫時沒有用到vuex(後面教程介紹),直接使用原生的雙向綁定更簡單。用$emit通知父組件屬性改變事件。
相關屬性值,參數API文檔:https://www.yuque.com/alsmile...
<div class="props"> <CanvasProps :props.sync="props" @change="onUpdateProps"></CanvasProps> </div>
一樣,咱們利用.sync關鍵字使用雙向綁定,並接收chang事件,反饋給畫布組件:
onUpdateProps(node) { // 若是是node屬性改變,須要傳入node,從新計算node相關屬性值 // 若是是line屬性改變,無需傳參 this.canvas.updateProps(node) }
自此,一個簡單的繪圖項目就完成了,後續功能完善待續。
但,但,但...右側屬性欄,但願你們根據開發文檔去參與完善,展現本身舞臺的機會到了,可加入貢獻者名單哦!不清楚的,歡迎聯繫管理員:(微信)alsmile123,或加羣:
經過GitHub的pr方式:
開源項目不易,歡迎你們一塊兒參與,給【文章、GitHub開源庫】點星點贊,或資助服務器: