• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

GOJS使用教程

武飞扬头像
高级API调用攻城狮
帮助1

简介

GoJS是一个用于交互式图表和图形的JavaScript和TypeScript库。允许您为用户构建各种图表,从简单的流程图、组织图到图表、SCADA和BPMN图表、医学图表(如基因组图)等等。GoJS使用可定制的模板和布局,可以轻松构建复杂节点、链接和组的JavaScript图。
为用户提供了许多高级功能,如拖放、复制粘贴、就地文本编辑、工具提示、上下文菜单、自动布局和操作。

安装依赖

yarn add gojs@2.2.7

页面使用

  1.  
    <template>
  2.  
    <div>
  3.  
    <div id="myDiagramDiv"
  4.  
    class="diagram-box"></div>
  5.  
    <ul id="contextMenu"
  6.  
    class="menu">
  7.  
    <li id="cut"
  8.  
    class="menu-item"
  9.  
    @click="cxcommand($event)">Cut</li>
  10.  
    <li id="copy"
  11.  
    class="menu-item"
  12.  
    @click="cxcommand($event)">Copy</li>
  13.  
    <li id="paste"
  14.  
    class="menu-item"
  15.  
    @click="cxcommand($event)">Paste</li>
  16.  
    <li id="delete"
  17.  
    class="menu-item"
  18.  
    @click="cxcommand($event)">Delete</li>
  19.  
    </ul>
  20.  
    </div>
  21.  
    </template>
