Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在画布上寻找定制(加入div并维护它的关系)

在画布上寻找定制(加入div并维护它的关系)
EN

Stack Overflow用户
提问于 2019-02-19 09:30:43
回答 4查看 4.6K关注 0票数 2

我正在寻找一个javascript库或自定义解决方案,在那里我可以自由地拖放组件并维护它们之间的关系(比如哪个节点与什么相连&在我想要的任何地方自由移动节点)

通过维护这种关系,我的意思是不同的组件应该保持它们的互连流(如流程图)。在绘制完它们之后,我需要获得它们之间关系的JSON数据。

下面是我所说的一些例子

在上面的图片中,您可以看到,我有不同的节点,它们是相互关联的。如何通过库或自定义解决方案实现这些功能?

上面的图像来自反应-反应图 react库。我已经尝试过了,但是它使用SVG,并且缺少我想要的大量定制。

我也尝试过rete.js,但无法根据我的需要定制它(定制形状等)。

我也在考虑从头开始构建一个解决方案,我面临的唯一问题是如何在画布上加入两个或多个div来维护它的关系?

备注我为什么要这么做?

  1. 我这样做的目的是要创建一个可视化编辑器,由非技术人员设计流程,然后导出JSON,将其相应地存储在我的数据库中。
  2. 当我再次加载这个流的画布时,我应该能够根据我将拥有的JSON数据再次呈现与连接节点一起的互连流。

如果你遇到这样的情况,你能给我一些建议吗?你们的任何帮助都是非常感谢的。

EN

回答 4

Stack Overflow用户

发布于 2019-02-20 09:39:30

我很想知道更多关于你心目中的布局的信息。

这是一个演示,你可以点击灰色点。当点击2个点时,在svg画布上绘制两个点之间的连接。

在HTML中,所有元素都在一个#wrap元素中。在div下面有一个svg元素,大小与#wrap相同。divs定位为absolute,并以百分比表示顶部和左侧属性。svg画布有一个viewBox="0 0 100 100"preserveAspectRatio="none",以使绘图适应#wrap的大小。连接器是使用fill:nonevector-effect: non-scaling-stroke;在svg上绘制的路径,用于在拉伸或压缩的画布上进行一致的笔画。

最后,您可以为数据保存点数组。

我希望这能给你一个关于你需要做什么的想法。

代码语言:javascript
运行
AI代码解释
复制
const SVG_NS = 'http://www.w3.org/2000/svg';
let mainBox = wrap.getBoundingClientRect();

let dots = Array.from(document.querySelectorAll(".dot"))

let points = [];
let count = 0;

dots.forEach(d=>{
  d.addEventListener("click",(e)=>{
    
    let bcr = d.getBoundingClientRect();
    mainBox = wrap.getBoundingClientRect()
    // calculate the x and y coordinates for the connectors as a number from 0 to 100 
    let x = map(bcr.left - mainBox.left + bcr.width/2, mainBox.left, mainBox.left + mainBox.width, 0, 100);
    let y = map(bcr.top - mainBox.top + bcr.height/2, mainBox.top, mainBox.top + mainBox.height, 0, 100);
    
    points.push({x,y})
    if(count % 2 == 1){
      // connects the last 2 dots in the array
      drawConnector(points[points.length-1],points[points.length-2])
    }    
    count++;
  })
})

function map(n, a, b, _a, _b) {
  let d = b - a;
  let _d = _b - _a;
  let u = _d / d;
  return _a + n * u;
}


function drawConnector(a,b){
  let path = document.createElementNS(SVG_NS, 'path');
  let d = `M${a.x},${a.y} C50,${a.y} 50 ${b.y} ${b.x} ${b.y}`;
  path.setAttributeNS(null,"d",d);
  svg.appendChild(path)
}
代码语言:javascript
运行
AI代码解释
复制
* {
  box-sizing: border-box;
}
.box {
  width: 20%;
  height: 100px;
  border: 1px solid #bbb;
  border-radius: 10px;
  position: absolute;
  background: #efefef;
}

#wrap {
  position: absolute;
  margin:auto;
  top:0;bottom:0;left:0;right:0;
  width: 60%;
  height: 350px;
  border: 1px solid;
  min-width: 350px;
}

