浏览代码

工具栏:字号,样式,填充,边框

cxmo 1 年之前
父节点
当前提交
fd674fc9d6

+ 14 - 74
src/views/chartFrame_manage/common/config.js

@@ -25,11 +25,15 @@ export const baseNode = {
         body:{
             fill:'#fff',//背景色
             stroke:'#333',//边框色
+            strokeWidth:2,//边框宽度
+            strokeDasharray:0,//虚线
         },
         label:{ //与svg text属性相同
             fill:'#333',//文字颜色
             fontSize:14,//文字大小
             fontWeight:'normal',//文字粗细
+            fontStyle:'normal',//斜体
+            textDecoration:'normal',//下划线
         }
     },
     ports: { //基础连接桩
@@ -65,80 +69,14 @@ export const baseNode = {
 }
 //基础线条
 export const baseEdge = {
-
-}
-
-//基础工具栏
-export const baseToolBar = [
-    {
-        toolkey:'undo',
-        toolname:'撤销',
-    },
-    {
-        toolkey:'redo',
-        toolname:'恢复',
-    },
-    {
-        toolkey:'fontFamily',
-        toolname:'字体'
-    },
-    {
-        toolkey:'fontSize',
-        toolname:'字号'
-    },
-    {
-        toolkey:'fontWeight',
-        toolname:'加粗'
-    },
-    {//fontStyle
-        toolkey:'italic',
-        toolname:'倾斜'
-    },
-    {
-        toolkey:'textDecoration',
-        toolname:'下划线'
-    },
-    {
-        toolkey:'label-fill',
-        toolname:'字体颜色'
-    },
-    {
-        toolkey:'lineHeight',
-        toolname:'文本行高'
-    },
-    {
-        toolkey:'textAligh',
-        toolname:'文本对齐'
-    },
-    {
-        toolkey:'node-fill',
-        toolname:'颜色填充'
-    },
-    {
-        toolkey:'stroke',
-        toolname:'线条颜色'
-    },
-    {
-        toolkey:'',
-        toolname:'线条宽度'
-    },
-    {
-        toolkey:'',
-        toolname:'线条样式'
-    },
-    {
-        toolkey:'',
-        toolname:'连线类型'
-    },
-    {
-        toolkey:'',
-        toolname:'开始箭头'
-    },
-    {
-        toolkey:'',
-        toolname:'结束箭头'
+    attrs:{
+        line:{
+            stroke:'#333',//线条颜色
+            strokeWidth:2,//线条宽
+            strokeDasharray:0,//虚线
+        }
     }
-]
+}
 
 //字号
 export const sizeOptions = [
@@ -153,4 +91,6 @@ export const sizeOptions = [
     14,
     12,
     10,
-]
+]
+//线框宽度
+export const stokeWidthOptions = [1,2,3,4,5]

+ 31 - 9
src/views/chartFrame_manage/common/event.js

@@ -1,5 +1,6 @@
-//监听画布事件
-export const myEvents = (graph)=>{
+import { baseNode } from './config';
+//监听画布事件 tempThis是一个vue实例
+export const myEvents = (graph,tempThis=null)=>{
     //右键节点/边
     graph.on('cell:contextmenu',({cell,e})=>{
         if(window.location.pathname.startsWith('/chartframe')) return 
@@ -9,13 +10,12 @@ export const myEvents = (graph)=>{
         dom.style.top = e.clientY-3 + 'px';
     })
 
-    /* graph.on('node:click',({node,e})=>{
+    graph.on('node:click',({node,e})=>{
         if(window.location.pathname.startsWith('/editframe')) return 
-        if(node.data&&node.data.myETAId){
-            graph.showDialog = true
-            console.log('now',graph)
+        if(node.data&&node.data.id){
+            tempThis&&tempThis.$emit('showDialog',node.data)
         }
-    }) */
+    })
 
     /* 鼠标移入移出控制连接桩 */
     graph.on('node:mouseenter', ({ node, e }) => {
@@ -46,8 +46,30 @@ export const myEvents = (graph)=>{
         ])
       })
       
-      graph.on('edge:mouseleave', ({ edge }) => {
+    graph.on('edge:mouseleave', ({ edge }) => {
         edge.removeTools()
-      })
+    })
+
+    /* 元素选中事件 */
+    graph.on('cell:selected',({cell})=>{
+        const selects = graph.getSelectedCells()
+        if(cell.isNode()){
+            tempThis.isSelectEdge = false
+            tempThis.isSelectNode = true
+        }else if(cell.isEdge()){
+            tempThis.isSelectNode = false
+            tempThis.isSelectEdge = true
+        }
+        tempThis.cleanSelect = false
+        selects&&selects.length&&(tempThis.currentCell = selects[0])
+    })
+    /* 点击空白区域清空选区 屏蔽工具栏 */
+    graph.on('blank:click',() => {
+        graph.cleanSelection();
+        tempThis.isSelectEdge = false
+        tempThis.isSelectNode = false
+        tempThis.cleanSelect = true
+        tempThis.currentCell = baseNode
+    })
 
 }

