nodelayout
Advanced tools
Comparing version 1.5.0 to 1.5.1
{ | ||
"name": "nodelayout", | ||
"version": "1.5.0", | ||
"version": "1.5.1", | ||
"description": "For node Layout.", | ||
@@ -31,3 +31,7 @@ "main": "lib/index.js", | ||
"webpack-dev-server": "^4.3.1" | ||
}, | ||
"dependencies": { | ||
"@babel/core": "^7.16.5", | ||
"babel-loader": "^8.2.3" | ||
} | ||
} |
760
src/index.js
@@ -7,162 +7,152 @@ import * as d3 from "d3"; | ||
let objectWrap, gWrap, pathWrap; | ||
// control the animation | ||
let isInit = true; | ||
// circle radius | ||
const mainCirceRadius = 25; | ||
const smallCirceRadius = 5; | ||
const svgWidth = 1000; | ||
const svgHeight = 800; | ||
// the x,y change when zoom | ||
let zoomX = 0; | ||
let zoomY = 0; | ||
let zoomK = 0; | ||
// onNodeClick | ||
let onNodeClick; | ||
// onPathClick | ||
let onPathClick; | ||
// line type | ||
let connectType = "line"; | ||
// node type | ||
let nodeType = "circle"; | ||
// offset size | ||
let leftSize = 0; | ||
let topSize = 0; | ||
let nodeData = []; | ||
let connectData = []; | ||
// main circle drag | ||
const drag = d3 | ||
.drag() | ||
.on("start", dragstart) | ||
.on("drag", draging) | ||
.on("end", dragend); | ||
// on click | ||
function handleClick (event, d) { | ||
if (onNodeClick) onNodeClick(d); | ||
d3.selectAll(".unit-dis").attr("class", "unit-dis"); | ||
d3.selectAll('.connect-fixed-line').attr('data-selected', '') | ||
d3.select(this).attr("class", "unit-dis selected"); | ||
} | ||
// on path click | ||
function handlePathClick (event, d) { | ||
d3.selectAll(".unit-dis").attr("class", "unit-dis"); | ||
d3.selectAll('.connect-fixed-line').attr('data-selected', '') | ||
d3.select(this).attr("data-selected", true); | ||
if (onPathClick) onPathClick(d); | ||
} | ||
// drag start | ||
function dragstart (event, d) { | ||
// d3.select(this).classed("fixed", false); | ||
d.dx = event.sourceEvent.x; | ||
d.dy = event.sourceEvent.y; | ||
} | ||
// draging | ||
function draging (event, d) { | ||
const $this = this; | ||
d.xp = d.x - (d.dx - event.sourceEvent.x); | ||
d.yp = d.y - (d.dy - event.sourceEvent.y); | ||
connectData.forEach(item => { | ||
const index = item.source === d.id ? item.startIndex : item.endIndex; | ||
const xValue = Math.cos(Math.PI / 180 * index * 90) * mainCirceRadius; | ||
const yValue = Math.sin(Math.PI / 180 * index * 90) * mainCirceRadius; | ||
if (item.source === d.id) { | ||
item.x1 = d.xp + xValue; | ||
item.y1 = d.yp + yValue; | ||
} else if (item.target === d.id) { | ||
item.x2 = d.xp + xValue; | ||
item.y2 = d.yp + yValue; | ||
class NodeLayout { | ||
constructor (params = {}) { | ||
this.objectWrap = null; | ||
this.svgWrap = null; | ||
this.svgWrapg = null; | ||
this.gWrap = null; | ||
this.pathWrap = null; | ||
// control the animation | ||
this.isInit = true; | ||
// circle radius | ||
this.mainCirceRadius = 25; | ||
this.smallCirceRadius = 5; | ||
this.svgWidth = 1000; | ||
this.svgHeight = 800; | ||
// the x,y change when zoom | ||
this.zoomX = 0; | ||
this.zoomY = 0; | ||
this.zoomK = 0; | ||
// onNodeClick | ||
this.onNodeClick = null; | ||
// onPathClick | ||
this.onPathClick = null; | ||
// line type | ||
this.connectType = "line"; | ||
// node type | ||
this.nodeType = "circle"; | ||
// offset size | ||
this.leftSize = 0; | ||
this.topSize = 0; | ||
this.nodePosition = {} | ||
this.nodeData = []; | ||
this.connectData = []; | ||
const $this = this; | ||
this.zoom = d3.zoom() | ||
.scaleExtent([.1, 100]) | ||
.on("zoom", (d) => this.svgZoomed(d)); | ||
// main circle drag | ||
this.drag = d3 | ||
.drag() | ||
.on("start", this.dragstart) | ||
.on("drag", function (event, d) { $this.draging(event, d, $this, this) }) | ||
.on("end", this.dragend); | ||
this.smallCircleDrag = d3 | ||
.drag() | ||
.on("start", function (event, d) { $this.smallCircleDragstart(event, d, $this) }) | ||
.on("drag", function (event, d) { $this.smallCircleDraging(event, d, $this) }) | ||
.on("end", function (event, d) { $this.smallCircleDragend(event, d, $this, this) }); | ||
} | ||
// on click | ||
handleClick (event, d) { | ||
if (this.onNodeClick) this.onNodeClick(d); | ||
d3.selectAll(".unit-dis").attr("class", "unit-dis"); | ||
d3.selectAll('.connect-fixed-line').attr('data-selected', '') | ||
d3.select(this).attr("class", "unit-dis selected"); | ||
} | ||
// on path click | ||
handlePathClick (event, d) { | ||
d3.selectAll(".unit-dis").attr("class", "unit-dis"); | ||
d3.selectAll('.connect-fixed-line').attr('data-selected', '') | ||
d3.select(this).attr("data-selected", true); | ||
if (this.onPathClick) this.onPathClick(d); | ||
} | ||
// drag start | ||
dragstart (event, d) { | ||
d.dx = event.sourceEvent.x; | ||
d.dy = event.sourceEvent.y; | ||
} | ||
// draging | ||
draging (event, d, $this, $that) { | ||
d.xp = d.x - (d.dx - event.sourceEvent.x); | ||
d.yp = d.y - (d.dy - event.sourceEvent.y); | ||
this.connectData.forEach(item => { | ||
const index = item.source === d.id ? item.startIndex : item.endIndex; | ||
const xValue = Math.cos(Math.PI / 180 * index * 90) * this.mainCirceRadius; | ||
const yValue = Math.sin(Math.PI / 180 * index * 90) * this.mainCirceRadius; | ||
if (item.source === d.id) { | ||
item.x1 = d.xp + xValue; | ||
item.y1 = d.yp + yValue; | ||
} else if (item.target === d.id) { | ||
item.x2 = d.xp + xValue; | ||
item.y2 = d.yp + yValue; | ||
} | ||
}); | ||
this.renderLines({ data: this.connectData }); | ||
d3.select($that).attr("transform", () => `translate(${d.xp}, ${d.yp})`); | ||
} | ||
// drag end | ||
dragend (event, d) { | ||
d.x = d.xp || event.sourceEvent.x; | ||
d.y = d.yp || event.sourceEvent.y; | ||
} | ||
renderNodes (params = {}) { | ||
d3.selectAll(".unit-dis").remove(); | ||
this.objectWrap = this.gWrap.selectAll("g") | ||
.data(params.data) | ||
.enter() | ||
.append("g") | ||
.attr("id", d => d.id) | ||
.attr("class", "unit-dis") | ||
.call(this.drag) | ||
.on("click", this.handleClick) | ||
.attr('transform', (d) => this.isInit ? `translate(0, 0)` : `translate(${d.x}, ${d.y})` ); | ||
if (this.isInit) { | ||
this.objectWrap.transition() | ||
.duration(750) | ||
.delay(function(d, i) { return i * 10; }) | ||
.attr('transform', (d) => `translate(${d.x}, ${d.y})`); | ||
} | ||
}); | ||
renderLines({ data: connectData }); | ||
d3.select($this).attr("transform", () => `translate(${d.xp}, ${d.yp})`); | ||
} | ||
// drag end | ||
function dragend (event, d) { | ||
d.x = d.xp || event.sourceEvent.x; | ||
d.y = d.yp || event.sourceEvent.y; | ||
} | ||
function renderNodes (params = {}) { | ||
d3.selectAll(".unit-dis").remove(); | ||
objectWrap = gWrap.selectAll("g") | ||
.data(params.data) | ||
.enter() | ||
.append("g") | ||
.attr("id", d => d.id) | ||
.attr("class", "unit-dis") | ||
.call(drag) | ||
.on("click", handleClick) | ||
.attr('transform', (d) => isInit ? `translate(0, 0)` : `translate(${d.x}, ${d.y})` ); | ||
if (isInit) { | ||
objectWrap.transition() | ||
.duration(750) | ||
.delay(function(d, i) { return i * 10; }) | ||
.attr('transform', (d) => `translate(${d.x}, ${d.y})`); | ||
this.renderMain(); | ||
} | ||
renderMain(); | ||
} | ||
// draw connect lines | ||
function renderLines (params = {}) { | ||
pathWrap.selectAll(".connect-fixed-line").remove(); | ||
const allPath = pathWrap.selectAll(".connect-fixed-line") | ||
.data(params.data) | ||
.enter() | ||
.append("path") | ||
.attr("class", (d) => `start-${d.source} end-${d.target} connect-fixed-line`) | ||
.attr("marker-end","url(#arrowEnd)") | ||
.attr("d", (d) => isInit ? `M0,0 0,0` : `M${d.x1},${d.y1} ${d.x2},${d.y2}`) | ||
.attr("data-id", d => d.id) | ||
.on("click", handlePathClick); | ||
if (isInit) { | ||
allPath.transition() | ||
.duration(750) | ||
.delay(function(d, i) { return i * 10; }) | ||
.attr("d", (d) => `M${d.x1},${d.y1} ${d.x2},${d.y2}`); | ||
// draw connect lines | ||
renderLines (params = {}) { | ||
this.pathWrap.selectAll(".connect-fixed-line").remove(); | ||
const allPath = this.pathWrap.selectAll(".connect-fixed-line") | ||
.data(params.data) | ||
.enter() | ||
.append("path") | ||
.attr("class", (d) => `start-${d.source} end-${d.target} connect-fixed-line`) | ||
.attr("marker-end","url(#arrowEnd)") | ||
.attr("d", (d) => this.isInit ? `M0,0 0,0` : `M${d.x1},${d.y1} ${d.x2},${d.y2}`) | ||
.attr("data-id", d => d.id) | ||
.on("click", this.handlePathClick); | ||
if (this.isInit) { | ||
allPath.transition() | ||
.duration(750) | ||
.delay(function(d, i) { return i * 10; }) | ||
.attr("d", (d) => `M${d.x1},${d.y1} ${d.x2},${d.y2}`); | ||
} | ||
this.isInit = false; | ||
} | ||
isInit = false; | ||
} | ||
function handleDeleteNode(event, d) { | ||
nodeData = nodeData.filter (item => d.id !== item.id); | ||
renderNodes({ data: nodeData }); | ||
connectData = connectData.filter (item => { | ||
return item.source !== d.id && item.target !== d.id; | ||
}); | ||
renderLines({ data: connectData }); | ||
} | ||
function renderMain () { | ||
// delete button | ||
objectWrap.append("g") | ||
.attr("class", "delete-circle") | ||
.attr("title", "delete") | ||
.attr("transform", `translate(${mainCirceRadius}, ${-mainCirceRadius - 5})`) | ||
.on("click", handleDeleteNode) | ||
.html(deletIcon); | ||
// small circle drag | ||
const smallCircleDrag = d3 | ||
.drag() | ||
.on("start", smallCircleDragstart) | ||
.on("drag", smallCircleDraging) | ||
.on("end", smallCircleDragend); | ||
// handle small circle | ||
function smallCircleDragstart (event, d) { | ||
d.dx = event.sourceEvent.layerX - Math.cos(Math.PI / 180 * d.index * 90) * smallCirceRadius; | ||
d.dy = event.sourceEvent.layerY - Math.sin(Math.PI / 180 * d.index * 90) * smallCirceRadius; | ||
handleDeleteNode(event, d) { | ||
this.nodeData = this.nodeData.filter (item => d.id !== item.id); | ||
renderNodes({ data: this.nodeData }); | ||
this.connectData = this.connectData.filter (item => { | ||
return item.source !== d.id && item.target !== d.id; | ||
}); | ||
this.renderLines({ data: this.connectData }); | ||
} | ||
function smallCircleDraging (event, d) { | ||
const k = zoomK === 0 ? 1 : zoomK; | ||
d.x1 = (d.dx - zoomX)/k; | ||
d.y1 = (d.dy - zoomY)/k; | ||
d.x2 = (event.sourceEvent.layerX - zoomX)/k; | ||
d.y2 = (event.sourceEvent.layerY - zoomY)/k; | ||
smallCircleDragstart (event, d, $this) { | ||
d.dx = event.sourceEvent.layerX - Math.cos(Math.PI / 180 * d.index * 90) * $this.smallCirceRadius; | ||
d.dy = event.sourceEvent.layerY - Math.sin(Math.PI / 180 * d.index * 90) * $this.smallCirceRadius; | ||
} | ||
smallCircleDraging (event, d, $this) { | ||
const k = $this.zoomK === 0 ? 1 : $this.zoomK; | ||
d.x1 = (d.dx - $this.zoomX)/k; | ||
d.y1 = (d.dy - $this.zoomY)/k; | ||
d.x2 = (event.sourceEvent.layerX - $this.zoomX)/k; | ||
d.y2 = (event.sourceEvent.layerY - $this.zoomY)/k; | ||
let pos = `M${d.x1},${d.y1} ${d.x2},${d.y2}`; | ||
if (connectType === "path") { | ||
if ($this.connectType === "path") { | ||
switch (d.index) { | ||
@@ -189,8 +179,8 @@ case 0: | ||
} | ||
function smallCircleDragend (event, d) { | ||
smallCircleDragend (event, d, $this, $that) { | ||
d3.select(".connect-line").attr("class", "connect-line"); | ||
const hasAcitve = document.querySelector(".small-circle.active"); | ||
if (hasAcitve) { | ||
connectData.push({ | ||
source: this.parentNode.getAttribute("id"), | ||
$this.connectData.push({ | ||
source: $that.parentNode.getAttribute("id"), | ||
target: hasAcitve.parentNode.getAttribute("id"), | ||
@@ -204,229 +194,247 @@ startIndex: d.index, | ||
}); | ||
renderLines({ data: connectData }); | ||
$this.renderLines({ data: $this.connectData }); | ||
} | ||
} | ||
// main circle | ||
if (nodeType === "rect") { | ||
objectWrap.append("rect") | ||
.attr("fill", "#fff") | ||
.attr("class", "main-circle") | ||
.attr("stroke", "#227AE6") | ||
.attr("x", -mainCirceRadius) | ||
.attr("y", -mainCirceRadius) | ||
.attr("rx", 5) | ||
.attr("ry", 5) | ||
.attr("height", mainCirceRadius * 2) | ||
.attr("width", mainCirceRadius * 2); | ||
} else { | ||
objectWrap.append("circle") | ||
.attr("fill", "#fff") | ||
.attr("class", "main-circle") | ||
.attr("stroke", "#227AE6") | ||
.attr("r", mainCirceRadius); | ||
renderMain () { | ||
// delete button | ||
this.objectWrap.append("g") | ||
.attr("class", "delete-circle") | ||
.attr("title", "delete") | ||
.attr("transform", `translate(${this.mainCirceRadius}, ${-this.mainCirceRadius - 5})`) | ||
.on("click", this.handleDeleteNode) | ||
.html(deletIcon); | ||
// main circle | ||
if (this.nodeType === "rect") { | ||
this.objectWrap.append("rect") | ||
.attr("fill", "#fff") | ||
.attr("class", "main-circle") | ||
.attr("stroke", "#227AE6") | ||
.attr("x", -this.mainCirceRadius) | ||
.attr("y", -this.mainCirceRadius) | ||
.attr("rx", 5) | ||
.attr("ry", 5) | ||
.attr("height", this.mainCirceRadius * 2) | ||
.attr("width", this.mainCirceRadius * 2); | ||
} else { | ||
this.objectWrap.append("circle") | ||
.attr("fill", "#fff") | ||
.attr("class", "main-circle") | ||
.attr("stroke", "#227AE6") | ||
.attr("r", this.mainCirceRadius); | ||
} | ||
// small circle | ||
const smallCircelData = [{ | ||
x : this.mainCirceRadius, | ||
y : 0, | ||
index: 0 | ||
},{ | ||
x : 0, | ||
y : this.mainCirceRadius, | ||
index: 1 | ||
},{ | ||
x : -this.mainCirceRadius, | ||
y : 0, | ||
index: 2 | ||
},{ | ||
x : 0, | ||
y : -this.mainCirceRadius, | ||
index: 3 | ||
}]; | ||
this.objectWrap.selectAll(".small-circle") | ||
.data(smallCircelData) | ||
.enter() | ||
.append("circle") | ||
.attr("class","small-circle") | ||
.attr("data-index", (d) => d.index) | ||
.attr("cx",d => d.x) | ||
.attr("cy",d => d.y) | ||
.attr("r", this.smallCirceRadius) | ||
.on("mouseenter",function(d){ | ||
this.setAttribute("class","small-circle active"); | ||
}) | ||
.on("mouseleave",function(d){ | ||
this.setAttribute("class","small-circle"); | ||
}) | ||
.call(this.smallCircleDrag); | ||
// icon | ||
this.objectWrap.append("g") | ||
.attr("transform", "translate(-15, -15)") | ||
.html(defaultIcon); | ||
this.objectWrap.append("text") | ||
.attr("y", 45) | ||
.attr("fill", "#111") | ||
.attr("style", "text-anchor: middle;") | ||
.text((d) => d.text); | ||
} | ||
// small circle | ||
const smallCircelData = [{ | ||
x : mainCirceRadius, | ||
y : 0, | ||
index: 0 | ||
},{ | ||
x : 0, | ||
y : mainCirceRadius, | ||
index: 1 | ||
},{ | ||
x : -mainCirceRadius, | ||
y : 0, | ||
index: 2 | ||
},{ | ||
x : 0, | ||
y : -mainCirceRadius, | ||
index: 3 | ||
}]; | ||
objectWrap.selectAll(".small-circle") | ||
.data(smallCircelData) | ||
.enter() | ||
.append("circle") | ||
.attr("class","small-circle") | ||
.attr("data-index", (d) => d.index) | ||
.attr("cx",d => d.x) | ||
.attr("cy",d => d.y) | ||
.attr("r", smallCirceRadius) | ||
.on("mouseenter",function(d){ | ||
this.setAttribute("class","small-circle active"); | ||
}) | ||
.on("mouseleave",function(d){ | ||
this.setAttribute("class","small-circle"); | ||
}) | ||
.call(smallCircleDrag); | ||
// icon | ||
objectWrap.append("g") | ||
.attr("transform", "translate(-15, -15)") | ||
.html(defaultIcon); | ||
objectWrap.append("text") | ||
.attr("y", 45) | ||
.attr("fill", "#111") | ||
.attr("style", "text-anchor: middle;") | ||
.text((d) => d.text); | ||
} | ||
function init(params = {}) { | ||
const wrap = d3.select(`#${params.id}`).attr("height", svgHeight).html(""); | ||
const queryWrap = document.querySelector(`#${params.id}`) | ||
leftSize = queryWrap.offsetLeft | ||
topSize = queryWrap.offsetTop | ||
connectType = params.connectType || "line" | ||
nodeType = params.nodeType || "circle" | ||
renderOptionList({ | ||
wrap, | ||
add, | ||
option: params.list | ||
}); | ||
const wraps = wrap.append("div"); | ||
const svg = wraps.append("svg"); | ||
// fill pattern | ||
svg.append("rect") | ||
.attr("width", "100%") | ||
.attr("height", svgHeight) | ||
.attr("fill", "url(#diagramPattern)") | ||
.on("click", (event) => { | ||
d3.selectAll(".unit-dis").attr("class", "unit-dis"); | ||
}) | ||
.call( | ||
d3.zoom() | ||
.scaleExtent([.1, 100]) | ||
.on("zoom", svgZoomed) | ||
); | ||
const svgWrap = svg.append("g"); | ||
pathWrap = svgWrap.append("g"); | ||
gWrap = svgWrap.append("g"); | ||
wrap.attr("class", "nodelayout-wrap"); | ||
svg | ||
.attr("width", "100%") | ||
.attr("height", svgHeight); | ||
// connect line | ||
gWrap.append("path") | ||
.attr("class", "connect-line") | ||
.attr("marker-end","url(#arrowEnd)"); | ||
function svgZoomed(d) { | ||
zoomX = d.transform.x; | ||
zoomY = d.transform.y; | ||
zoomK = d.transform.k; | ||
svgWrap.attr("transform", d.transform); | ||
svgZoomed(d) { | ||
this.zoomX = d.transform.x; | ||
this.zoomY = d.transform.y; | ||
this.zoomK = d.transform.k; | ||
this.svgWrapg.attr("transform", d.transform); | ||
} | ||
if (!params.nodes) params.nodes = []; | ||
if (params.onNodeClick) onNodeClick = params.onNodeClick; | ||
if (params.onPathClick) onPathClick = params.onPathClick; | ||
/* nodeData = params.nodes.map((item, index) => { | ||
return { | ||
id: item.id, | ||
text: item.title, | ||
x: svgWidth/10 + index * 200, | ||
y: svgHeight / 2 | ||
}; | ||
}); */ | ||
const nodePosition = {} | ||
nodeData = params.nodes.map((item, index) => { | ||
nodePosition[item.id] = { | ||
x: item.x || 100 * index + 200, | ||
y: item.y || svgHeight/5 | ||
init(params = {}) { | ||
const wrap = d3.select(`#${params.id}`).attr("height", this.svgHeight).html(""); | ||
const queryWrap = document.querySelector(`#${params.id}`) | ||
this.leftSize = queryWrap.offsetLeft | ||
this.topSize = queryWrap.offsetTop | ||
this.connectType = params.connectType || "line" | ||
this.nodeType = params.nodeType || "circle" | ||
renderOptionList({ | ||
wrap, | ||
add: (params = {}) => this.add(params), | ||
option: params.list | ||
}); | ||
const wraps = wrap.append("div"); | ||
this.svgWrap = wraps.append("svg").call(this.zoom); | ||
// fill pattern | ||
this.svgWrap.append("rect") | ||
.attr("width", "100%") | ||
.attr("height", this.svgHeight) | ||
.attr("fill", "url(#diagramPattern)") | ||
.on("click", (event) => { | ||
d3.selectAll(".unit-dis").attr("class", "unit-dis"); | ||
}); | ||
this.svgWrapg = this.svgWrap.append("g"); | ||
this.pathWrap = this.svgWrapg.append("g"); | ||
this.gWrap = this.svgWrapg.append("g"); | ||
wrap.attr("class", "nodelayout-wrap"); | ||
this.svgWrap | ||
.attr("width", "100%") | ||
.attr("height", this.svgHeight); | ||
// connect line | ||
this.gWrap.append("path") | ||
.attr("class", "connect-line") | ||
.attr("marker-end","url(#arrowEnd)"); | ||
if (!params.nodes) params.nodes = []; | ||
if (params.onNodeClick) this.onNodeClick = params.onNodeClick; | ||
if (params.onPathClick) this.onPathClick = params.onPathClick; | ||
/* nodeData = params.nodes.map((item, index) => { | ||
return { | ||
id: item.id, | ||
text: item.title, | ||
x: svgWidth/10 + index * 200, | ||
y: svgHeight / 2 | ||
}; | ||
}); */ | ||
this.nodeData = params.nodes.map((item, index) => { | ||
let x = item.x || 100 * index + 200 | ||
let y = item.y || this.svgHeight/5 | ||
if (index === 0) { | ||
x = 250 | ||
y = 400 | ||
} | ||
this.nodePosition[item.id] = { | ||
x, | ||
y | ||
} | ||
return { | ||
id: item.id, | ||
text: item.title, | ||
x, | ||
y | ||
}; | ||
}); | ||
this.renderNodes({ data: this.nodeData }); | ||
// node connect line | ||
if (params.lines) { | ||
this.connectData = [] | ||
params.lines.forEach((item, index) => { | ||
const startIndex = item.startIndex | ||
const endIndex = item.endIndex | ||
this.connectData.push({ | ||
id: uuid(), | ||
source: item.source, | ||
target: item.target, | ||
startIndex, | ||
endIndex, | ||
x1: this.nodePosition[item.source].x + Math.cos(Math.PI / 180 * startIndex * 90) * this.mainCirceRadius, | ||
y1: this.nodePosition[item.source].y + Math.sin(Math.PI / 180 * startIndex * 90) * this.mainCirceRadius, | ||
x2: this.nodePosition[item.target].x + Math.cos(Math.PI / 180 * endIndex * 90) * this.mainCirceRadius, | ||
y2: this.nodePosition[item.target].y + Math.sin(Math.PI / 180 * endIndex * 90) * this.mainCirceRadius | ||
}); | ||
}); | ||
this.renderLines({ data: this.connectData }); | ||
} | ||
return { | ||
id: item.id, | ||
text: item.title, | ||
x: item.x || 100 * index + 200, | ||
y: item.y || svgHeight/5 | ||
}; | ||
}); | ||
/* nodeData[0].x = 700; | ||
nodeData[0].y = svgHeight/2 + 100; */ | ||
renderNodes({ data: nodeData }); | ||
// node connect line | ||
if (params.lines) { | ||
connectData = [] | ||
params.lines.forEach((item, index) => { | ||
const startIndex = item.startIndex | ||
const endIndex = item.endIndex | ||
connectData.push({ | ||
id: uuid(), | ||
source: item.source, | ||
target: item.target, | ||
startIndex, | ||
endIndex, | ||
x1: nodePosition[item.source].x + Math.cos(Math.PI / 180 * startIndex * 90) * mainCirceRadius, | ||
y1: nodePosition[item.source].y + Math.sin(Math.PI / 180 * startIndex * 90) * mainCirceRadius, | ||
x2: nodePosition[item.target].x + Math.cos(Math.PI / 180 * endIndex * 90) * mainCirceRadius, | ||
y2: nodePosition[item.target].y + Math.sin(Math.PI / 180 * endIndex * 90) * mainCirceRadius | ||
// arrow | ||
let markerWrap = this.svgWrap.append("defs"); | ||
markerWrap.append("marker") | ||
.attr("id","arrowEnd") | ||
.attr("markerUnits","strokeWidth") | ||
.attr("markerWidth","12") | ||
.attr("markerHeight","12") | ||
.attr("viewBox","0 0 12 12") | ||
.attr("refX","10") | ||
.attr("refY","6") | ||
.attr("orient","auto") | ||
.append("path") | ||
.attr("d","M2,2 L10,6 L2,10 L6,6 L2,2") | ||
.attr("class","pathArrow"); | ||
markerWrap.append("marker") | ||
.attr("id","arrowStart") | ||
.attr("markerUnits","strokeWidth") | ||
.attr("markerWidth","12") | ||
.attr("markerHeight","12") | ||
.attr("viewBox","0 0 12 12") | ||
.attr("refX","0") | ||
.attr("refY","6") | ||
.attr("orient","auto") | ||
.append("path") | ||
.attr("d","M10,2 L2,6 L10,10 L6,6 L10,2") | ||
.attr("class","pathArrow"); | ||
/* 网格 */ | ||
const gridArr = new Array(20); | ||
const patternWrap = markerWrap | ||
.append("pattern") | ||
.attr("id", "diagramPattern") | ||
.attr("x", 0) | ||
.attr("y", 0) | ||
.attr("width", 100) | ||
.attr("height", 100) | ||
.attr("patternUnits", "userSpaceOnUse"); | ||
patternWrap | ||
.selectAll("path") | ||
.data(gridArr) | ||
.enter() | ||
.append("path") | ||
.attr("stroke", "#e0e0e0") | ||
.attr("stroke-width", "0.25") | ||
.attr("dashArray", "") | ||
.attr("d", (d, index) => { | ||
if (index === 0) { | ||
return `M0,0.5 L100,0.5 Z`; | ||
} else if (index < 10 && index > 0) { | ||
return `M0,${index * 10}.125 L100,${index * 10}.125 Z`; | ||
} else if (index === 10) { | ||
return `M0.5,0 L0.5,100 Z`; | ||
} else if (index > 10) { | ||
return `M${(index - 10) * 10}.125,0 L${(index - 10) * 10}.125,100 Z`; | ||
} | ||
}); | ||
} | ||
add (params = {}) { | ||
const x = params.x || Math.random() * 1000; | ||
const y = params.y || Math.random() * 600 + 200; | ||
const k = this.zoomK === 0 ? 1 : this.zoomK; | ||
this.nodeData.push({ | ||
id: uuid(), | ||
text: params.title || params + (this.nodeData.length + 1), | ||
x: (x - this.zoomX) / k - this.leftSize, | ||
y: (y - this.zoomY) / k - this.topSize | ||
}); | ||
renderLines({ data: connectData }); | ||
this.renderNodes({ data: this.nodeData }); | ||
} | ||
// arrow | ||
let markerWrap = svg.append("defs"); | ||
markerWrap.append("marker") | ||
.attr("id","arrowEnd") | ||
.attr("markerUnits","strokeWidth") | ||
.attr("markerWidth","12") | ||
.attr("markerHeight","12") | ||
.attr("viewBox","0 0 12 12") | ||
.attr("refX","10") | ||
.attr("refY","6") | ||
.attr("orient","auto") | ||
.append("path") | ||
.attr("d","M2,2 L10,6 L2,10 L6,6 L2,2") | ||
.attr("class","pathArrow"); | ||
markerWrap.append("marker") | ||
.attr("id","arrowStart") | ||
.attr("markerUnits","strokeWidth") | ||
.attr("markerWidth","12") | ||
.attr("markerHeight","12") | ||
.attr("viewBox","0 0 12 12") | ||
.attr("refX","0") | ||
.attr("refY","6") | ||
.attr("orient","auto") | ||
.append("path") | ||
.attr("d","M10,2 L2,6 L10,10 L6,6 L10,2") | ||
.attr("class","pathArrow"); | ||
/* 网格 */ | ||
const gridArr = new Array(20); | ||
const patternWrap = markerWrap | ||
.append("pattern") | ||
.attr("id", "diagramPattern") | ||
.attr("x", 0) | ||
.attr("y", 0) | ||
.attr("width", 100) | ||
.attr("height", 100) | ||
.attr("patternUnits", "userSpaceOnUse"); | ||
patternWrap | ||
.selectAll("path") | ||
.data(gridArr) | ||
.enter() | ||
.append("path") | ||
.attr("stroke", "#e0e0e0") | ||
.attr("stroke-width", "0.25") | ||
.attr("dashArray", "") | ||
.attr("d", (d, index) => { | ||
if (index === 0) { | ||
return `M0,0.5 L100,0.5 Z`; | ||
} else if (index < 10 && index > 0) { | ||
return `M0,${index * 10}.125 L100,${index * 10}.125 Z`; | ||
} else if (index === 10) { | ||
return `M0.5,0 L0.5,100 Z`; | ||
} else if (index > 10) { | ||
return `M${(index - 10) * 10}.125,0 L${(index - 10) * 10}.125,100 Z`; | ||
} | ||
}); | ||
zoomIn () { | ||
this.svgWrap.transition().call(this.zoom.scaleBy, 1.5) | ||
} | ||
zoomOut () { | ||
this.svgWrap.transition().call(this.zoom.scaleBy, 0.5) | ||
} | ||
reset () { | ||
this.svgWrap.transition().duration(750).call( | ||
this.zoom.transform, | ||
d3.zoomIdentity | ||
) | ||
} | ||
} | ||
function add (params = {}) { | ||
const x = params.x || Math.random() * 1000; | ||
const y = params.y || Math.random() * 600 + 200; | ||
const k = zoomK === 0 ? 1 : zoomK; | ||
nodeData.push({ | ||
id: uuid(), | ||
text: params.title || params + (nodeData.length + 1), | ||
x: (x - zoomX) / k - leftSize, | ||
y: (y - zoomY) / k - topSize | ||
}); | ||
renderNodes({ data: nodeData }); | ||
} | ||
export { init, add }; | ||
export { NodeLayout }; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
140102
591
2
+ Added@babel/core@^7.16.5
+ Addedbabel-loader@^8.2.3
+ Added@ampproject/remapping@2.3.0(transitive)
+ Added@babel/code-frame@7.26.2(transitive)
+ Added@babel/compat-data@7.26.2(transitive)
+ Added@babel/core@7.26.0(transitive)
+ Added@babel/generator@7.26.2(transitive)
+ Added@babel/helper-compilation-targets@7.25.9(transitive)
+ Added@babel/helper-module-imports@7.25.9(transitive)
+ Added@babel/helper-module-transforms@7.26.0(transitive)
+ Added@babel/helper-string-parser@7.25.9(transitive)
+ Added@babel/helper-validator-identifier@7.25.9(transitive)
+ Added@babel/helper-validator-option@7.25.9(transitive)
+ Added@babel/helpers@7.26.0(transitive)
+ Added@babel/parser@7.26.2(transitive)
+ Added@babel/template@7.25.9(transitive)
+ Added@babel/traverse@7.25.9(transitive)
+ Added@babel/types@7.26.0(transitive)
+ Added@jridgewell/gen-mapping@0.3.5(transitive)
+ Added@jridgewell/resolve-uri@3.1.2(transitive)
+ Added@jridgewell/set-array@1.2.1(transitive)
+ Added@jridgewell/source-map@0.3.6(transitive)
+ Added@jridgewell/sourcemap-codec@1.5.0(transitive)
+ Added@jridgewell/trace-mapping@0.3.25(transitive)
+ Added@types/eslint@9.6.1(transitive)
+ Added@types/eslint-scope@3.7.7(transitive)
+ Added@types/estree@1.0.6(transitive)
+ Added@types/json-schema@7.0.15(transitive)
+ Added@types/node@22.9.0(transitive)
+ Added@webassemblyjs/ast@1.14.1(transitive)
+ Added@webassemblyjs/floating-point-hex-parser@1.13.2(transitive)
+ Added@webassemblyjs/helper-api-error@1.13.2(transitive)
+ Added@webassemblyjs/helper-buffer@1.14.1(transitive)
+ Added@webassemblyjs/helper-numbers@1.13.2(transitive)
+ Added@webassemblyjs/helper-wasm-bytecode@1.13.2(transitive)
+ Added@webassemblyjs/helper-wasm-section@1.14.1(transitive)
+ Added@webassemblyjs/ieee754@1.13.2(transitive)
+ Added@webassemblyjs/leb128@1.13.2(transitive)
+ Added@webassemblyjs/utf8@1.13.2(transitive)
+ Added@webassemblyjs/wasm-edit@1.14.1(transitive)
+ Added@webassemblyjs/wasm-gen@1.14.1(transitive)
+ Added@webassemblyjs/wasm-opt@1.14.1(transitive)
+ Added@webassemblyjs/wasm-parser@1.14.1(transitive)
+ Added@webassemblyjs/wast-printer@1.14.1(transitive)
+ Added@xtuc/ieee754@1.2.0(transitive)
+ Added@xtuc/long@4.2.2(transitive)
+ Addedacorn@8.14.0(transitive)
+ Addedajv@6.12.6(transitive)
+ Addedajv-keywords@3.5.2(transitive)
+ Addedbabel-loader@8.4.1(transitive)
+ Addedbig.js@5.2.2(transitive)
+ Addedbrowserslist@4.24.2(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedcaniuse-lite@1.0.30001680(transitive)
+ Addedchrome-trace-event@1.0.4(transitive)
+ Addedcommander@2.20.3(transitive)
+ Addedcommondir@1.0.1(transitive)
+ Addedconvert-source-map@2.0.0(transitive)
+ Addeddebug@4.3.7(transitive)
+ Addedelectron-to-chromium@1.5.57(transitive)
+ Addedemojis-list@3.0.0(transitive)
+ Addedenhanced-resolve@5.17.1(transitive)
+ Addedes-module-lexer@1.5.4(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addedeslint-scope@5.1.1(transitive)
+ Addedesrecurse@4.3.0(transitive)
+ Addedestraverse@4.3.05.3.0(transitive)
+ Addedevents@3.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedfind-cache-dir@3.3.2(transitive)
+ Addedfind-up@4.1.0(transitive)
+ Addedgensync@1.0.0-beta.2(transitive)
+ Addedglob-to-regexp@0.4.1(transitive)
+ Addedglobals@11.12.0(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhas-flag@4.0.0(transitive)
+ Addedjest-worker@27.5.1(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjsesc@3.0.2(transitive)
+ Addedjson-parse-even-better-errors@2.3.1(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson5@2.2.3(transitive)
+ Addedloader-runner@4.3.0(transitive)
+ Addedloader-utils@2.0.4(transitive)
+ Addedlocate-path@5.0.0(transitive)
+ Addedlru-cache@5.1.1(transitive)
+ Addedmake-dir@3.1.0(transitive)
+ Addedmerge-stream@2.0.0(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addedms@2.1.3(transitive)
+ Addedneo-async@2.6.2(transitive)
+ Addednode-releases@2.0.18(transitive)
+ Addedp-limit@2.3.0(transitive)
+ Addedp-locate@4.1.0(transitive)
+ Addedp-try@2.2.0(transitive)
+ Addedpath-exists@4.0.0(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedpkg-dir@4.2.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedrandombytes@2.1.0(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedschema-utils@2.7.13.3.0(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedserialize-javascript@6.0.2(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsource-map-support@0.5.21(transitive)
+ Addedsupports-color@8.1.1(transitive)
+ Addedtapable@2.2.1(transitive)
+ Addedterser@5.36.0(transitive)
+ Addedterser-webpack-plugin@5.3.10(transitive)
+ Addedundici-types@6.19.8(transitive)
+ Addedupdate-browserslist-db@1.1.1(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addedwatchpack@2.4.2(transitive)
+ Addedwebpack@5.96.1(transitive)
+ Addedwebpack-sources@3.2.3(transitive)
+ Addedyallist@3.1.1(transitive)