学新通
  1.  
    import go from 'gojs';
  2.  
    export default {
  3.  
    computed: {},
  4.  
    data() {
  5.  
    return {
  6.  
    myDiagram: {},
  7.  
    };
  8.  
    },
  9.  
    created() {},
  10.  
    mounted() {
  11.  
    this.init();
  12.  
    },
  13.  
    methods: {
  14.  
    init() {
  15.  
    /*
  16.  
    图表(Diagram)
  17.  
    基本元素:点(Node)、线(Link)
  18.  
    点和线自由组合就是 组(Group)
  19.  
    所有的元素都处在 图层(Layer) 上,并且可以对他们进行 布局(Layout)
  20.  
    每一个点和线都是通过模板来描述他们的文本、形状、颜色等信息以及交互行为。每一个模板其实就是一个 面板(Panel)
  21.  
    每个图表都是通过 数据模型(Model) 来填充和确定 点 的信息和 线 的所属关系
  22.  
    并且我们只需创建好 点 和 线 的模板以及数据模型,其他事情都交给gojs处理
  23.  
    Model又分为了以下三种类型:
  24.  
    Model:最基本的(不带连线)
  25.  
    GraphLinksModel :高级点的动态连线图
  26.  
    TreeModel:树形图的模型
  27.  
    gojs通过Model.nodeDataArray方法和GraphLinksModel.linkDataArray方法自动加载模型并构建元素
  28.  
    通过ToolManager对象管理工具类(交互行为),譬如管理CommandHandler对象用来添加一些键盘命令
  29.  
    gojs定义了一个用于创建GraphObject对象的静态函数GraphObject.make
  30.  
    GraphObject是所有图形对象的抽象类,这个类的子类包括Panel、Shape、TextBlock、Picture和Placeholder。其中Panel派生的子类Part是Node和Link的父类
  31.  
    Part是一个图表对象,它继承自Panel。它是所有用户操作级别对象的基类
  32.  
    Shape:形状——Rectangle(矩形)、RoundedRectangle(圆角矩形),Ellipse(椭圆形),Triangle(三角形),Diamond(菱形),Circle(圆形)等
  33.  
    TextBlock:文本域(可编辑)
  34.  
    Picture:图片
  35.  
    Panel:容器来保存其他Node的集合
  36.  
    */
  37.  
    var $ = go.GraphObject.make; // 给go.GraphObject.make起简称
  38.  
    // var diagram = new go.Diagram('myDiagramDiv');
  39.  
    // diagram.model = new go.GraphLinksModel([{ key: 'Hello' }, { key: 'World!' }], [{ from: 'Hello', to: 'World!' }]);
  40.  
    // 创建Diagram对象 定义画布的基本属性
  41.  
    var myDiagram = (this.myDiagram = $(
  42.  
    go.Diagram,
  43.  
    'myDiagramDiv', // 必须命名或引用DIV HTML元素 画布绑定的Div的ID
  44.  
    {
  45.  
    LinkDrawn: showLinkLabel, // 监听线生成事件
  46.  
    LinkRelinked: showLinkLabel, // 线重新连接事件
  47.  
    initialContentAlignment: go.Spot.Center, // 任何初始图都位于视口中的中心
  48.  
    InitialLayoutCompleted: loadDiagramProperties, // 在加载新模型之前不要初始化一些属性
  49.  
    'toolManager.mouseWheelBehavior': go.ToolManager.WheelZoom, // 鼠标滚轮事件放大和缩小,而不是向上和向下滚动
  50.  
    // 允许通过双击创建一个新节点,与nodeTemplate里TextBlock绑定的属性值new go.Binding('text', 'key')有关
  51.  
    'clickCreatingTool.archetypeNodeData': { key: 'new node', color: 'white' },
  52.  
    'undoManager.isEnabled': true, // 允许取消和重做 undo & redo
  53.  
    allowZoom: false, // 不允许用户改变图表的规模
  54.  
    'grid.visible': true, // 画布上面是否出现网格
  55.  
    }
  56.  
    ));
  57.  
     
  58.  
    function loadDiagramProperties(e) {}
  59.  
     
  60.  
    // TextBlock案例
  61.  
    myDiagram.add(
  62.  
    $(
  63.  
    go.Part,
  64.  
    'Vertical',
  65.  
    $(
  66.  
    go.Panel,
  67.  
    'Vertical',
  68.  
    // TextBlock是用于显示文本信息的对象 font属性设置文本的字体 stroke属性设置文本字体的颜色
  69.  
    $(go.TextBlock, {
  70.  
    text: 'a Text Block\nwith three logical lines\nof text',
  71.  
    background: 'lightgreen',
  72.  
    margin: 2,
  73.  
    stroke: 'red',
  74.  
    isMultiline: false, // 设置是否开启内嵌文本中的换行符作用
  75.  
    }),
  76.  
    $(go.TextBlock, {
  77.  
    text: 'a Text Block\nwith three logical lines\nof text',
  78.  
    background: 'lightgreen',
  79.  
    margin: 2,
  80.  
    isMultiline: true,
  81.  
    }),
  82.  
    $(go.TextBlock, {
  83.  
    text: '文本块\n中有三行居中\n文本',
  84.  
    background: 'lightgreen',
  85.  
    margin: 2,
  86.  
    isMultiline: true,
  87.  
    textAlign: 'center', // 对齐方式
  88.  
    font: 'bold 14pt serif',
  89.  
    }),
  90.  
    $(go.TextBlock, {
  91.  
    text: 'a single line of centered text that should wrap because we will limit the width',
  92.  
    background: 'lightgreen',
  93.  
    margin: 2,
  94.  
    width: 80,
  95.  
    wrap: go.TextBlock.WrapFit, // 根据TextBlock的尺寸自动对文本进行换行
  96.  
    textAlign: 'center',
  97.  
    })
  98.  
    ),
  99.  
    $(
  100.  
    go.Panel,
  101.  
    'Vertical',
  102.  
    { width: 150, defaultStretch: go.GraphObject.None },
  103.  
    $(go.TextBlock, { text: 'alignment: Left', background: 'lightgreen', margin: 2, alignment: go.Spot.Left }),
  104.  
    $(go.TextBlock, { text: 'alignment: Center', background: 'lightgreen', margin: 2, alignment: go.Spot.Center }),
  105.  
    $(go.TextBlock, { text: 'alignment: Right', background: 'lightgreen', margin: 2, alignment: go.Spot.Right })
  106.  
    ),
  107.  
    // editable对TextBlock文本的编辑功能
  108.  
    // 设置TextBlock.textValidation属性编写验证规则,该属性的值为function。设置TextBlock.textEditor属性更换文本编辑器
  109.  
    $(go.TextBlock, { text: 'select and then click to edit', background: 'lightblue', editable: true, isMultiline: false }),
  110.  
    $(go.TextBlock, { text: 'this one allows embedded newlines', background: 'lightblue', editable: true })
  111.  
    )
  112.  
    );
  113.  
     
  114.  
    // 单独创建能够复用的对象,比如样式刷(Brush)
  115.  
    var violetbrush = $(go.Brush, go.Brush.Linear, { 0.0: 'Violet', 1.0: 'Lavender' });
  116.  
     
  117.  
    // Shape案例
  118.  
    myDiagram.add(
  119.  
    $(
  120.  
    go.Part,
  121.  
    'Table',
  122.  
    // 通过Shape可以构建一个几何图形
  123.  
    // fill属性设置填充颜色。
  124.  
    // 如果设置为null,那么只能点击图形的轮廓才能选中,点击图形里面是无法选中的。而如设置为transparent,点击图形的任何地方都可以选中该图形。
  125.  
    $(go.Shape, 'RoundedRectangle', { row: 0, column: 0, width: 40, height: 40, margin: 4, fill: violetbrush }),
  126.  
    $(go.TextBlock, 'green', { row: 1, column: 0 }),
  127.  
    $(go.Shape, { row: 0, column: 1, figure: 'RoundedRectangle', width: 40, height: 40, margin: 4, fill: 'white' }),
  128.  
    $(go.TextBlock, 'white', { row: 1, column: 1 }),
  129.  
    $(go.Shape, { row: 0, column: 2, figure: 'Ellipse', width: 40, height: 40, margin: 4, fill: 'transparent' }),
  130.  
    $(go.TextBlock, 'transparent', { row: 1, column: 2 }),
  131.  
    // angle和.scale属性设置Shape的角度和比例
  132.  
    $(go.Shape, { row: 0, column: 3, figure: 'Ellipse', width: 40, height: 40, margin: 4, fill: null, angle: 30, scale: 1.5 }),
  133.  
    $(go.TextBlock, 'null', { row: 1, column: 3 })
  134.  
    )
  135.  
    );
  136.  
     
  137.  
    // 右键菜单
  138.  
    var cxElement = document.getElementById('contextMenu');
  139.  
    var myContextMenu = $(go.HTMLInfo, {
  140.  
    show: showContextMenu,
  141.  
    hide: hideContextMenu,
  142.  
    });
  143.  
     
  144.  
    cxElement.addEventListener(
  145.  
    'contextmenu',
  146.  
    function (e) {
  147.  
    e.preventDefault();
  148.  
    return false;
  149.  
    },
  150.  
    false
  151.  
    );
  152.  
     
  153.  
    // 显示右键菜单回调函数
  154.  
    function showContextMenu(obj, diagram, tool) {
  155.  
    // 只显示当前状态下的相关按钮。
  156.  
    var cmd = diagram.commandHandler;
  157.  
    var hasMenuItem = false;
  158.  
    function maybeShowItem(elt, pred) {
  159.  
    if (pred) {
  160.  
    elt.style.display = 'block';
  161.  
    hasMenuItem = true;
  162.  
    } else {
  163.  
    elt.style.display = 'none';
  164.  
    }
  165.  
    }
  166.  
    // 重写键盘工具类commandHandler,去拦截调用deleteSelection 实现取消删除的功能
  167.  
    maybeShowItem(document.getElementById('cut'), cmd.canCutSelection());
  168.  
    maybeShowItem(document.getElementById('copy'), cmd.canCopySelection());
  169.  
    maybeShowItem(document.getElementById('paste'), cmd.canPasteSelection(diagram.toolManager.contextMenuTool.mouseDownPoint));
  170.  
    maybeShowItem(document.getElementById('delete'), cmd.canDeleteSelection());
  171.  
    // Now show the whole context menu element
  172.  
    if (hasMenuItem) {
  173.  
    cxElement.classList.add('show-menu');
  174.  
    // we don't bother overriding positionContextMenu, we just do it here:
  175.  
    var mousePt = diagram.lastInput.viewPoint;
  176.  
    cxElement.style.left = mousePt.x 5 'px';
  177.  
    cxElement.style.top = mousePt.y 'px';
  178.  
    }
  179.  
    // 可选:使用' window '的单击监听与事件捕获
  180.  
    // 如果用户单击页面上其他地方,则删除上下文菜单
  181.  
    window.addEventListener('click', hideCX, true);
  182.  
    }
  183.  
    function hideCX() {
  184.  
    if (myDiagram.currentTool instanceof go.ContextMenuTool) {
  185.  
    myDiagram.currentTool.doCancel();
  186.  
    }
  187.  
    }
  188.  
    // 隐藏右键菜单回调函数
  189.  
    function hideContextMenu() {
  190.  
    cxElement.classList.remove('show-menu');
  191.  
    // 可选:使用' window '的单击监听与事件捕获
  192.  
    // 如果用户单击页面上其他地方,则删除上下文菜单
  193.  
    window.removeEventListener('click', hideCX, true);
  194.  
    }
  195.  
    // 全局(图表空白处)绑定自定义右键菜单
  196.  
    myDiagram.contextMenu = myContextMenu;
  197.  
     
  198.  
    // 定义一个函数来创建一个新连线用来连接两个节点
  199.  
    function makePort(name, align, spot, output, input) {
  200.  
    var horizontal = align.equals(go.Spot.Top) || align.equals(go.Spot.Bottom);
  201.  
    return $(go.Shape, {
  202.  
    fill: 'transparent', // 定义锚点颜色
  203.  
    strokeWidth: 0, // no stroke
  204.  
    width: horizontal ? NaN : 8, // if not stretching horizontally, just 8 wide
  205.  
    height: !horizontal ? NaN : 8, // if not stretching vertically, just 8 tall
  206.  
    alignment: align, // 规定锚点的位置
  207.  
    stretch: horizontal ? go.GraphObject.Horizontal : go.GraphObject.Vertical,
  208.  
    portId: name, // 规定锚点的名称
  209.  
    fromSpot: spot, // 输出点
  210.  
    fromLinkable: output, // 是否可以作为新连线的末节点
  211.  
    toSpot: spot, // 输入点
  212.  
    toLinkable: input, // 是否可以作为新连线的初始节点
  213.  
    cursor: 'pointer', // 显示不同的光标以指示潜在的链接点
  214.  
    mouseEnter: function (e, port) {
  215.  
    // the PORT argument will be this Shape 鼠标移入
  216.  
    if (!e.diagram.isReadOnly) port.fill = 'rgba(255,0,255,1)';
  217.  
    },
  218.  
    mouseLeave: function (e, port) {
  219.  
    port.fill = 'transparent';
  220.  
    },
  221.  
    });
  222.  
    }
  223.  
    // 监听线生成和重新连接事件
  224.  
    function showLinkLabel(e) {
  225.  
    var label = e.subject.findObject('LABEL');
  226.  
    if (label !== null) label.visible = e.subject.fromNode.data.category === 'Conditional';
  227.  
    }
  228.  
     
  229.  
    // Link案例
  230.  
    // 自定义Nodes案例
  231.  
    // 节点面板子元素布局定义
  232.  
    // Auto:子元素叠加布局、Vertical:子元素垂直布局、Horizontal:子元素水平布局、Position:子元素坐标布局、Table:子元素表格布局
  233.  
    // Spot: Node里的元素都排列在这个Node中的各个锚点上
  234.  
    myDiagram.nodeTemplate = $(
  235.  
    go.Node,
  236.  
    'Auto',
  237.  
    new go.Binding('location', 'loc', go.Point.parse), // 申明动态绑定指定属性,将数据源中提供指定字段的值赋值给当前的指定属性
  238.  
    // new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify) 双向绑定
  239.  
    $(go.Shape, 'RoundedRectangle', {
  240.  
    fill: 'white',
  241.  
    portId: '',
  242.  
    cursor: 'pointer',
  243.  
    // 允许可以更改连线的端口,配合linkTemplate的relinkableFrom和relinkableTo属性使用
  244.  
    fromLinkable: true,
  245.  
    fromLinkableSelfNode: true,
  246.  
    fromLinkableDuplicates: true,
  247.  
    toLinkable: true,
  248.  
    toLinkableSelfNode: true,
  249.  
    toLinkableDuplicates: true,
  250.  
    }),
  251.  
    $(go.Picture, { maxSize: new go.Size(50, 50) }, new go.Binding('source', 'img')),
  252.  
    $(go.TextBlock, { margin: new go.Margin(65, 0, 0, 0) }, new go.Binding('text', 'key')),
  253.  
    {
  254.  
    // 鼠标悬浮title
  255.  
    toolTip: $(
  256.  
    go.Adornment,
  257.  
    'Auto',
  258.  
    $(
  259.  
    go.Shape,
  260.  
    { fill: '#F3F3C3' },
  261.  
    new go.Binding('visible', 'info', function (i) {
  262.  
    return i ? true : false;
  263.  
    })
  264.  
    ),
  265.  
    $(go.TextBlock, { margin: 4 }, new go.Binding('text', 'info'))
  266.  
    ),
  267.  
    },
  268.  
    { contextMenu: myContextMenu },
  269.  
    makePort('T', go.Spot.Top, go.Spot.TopSide, false, true),
  270.  
    makePort('L', go.Spot.Left, go.Spot.LeftSide, true, true),
  271.  
    makePort('R', go.Spot.Right, go.Spot.RightSide, true, true),
  272.  
    makePort('B', go.Spot.Bottom, go.Spot.BottomSide, true, false)
  273.  
    );
  274.  
     
  275.  
    // 构建一个连线模板
  276.  
    myDiagram.linkTemplate = $(
  277.  
    go.Link,
  278.  
    {
  279.  
    routing: go.Link.AvoidsNodes, // 设置默认规则,可被后续绑定的new go.Binding覆盖
  280.  
    curve: go.Link.JumpOver, // 当两条连线相交时,JumpOver:一条线越过了交叉的另一条线。Bezier:设置连线的弯曲度;JumpGap:在相交处会断开
  281.  
    corner: 10, // 设置连线折角的弧度
  282.  
    toShortLength: 4,
  283.  
    relinkableFrom: true, // 可以更改线的初始点
  284.  
    relinkableTo: true, // 可以更改线的末端点
  285.  
    reshapable: true, // 重塑(改变shape形状边界时使用,将影响节点大小)
  286.  
    resegmentable: true, // 连线中直线可更改
  287.  
    // mouse-overs subtly highlight links: 鼠标移入事件
  288.  
    mouseEnter: function (e, link) {
  289.  
    link.findObject('HIGHLIGHT').stroke = 'rgba(30,144,255,0.2)';
  290.  
    link.findObject('HIGHLIGHT').strokeWidth = 5;
  291.  
    },
  292.  
    mouseLeave: function (e, link) {
  293.  
    link.findObject('HIGHLIGHT').stroke = '#000';
  294.  
    link.findObject('HIGHLIGHT').strokeWidth = 1;
  295.  
    },
  296.  
    selectionAdorned: true, // 显示选中边框
  297.  
    },
  298.  
    { contextMenu: myContextMenu },
  299.  
    $(
  300.  
    go.Shape, // 线的悬浮高亮
  301.  
    {
  302.  
    isPanelMain: true,
  303.  
    strokeWidth: 1,
  304.  
    name: 'HIGHLIGHT',
  305.  
    }
  306.  
    ),
  307.  
    new go.Binding('routing', 'routing'),
  308.  
    $(
  309.  
    go.Shape, // 箭头OpenTriangle
  310.  
    { toArrow: 'standard', fill: null }
  311.  
    ),
  312.  
    $(
  313.  
    go.Panel,
  314.  
    'Auto', // 连线标签,默认不可见
  315.  
    {
  316.  
    visible: true,
  317.  
    name: 'LABEL',
  318.  
    segmentIndex: 2,
  319.  
    segmentFraction: 0.5,
  320.  
    },
  321.  
    new go.Binding('visible', 'visible').makeTwoWay(),
  322.  
    $(go.Shape, 'RoundedRectangle', { fill: '#F8F8F8', strokeWidth: 0 }),
  323.  
    $(
  324.  
    go.TextBlock,
  325.  
    '标签',
  326.  
    {
  327.  
    textAlign: 'center',
  328.  
    font: '10pt helvetica, arial, sans-serif',
  329.  
    stroke: '#333333',
  330.  
    editable: true,
  331.  
    },
  332.  
    new go.Binding('text').makeTwoWay()
  333.  
    )
  334.  
    )
  335.  
    );
  336.  
    // 为图表背景定义行为:
  337.  
    function diagramInfo(model) {
  338.  
    // diagram's model工具提示信息
  339.  
    return '模板:\n' model.nodeDataArray.length ' 节点(node), ' model.linkDataArray.length ' 连线(Links)';
  340.  
    }
  341.  
    // 当不在任何Part上时,为Diagram的背景提供工具提示
  342.  
    myDiagram.toolTip = $('ToolTip', $(go.TextBlock, { margin: 4 }, new go.Binding('text', '', diagramInfo)));
  343.  
     
  344.  
    var nodeDataArray = [
  345.  
    { key: 'Alpha', loc: '0 0', img: require('assets/logo.png'), info: '' },
  346.  
    { key: 'Beta', loc: '200 350', img: require('assets/logo.png'), info: 'shredded curtains' },
  347.  
    { key: 'Gamma', loc: '300 125', img: require('assets/logo.png'), info: 'shredded' },
  348.  
    ];
  349.  
    var linkDataArray = [
  350.  
    { from: 'Alpha', to: 'Beta', routing: go.Link.Normal }, // routing改变连线的路径,Orthogonal:正交,AvoidsNodes:自动避开Node
  351.  
    { from: 'Alpha', to: 'Beta', routing: go.Link.Normal },
  352.  
    { from: 'Alpha', to: 'Beta', routing: go.Link.Normal },
  353.  
    { from: 'Alpha', to: 'Gamma', routing: go.Link.Orthogonal },
  354.  
    { from: 'Beta', to: 'Gamma', routing: go.Link.AvoidsNodes },
  355.  
    ];
  356.  
    myDiagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
  357.  
    },
  358.  
    // 右键菜单点击事件
  359.  
    cxcommand(event) {
  360.  
    var val = event.currentTarget.id;
  361.  
    var diagram = this.myDiagram;
  362.  
    switch (val) {
  363.  
    case 'cut':
  364.  
    diagram.commandHandler.cutSelection();
  365.  
    break;
  366.  
    case 'copy':
  367.  
    diagram.commandHandler.copySelection();
  368.  
    break;
  369.  
    case 'paste':
  370.  
    diagram.commandHandler.pasteSelection(diagram.toolManager.contextMenuTool.mouseDownPoint);
  371.  
    break;
  372.  
    case 'delete':
  373.  
    diagram.commandHandler.deleteSelection(); // 删除选中的节点或线
  374.  
    break;
  375.  
    }
  376.  
    diagram.currentTool.stopTool();
  377.  
    },
  378.  
    },
  379.  
    };