svg {
  position: absolute;
  width: 100%;
  height: 100%;
  background: rgba(0, 100, 250, 0.25);
}

.dot {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid #999;
  background: #d9d9d9;
  position: relative;
  left: calc(100% - 10px);
}

.dot:hover {
  border-color: tomato;
}

path {
  fill: none;
  stroke: black;
  vector-effect: non-scaling-stroke;
  stroke-width: 1px;
  stroke: #555;
}
代码语言:javascript
运行
AI代码解释
复制
<div id="wrap">
<svg id="svg" viewBox="0 0 100 100" preserveAspectRatio="none"></svg>  
  
<div class="box" id="a" style="top: 10%; left: 10%;">
  <div class="dot" style="top:20px" ></div>
  <div class="dot" style="top:40px" ></div>
</div>
<div class="box" id="b" style="top: 60%; left: 10%;">
  <div class="dot" style="top:20px" ></div>
  <div class="dot" style="top:40px" ></div>
</div>
<div class="box"  id="c" style="top: 30%; left: 65%; ">
  <div class="dot" style="top:20px; left:-10px" ></div>
  <div class="dot" style="top:40px; left:-10px" ></div>  
</div>
  
</div>

票数 5
EN

Stack Overflow用户

发布于 2019-02-23 13:40:11

Rete.js可以通过自定义Vue.js组件进行自定义。

示例

框架的可视部分由用于呈现的插件之一表示: vue或stage0。我更喜欢Vue.js,所以我开发了基于它的插件。

创建自定义套接字和节点

代码语言:javascript
运行
AI代码解释
复制
var CustomSocket = {
  template: `<div class="socket"
    :class="[type, socket.name, used()?'used':''] | kebab"
    :title="socket.name+'\\n'+socket.hint"></div>`,
  props: ['type', 'socket', 'used']
}


var CustomNode = {
  template,
  mixins: [VueRenderPlugin.mixin],
  methods:{
    used(io){
      return io.connections.length;
    }
  },
  components: {
    Socket: /*VueRenderPlugin.Socket*/CustomSocket
  }
}


class NumComponent extends Rete.Component {