+ 2 - 2
src/views/chartFrame_manage/common/graph.js

@@ -18,7 +18,7 @@ const viewConfig = {
     connecting:{},
     history:false,//关闭画布撤销/重做能力。
 }
-export function myGraph(wrapper) {
+export function myGraph(wrapper,tempThis) {
     const otherConfig = window.location.pathname.startsWith('/editframe')?{}:viewConfig
     const graph = new Graph({...{
         container: document.getElementById(wrapper),
@@ -117,6 +117,6 @@ export function myGraph(wrapper) {
             container: document.getElementById("frameMinimap"),
         }
     },...otherConfig})
-    myEvents(graph)
+    myEvents(graph,tempThis)
     return graph
 }

+ 17 - 11
src/views/chartFrame_manage/components/frameContainer.vue

@@ -3,7 +3,9 @@
     <div class="frame-container-wrap">
         <!-- 工具栏 -->
         <FrameToolBar v-if="$route.path==='/editframe'"
-            :graph="graph"
+            :is-select-edge="isSelectEdge"
+            :is-select-node="isSelectNode"
+            :current-cell="currentCell||baseNode"
         ></FrameToolBar>
         <div class="frame-container" id="frameContainer"></div>
         <!-- 缩略图 -->
@@ -28,6 +30,7 @@ import FrameToolBar from './frameToolBar.vue';
 export default {
     components:{ElDropdownMenu,FrameToolBar},
     data() {
+        this.baseNode = baseNode
         return {
             graph:null,
             contextMenu:[{
@@ -40,19 +43,22 @@ export default {
                 key: 'del',
                 icon: 'el-icon-delete'
             }],//右键菜单
+            isSelectEdge:false,
+            isSelectNode:false,
+            currentCell:null,
         };
     },
+    watch:{
+        cleanSelect(newVal){
+            if(newVal){
+                this.currentCell = null
+            }
+        }
+    },
     methods: {
         init(){
-            this.graph = new myGraph('frameContainer');
-            const tempThis = this
-            //需要调用vue实例的事件添加在这里
-            this.graph.on('node:click',({node,e})=>{
-                if(window.location.pathname.startsWith('/editframe')) return 
-                if(node.data&&node.data.id){
-                    tempThis.$emit('showDialog',node.data)
-                }
-            })
+            //如果需要在内部调用vue实例,则初始化时就将this传入
+            this.graph = new myGraph('frameContainer',this);
             //mock
             this.graph.addNode({
                 ...baseNode,
@@ -131,7 +137,7 @@ export default {
             const dom = $('#context-menu-wrapper')[0];
             dom.style.left = '-9999px';
             dom.style.top = '-9999px';
-        }
+        },
     },
     mounted(){
         this.init()

+ 190 - 43
src/views/chartFrame_manage/components/frameToolBar.vue

@@ -19,54 +19,126 @@
             <!-- 字体 暂定-->
             <!-- 字号 -->
             <ToolItem tooltip="字号" toolkey="fontSize">
-                <el-dropdown @command="changeStyle" trigger="click">
+                <el-dropdown @command="changeStyle" trigger="click" class="tool-item">
                     <span class="el-dropdown-link tool-item"> 
-                        <span>{{node}}</span>
+                        <span>{{nodeStyle.fontSize}}px</span>
                         <i class="el-icon-caret-bottom"></i>
                     </span>
                     <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item v-for="item in sizeOptions" 
-                            :key="item" :command="{attr:'fontSize',value:item}">{{item}}</el-dropdown-item>
+                            :key="item" :command="{attr:'label/fontSize',value:item}">{{item}}</el-dropdown-item>
                     </el-dropdown-menu>
+                    <span class="disabled" v-if="!isSelectNode"></span>
                 </el-dropdown>
+                
             </ToolItem>
             <!-- 加粗 -->
             <ToolItem tooltip="加粗" toolkey="fontWeight">
                 <span class="tool-item">
-                    <span class="item-text">B</span>
-                    <span class="disabled"></span>
+                    <span class="item-text"
+                        @click="changeStyleToggle('label/fontWeight')">B</span>
+                    <span class="disabled" v-if="!isSelectNode"></span>
                 </span>
             </ToolItem>
             <!-- 斜体 -->
             <ToolItem tooltip="斜体" toolkey="fontstyle">
                 <span class="tool-item">
-                    <span style="font-style: italic;" class="item-text">&nbsp;I&nbsp;</span>
-                    <span class="disabled"></span>
+                    <span style="font-style: italic;" class="item-text"
+                        @click="changeStyleToggle('label/fontStyle')">&nbsp;I&nbsp;</span>
+                    <span class="disabled" v-if="!isSelectNode"></span>
                 </span>
             </ToolItem>
             <!-- 下划线 -->
             <ToolItem tooltip="下划线" toolkey="textDecoration">
                 <span class="tool-item">
-                    <span style="text-decoration: underline;" class="item-text">U</span>
-                    <span class="disabled"></span>
+                    <span style="text-decoration: underline;" class="item-text"
+                        @click="changeStyleToggle('label/textDecoration')">U</span>
+                    <span class="disabled" v-if="!isSelectNode"></span>
                 </span>
             </ToolItem>
             <!-- 字体颜色 -->
             <ToolItem tooltip="字体颜色" toolkey="textDecoration">
                 <span class="tool-item">
-                    <!-- <span style="color:red;" class="item-text">T</span> -->
-                    <label for="fontColor" :style="`color:${color}`">T</label>
-                    <input type="color" id="fontColor" style="width: 0;height: 0;visibility: hidden;" @input="valueChange"/>
-                    <!-- <span class="disabled"></span> -->
+                    <label for="label/fill" :style="`color:${color}`">T</label>
+                    <input type="color" id="label/fill" style="width: 0;height: 0;visibility: hidden;" 
+                        :value="nodeStyle.color"
+                        @input="valueChange"/>
+                    <span class="disabled" v-if="!isSelectNode"></span>
                 </span>
             </ToolItem>
             <!-- 文本行高 暂定-->
             <!-- 文本对齐 暂定-->
             <!-- 节点颜色填充 -->
+            <ToolItem tooltip="填充颜色" toolkey="fillColor">
+                <span class="tool-item">
+                    <label for="body/fill" :style="`color:${fillColor}`"><i class="el-icon-s-open"></i></label>
+                    <input type="color" id="body/fill" style="width: 0;height: 0;visibility: hidden;"
+                        :value="nodeStyle.fill"
+                        @input="valueChange"/>
+                </span>
+            </ToolItem>
             <!-- 节点/线条边框颜色 -->
+            <ToolItem tooltip="边框颜色" toolkey="borderColor">
+                <span class="tool-item">
+                    <label for="storke" :style="`color:${borderColor}`"><i class="el-icon-minus"></i></label>
+                    <input type="color" id="storke" style="width: 0;height: 0;visibility: hidden;" 
+                        :value="cellStyle.stroke"
+                        @input="valueChange"/>
+                </span>
+            </ToolItem>
             <!-- 节点/线条边框宽度 -->
+            <ToolItem tooltip="线框宽度" toolkey="stokeWidth">
+                <el-dropdown @command="changeCellStyle" trigger="click" class="tool-item">
+                    <span class="el-dropdown-link tool-item"> 
+                        <i class="el-icon-minus"></i>
+                        <i class="el-icon-caret-bottom"></i>
+                    </span>
+                    <el-dropdown-menu slot="dropdown">
+                        <el-dropdown-item v-for="item in stokeWidthOptions" 
+                            :key="item" :command="{attr:'width',value:item}">{{item}}</el-dropdown-item>
+                    </el-dropdown-menu>
+                    <span class="disabled" v-if="!isSelectNode&&!isSelectEdge"></span>
+                </el-dropdown>
+            </ToolItem>
             <!-- 节点/线条边框样式 -->
+            <ToolItem tooltip="边框样式" toolkey="stokeWidth">
+                <el-dropdown @command="changeCellStyle" trigger="click" class="tool-item">
+                    <span class="el-dropdown-link tool-item"> 
+                        <i class="el-icon-minus"></i>
+                        <i class="el-icon-caret-bottom"></i>
+                    </span>
+                    <el-dropdown-menu slot="dropdown">
+                        <el-dropdown-item :command="{attr:'dash',value:5}">
+                            <i class="iconfont icon--xuxian" style="color:'#000';fontSize:30px"></i>
+                        </el-dropdown-item>
+                        <el-dropdown-item :command="{attr:'dash',value:0}">
+                            <i class="iconfont icon--shixian" style="color:'#000';fontSize:30px"></i>
+                        </el-dropdown-item>
+                    </el-dropdown-menu>
+                    <span class="disabled" v-if="!isSelectNode&&!isSelectEdge"></span>
+                </el-dropdown>
+            </ToolItem>
             <!-- 开始箭头 -->
+            <!-- <el-dropdown trigger="click" @command="setGraphStyle">
+                <div class="el-dropdown-link">
+                    <img src="~@/assets/icons/arrow.svg" width="20" height="20" style="vertical-align: middle;">
+                    <i class="el-icon-arrow-down" style="font-size:12px;"></i>
+                </div>
+                <el-dropdown-menu slot="dropdown">
+                    <el-dropdown-item :command="{attr:'',val: 'classic' , key:'end'}">
+                        <i class="iconfont icon-arrow-right" style="color:'#000';fontSize:24px"></i>
+                    </el-dropdown-item>
+                    <el-dropdown-item :command="{attr:'',val: 'classic' , key:'start'}">
+                            <i class="iconfont icon-arrow-left" style="color:'#000';fontSize:24px"></i>
+                    </el-dropdown-item>
+                    <el-dropdown-item :command="{attr:'',val: 'classic' , key:'both'}">
+                            <i class="iconfont icon-arrow-both" style="color:'#000';fontSize:30px"></i>
+                    </el-dropdown-item>
+                    <el-dropdown-item :command="{attr:'',val: '' , key:'none'}">
+                            <i class="iconfont icon--shixian" style="color:'#000';fontSize:32px"></i>
+                    </el-dropdown-item>
+                </el-dropdown-menu>
+            </el-dropdown> -->
             <!-- 结束箭头 -->
         </div>
         
@@ -74,28 +146,117 @@
 </template>
 
 <script>
+import '@/assets/icons/iconfont.css';
 import ToolItem from './toolItem.vue';
-import {sizeOptions} from '../common/config';
+import {sizeOptions,stokeWidthOptions} from '../common/config';
 export default {
     components: { ToolItem },
-    props:['graph'],
+    props:{
+        isSelectNode:{//当前选中的元素是否是节点
+            type:Boolean,
+            default:false
+        },
+        isSelectEdge:{//当前选中的元素是否是边
+            type:Boolean,
+            default:false
+        },
+        currentCell:{//当前传入的元素,Node/Edge
+            type:Object,
+        },
+    },
     data() {
         this.sizeOptions=sizeOptions
+        this.stokeWidthOptions=stokeWidthOptions
         return {
-            node:14,
-            color:'#333'
+            nodeStyle:{
+                fontSize:14,
+                fill:'#333',
+                color:'#333',
+            },
+            edgeStyle:{
+
+            },
+            cellStyle:{
+                stroke:'#333',
+            },
+            color:'#333',
+            fillColor:'#333',
+            borderColor:'#333',
         };
     },
+    watch:{
+        isSelectNode(newVal){
+            if(!newVal){
+                //重置 node相关样式
+                this.nodeStyle = {
+                    fontSize:14,
+                    fill:'#333',
+                    color:'#333',
+                    stroke:'#333'
+                }
+            }
+        },
+        currentCell(newVal){
+            if(newVal){
+                if(newVal.isNode&&newVal.isNode()){
+                    this.nodeStyle = {
+                        fontSize:newVal.attrs.label.fontSize,
+                        fill:newVal.attrs.body.fill,
+                        color:newVal.attrs.label.fill,
+                        stroke:newVal.attrs.body.stroke,
+                    }
+                    this.cellStyle = {
+                        store:newVal.attrs.body.stroke,
+                    }
+                }
+                if(newVal.isEdge&&newVal.isEdge()){
+                    this.cellStyle = {
+                        store:newVal.attrs.line.stroke
+                    }
+                }
+
+            }
+        }
+    },
     methods: {
-        setGraphStyle(){
-            console.log('aaa')
+        changeStyleToggle(attr){
+            const value = this.currentCell.attr(attr)
+            const valueMap = {
+                'label/fontWeight':['normal','bold'],
+                'label/fontStyle':['normal','italic'],
+                'label/textDecoration':['normal','underline'],
+            }
+            this.changeStyle({attr,
+                value:value===valueMap[attr][0]
+                ?valueMap[attr][1]
+                :valueMap[attr][0]})
+        },
+        changeStyle({attr,value}){
+            this.currentCell.attr(attr,value)
+            if(attr==='label/fontSize'){
+                this.nodeStyle.fontSize = value
+            }
+            
         },
         valueChange(e){
             //t.target.value: "#9c3535"
-            //console.log('test',e)
             if(e.target){
-                this.color = e.target.value
+                const styleMap = {
+                    'storke':['body/stroke','line/stroke'],
+                    'width':['body/strokeWidth','line/strokeWidth'],
+                    'dash':['body/strokeDasharray','line/strokeDasharray']
+                }
+                const {id,value} = e.target
+                let attr = id
+                if(styleMap[id]){
+                    attr = this.isSelectNode?styleMap[id][0]:styleMap[id][1]
+                } 
+                console.log('attr value',attr,value)
+                this.currentCell.attr(attr,value)
             }
+        },
+        changeCellStyle({attr,value}){
+            this.valueChange({target:{id:attr,value}})
         }
     },
     mounted(){
@@ -106,28 +267,11 @@ export default {
 
 <style lang="scss">
 .frame-tool-bar-wrap{
-    .el-select {
-        .el-input__inner {
-            border: none;
-            height: 28px;
-            padding: 0;
-            line-height: 28px;
-            width: 30px;
-            background: transparent;
-        }
-        .el-input__suffix {
-            /* display: none; */
-            top: -5px;right: -10px;
-
-            .el-select__caret {
-                transform: rotateZ(0);
-            }
-
-            .el-icon-arrow-up:before {
-                /* content: "\e790"; */
-                content: "\e6df";
-                font-size: 12px;
-                color: #333;
+    .tool-item{
+        .el-input{
+            .el-input__inner {
+                padding:0;
+                height:100%;
             }
         }
     }
@@ -152,6 +296,9 @@ export default {
             position: relative;
             .item-text{
                 padding:0 2px;
+                &.bold-act{
+                    font-weight: bold;
+                }
             }
             .disabled {
                 color: #bbb;