学新通
  1.  
    .diagram-box {
  2.  
    border: solid 1px blue;
  3.  
    width: 1500px;
  4.  
    height: 650px;
  5.  
    margin-top: 100px;
  6.  
    }
  7.  
     
  8.  
    #myDiagramDiv {
  9.  
    flex: 1;
  10.  
    border: 1px solid rgb(212, 212, 212);
  11.  
    }
  12.  
    .menu {
  13.  
    display: none;
  14.  
    position: absolute;
  15.  
    opacity: 0;
  16.  
    margin: 0;
  17.  
    padding: 8px 0;
  18.  
    z-index: 999;
  19.  
    box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
  20.  
    list-style: none;
  21.  
    background-color: #ffffff;
  22.  
    border-radius: 4px;
  23.  
    }
  24.  
     
  25.  
    .menu-item {
  26.  
    display: block;
  27.  
    position: relative;
  28.  
    min-width: 60px;
  29.  
    margin: 0;
  30.  
    padding: 6px 16px;
  31.  
    font: bold 12px sans-serif;
  32.  
    color: rgba(0, 0, 0, 0.87);
  33.  
    cursor: pointer;
  34.  
    }
  35.  
     
  36.  
    .menu-item::before {
  37.  
    position: absolute;
  38.  
    top: 0;
  39.  
    left: 0;
  40.  
    opacity: 0;
  41.  
    pointer-events: none;
  42.  
    content: '';
  43.  
    width: 100%;
  44.  
    height: 100%;
  45.  
    background-color: #000000;
  46.  
    }
  47.  
     
  48.  
    .menu-item:hover::before {
  49.  
    opacity: 0.04;
  50.  
    }
  51.  
     
  52.  
    .menu .menu {
  53.  
    top: -8px;
  54.  
    left: 100%;
  55.  
    }
  56.  
     
  57.  
    .show-menu,
  58.  
    .menu-item:hover > .menu {
  59.  
    display: block;
  60.  
    opacity: 1;
  61.  
    }
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfafke
系列文章
更多 icon
同类精品
更多 icon
继续加载