    constructor(){
        super("Number");
        this.data.component = CustomNode;
    }
...

模板:

代码语言:javascript
运行
AI代码解释
复制
  <div class="node" :class="[selected(), node.name] | kebab">
  <div class="title">{{node.name}}</div>
  <div class="content">
    <div class="col" v-if="node.controls.size&gt;0 || node.inputs.size&gt;0">
      <div class="input" v-for="input in inputs()" :key="input.key" style="text-align: left">
        <Socket v-socket:input="input" type="input" :socket="input.socket" :used="() => input.connections.length"></Socket>
        <div class="input-title" v-show="!input.showControl()">{{input.name}}</div>
        <div class="input-control" v-show="input.showControl()" v-control="input.control"></div>
     </div>
     <div class="control" v-for="control in controls()" v-control="control"></div>
    </div>
    <div class="col">
      <div class="output" v-for="output in outputs()" :key="output.key">
        <div class="output-title">{{output.name}}</div>
        <Socket v-socket:output="output" type="output" :socket="output.socket" :used="() => output.connections.length"></Socket>
      </div>
    </div>
  </div> 
</div>

因此,您可以不受限制地自定义节点、连接和背景。

票数 4
EN

Stack Overflow用户

发布于 2019-02-21 02:39:22

您可以使用GOJS

对于商业项目来说,这是一个很好的解决方案。它是灵活的设置,并使它很容易做惊人的事情。

官方网站上的示例。

代码语言:javascript
运行
AI代码解释
复制
function init() {
  if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
  var $ = go.GraphObject.make; // for conciseness in defining templates

  myDiagram =
    $(go.Diagram, "myDiagramDiv", {
      validCycle: go.Diagram.CycleNotDirected, // don't allow loops
      // For this sample, automatically show the state of the diagram's model on the page
      "undoManager.isEnabled": true
    });

  // This template is a Panel that is used to represent each item in a Panel.itemArray.
  // The Panel is data bound to the item object.
  var fieldTemplate =
    $(go.Panel, "TableRow", // this Panel is a row in the containing Table
      new go.Binding("portId", "name"), // this Panel is a "port"
      {
        background: "transparent", // so this port's background can be picked by the mouse
        fromSpot: go.Spot.Right, // links only go from the right side to the left side
        toSpot: go.Spot.Left,
        // allow drawing links from or to this port:
        fromLinkable: true,
        toLinkable: true
      },
      $(go.Shape, {
          width: 12,
          height: 12,
          column: 0,
          strokeWidth: 2,
          margin: 4,
          // but disallow drawing links from or to this shape:
          fromLinkable: false,
          toLinkable: false
        },
        new go.Binding("figure", "figure"),
        new go.Binding("fill", "color")),
      $(go.TextBlock, {
          margin: new go.Margin(0, 5),
          column: 1,
          font: "bold 13px sans-serif",
          alignment: go.Spot.Left,
          // and disallow drawing links from or to this text:
          fromLinkable: false,
          toLinkable: false
        },
        new go.Binding("text", "name")),
      $(go.TextBlock, {
          margin: new go.Margin(0, 5),
          column: 2,
          font: "13px sans-serif",
          alignment: go.Spot.Left
        },
        new go.Binding("text", "info"))
    );

  // This template represents a whole "record".
  myDiagram.nodeTemplate =
    $(go.Node, "Auto", {
        copyable: false,
        deletable: false
      },
      new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
      // this rectangular shape surrounds the content of the node
      $(go.Shape, {
        fill: "#EEEEEE"
      }),
      // the content consists of a header and a list of items
      $(go.Panel, "Vertical",
        // this is the header for the whole node
        $(go.Panel, "Auto", {
            stretch: go.GraphObject.Horizontal
          }, // as wide as the whole node
          $(go.Shape, {
            fill: "#1570A6",
            stroke: null
          }),
          $(go.TextBlock, {
              alignment: go.Spot.Center,
              margin: 3,
              stroke: "white",
              textAlign: "center",
              font: "bold 12pt sans-serif"
            },
            new go.Binding("text", "key"))),
        // this Panel holds a Panel for each item object in the itemArray;
        // each item Panel is defined by the itemTemplate to be a TableRow in this Table
        $(go.Panel, "Table", {
            padding: 2,
            minSize: new go.Size(100, 10),
            defaultStretch: go.GraphObject.Horizontal,
            itemTemplate: fieldTemplate
          },
          new go.Binding("itemArray", "fields")
        ) // end Table Panel of items
      ) // end Vertical Panel
    ); // end Node

  myDiagram.linkTemplate =
    $(go.Link, {
        relinkableFrom: true,
        relinkableTo: true, // let user reconnect links
        toShortLength: 4,
        fromShortLength: 2
      },
      $(go.Shape, {
        strokeWidth: 1.5
      }),
      $(go.Shape, {
        toArrow: "Standard",
        stroke: null
      })
    );

  myDiagram.model =
    $(go.GraphLinksModel, {
      copiesArrays: true,
      copiesArrayObjects: true,
      linkFromPortIdProperty: "fromPort",
      linkToPortIdProperty: "toPort",
      nodeDataArray: [{
          key: "Record1",
          fields: [{
              name: "field1",
              info: "",
              color: "#F7B84B",
              figure: "Ellipse"
            },
            {
              name: "field2",
              info: "the second one",
              color: "#F25022",
              figure: "Ellipse"
            },
            {
              name: "fieldThree",
              info: "3rd",
              color: "#00BCF2"
            }
          ],
          loc: "0 0"
        },
        {
          key: "Record2",
          fields: [{
              name: "fieldA",
              info: "",
              color: "#FFB900",
              figure: "Diamond"
            },
            {
              name: "fieldB",
              info: "",
              color: "#F25022",
              figure: "Rectangle"
            },
            {
              name: "fieldC",
              info: "",
              color: "#7FBA00",
              figure: "Diamond"
            },
            {
              name: "fieldD",
              info: "fourth",
              color: "#00BCF2",
              figure: "Rectangle"
            }
          ],
          loc: "280 0"
        }
      ],
      linkDataArray: [{
          from: "Record1",
          fromPort: "field1",
          to: "Record2",
          toPort: "fieldA"
        },
        {
          from: "Record1",
          fromPort: "field2",
          to: "Record2",
          toPort: "fieldD"
        },
        {
          from: "Record1",
          fromPort: "fieldThree",
          to: "Record2",
          toPort: "fieldB"
        }
      ]
    });
}

init();
代码语言:javascript
运行
AI代码解释
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/2.0.3/go.js"></script>
<div id="sample">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:300px"></div>
</div>

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54771893

复制
相关文章
SAP维护定制账户信息
在SAP系统中每做一步客制的动作,都需要产生一个Request No来供Basis传输到正式系统。例如以下对话框:
SAP梦心
2022/05/10
2610
SAP维护定制账户信息
flash和div层次关系
<param name=”WMODE” value=”transparent”> <param name=”wmode” value=”Opaque”> <param name=”wmode” value=”Window”> 介绍 window 模式 默认情况下的显示模式,在这种模式下flash player有自己的窗口句柄,这就意味着flash影片是存在于Windows中的一个显示实例,并且是在浏览器核心显示窗口之上的,所以flash只 是貌似显示在浏览器中,但这也是flash最快最有效率的渲染模式。由于
苦咖啡
2018/05/07
7980
在鼠标右键上加入使用notepad++编辑
个人博客:https://suveng.github.io/blog/​​​​​​​ 在鼠标右键上加入使用notepad++编辑 阅读原文
suveng
2019/09/18
1.1K0
在Ubuntu上启动并运行Hadoop
Hadoop是一个用Java编写的框架,它允许在大型商品硬件集群上以分布式方式处理大型数据集。
大数据弄潮儿
2018/05/29
4.6K0
在Ubuntu上启动并运行Hadoop
在mac上安装并使用docker
安装完毕,会在你的应用程序文件夹中生成一个boot2docker的app,运行他就会初始化docker了!
老高的技术博客
2022/12/28
2K0
在mac上安装并使用docker
在minukube上安装istio并测试使用
只有一台机器,又想玩一下 istio 怎么办呢?本文将介绍如何使用 minikube 来安装 istio。
黑光技术
2020/05/14
3.1K0
在minukube上安装istio并测试使用
Fkill –在Linux上搜索并终止进程
Fkill是Fabulous Kill的缩写,它是一个跨平台的命令行实用程序,可一次交互式地搜索和杀死多个进程。通常,我使用“ top”命令或“ ps -ef | grep <进程名称>”或“ pidof <进程名称>”来查找进程ID,并使用命令“ kill -9 <PID>”将其kill掉。后来我发现,Fkill程序可以找到正在运行的进程,并可根据需要杀死一个或多个进程。它使用Nodejs编写,并且支持Linux、Mac OS和Microsoft Windows。
用户6543014
2020/02/21
2.4K0
在服务器上安装维护你的MongoDB数据库
MongoDB是一个免费的开源NoSQL文档数据库,在Web应用程序中经常使用。在本教程中,您将安装MongoDB,学习如何管理其服务并启用远程访问。
水门
2018/07/24
4K0
News | Google地图加入可高度定制化的进阶图标
Google地图平台添加可让开发者更改样式的进阶图标,甚至能以CSS动态配置进阶图标,提供动态图标体验
阿泽
2023/03/15
1.6K0
News | Google地图加入可高度定制化的进阶图标
JavaScript 编程精解 中文第三版 十七、在画布上绘图
浏览器为我们提供了多种绘图方式。最简单的方式是用样式来规定普通 DOM 对象的位置和颜色。就像在上一章中那个游戏展示的,我们可以使用这种方式实现很多功能。我们可以为节点添加半透明的背景图片,来获得我们希望的节点外观。我们也可以使用transform样式来旋转或倾斜节点。
ApacheCN_飞龙
2022/12/01
3.8K0
JavaScript 编程精解 中文第三版 十七、在画布上绘图
[JavaScript] JS 获取所有相同class的div,并遍历
Again,这个问题对于使用mvvm框架,例如vue,weex和angular 是任何难度的因为他们的dom都是直接用js生成控制的,在生成之初就直接处理好久好了。
用户2353021
2020/05/11
14.2K0
在Windows上安装Docker并部署Node项目
为啥要在Windows上装Docker呢?在Windows上又不能发挥Docker的优势!!
码客说
2021/03/23
4.1K0
寻找并删除Git记录中的大文件
有时候gitignore没做好,一不小心就又进来一个二进制文件 在重复了N次Google之后,还是记一下吧 首先通过rev-list来找到仓库记录中的大文件: 1 git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')" 然后通过filter-branch来重写这些大文件涉及到的所有提交(重写历史记录): 1 g
happy123.me
2018/06/04
3.5K0
在 Linux 上创建并调试转储文件
崩溃转储、内存转储、核心转储、系统转储……这些全都会产生同样的产物:一个包含了当应用崩溃时,在那个特定时刻应用的内存状态的文件。
用户8639654
2021/09/15
3.5K0
在Ubuntu 16.04上安装Seafile并配置Nginx
Seafile是一个跨平台的文件托管工具,包含了适用于Linux和Windows的服务器应用程序,以及适用于Android,iOS,Linux,OS X和Windows的GUI客户端。它支持文件版本控制和快照,双重身份验证,WebDAV(Web-based Distributed Authoring and Versioning),并且可以配合Nginx和Apache使用以启用HTTPS。
Techeek
2018/09/06
4.1K0
精读《如何抽象可视化搭建》
如果不抽象,当搭建项目做到后期可能会出现 API 杂乱,难以维护的问题;做到一半甚至会怀疑为什么需要一个搭建框架,怀疑把框架去掉会不会效率更高;在后期发现不能自然的水平拓展到仪表盘、大屏、表单搭建场景等。
黄子毅
2023/02/14
8030
精读《如何抽象可视化搭建》
Seurat Weekly NO.13 || 依赖关系与维护
遇到报错第一步肯定是先去浏览器查询啦。方法是:复制Error:后面的信息,黏贴到浏览器(必应或者Google),按搜索按钮就可以了。相信我,你并不孤独。果然有很多人遇到这个问题了,而且已经给出了解决方案,并在Seurat问答池中形成讨论:
生信菜鸟团
2021/04/29
1.3K0
Seurat Weekly NO.13 || 依赖关系与维护
寻找合适的研发效能度量指标(上)
最近几年 “软件研发效能” 成了业界的热词 ,频繁出现在各个行业大会,被各大厂、传统行业数字化部门、追求高效能的团队不断的提及并迭代,比如阿里的效能改进211愿景,腾讯的智研平台,百度工程能力白皮书。
ThoughtWorks
2021/10/09
8920
在 SwiftUI 下定制手势
不同于众多的内置控件,SwiftUI 没有采用对 UIGestureRecognizer(或 NSGestureRecognizer)进行包装的形式,而是重构了自己的手势体系。SwiftUI 手势在某种程度上降低了使用门槛,但由于缺乏提供底层数据的 API,严重制约了开发者的深度定制能力。在 SwiftUI 下,我们无法拥有类似构建全新 UIGestureRecongnizer 的能力。所谓的自定义手势,其实只是对系统预置手势的重构而已。本文将通过几个示例,演示如何使用 SwiftUI 提供的原生手段定制所需手势。
东坡肘子
2022/07/28
2.8K0
在 SwiftUI 下定制手势
div在div中垂直居中水平居中(css如何让div水平居中)
最近写网页经常需要将div在屏幕中居中显示,遂记录下几个常用的方法,都比较简单。 水平居中直接加上<center>标签即可,或者设置margin:auto;当然也可以用下面的方法
全栈程序员站长
2022/08/01
15.3K0
div在div中垂直居中水平居中(css如何让div水平居中)

相似问题

在画布上打印div

10

在div上覆盖画布

10

在画布上绘画并自动删除它(HTML5)

21

在画布上绘图,添加贴纸,定制位图- Android

13

联合所有并维护活动记录关系?

18
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档