This chapter responds to the feedback of partners, in addition to the algorithm automatically draw the connection line (still need to optimize the perfect), the realization of a straight line can be drawn manually, folding line connection line function.
Please give me a free Star!
If you find any bugs, please feel free to raise an Issue!
github source code
gitee source code
sample address (computing)
Mode switching
pre-production
Connection line Mode type
// src/Render/
export enum LinkType {
'auto' = 'auto', // straight
'straight' = 'straight', // straight line
'manual' = 'manual' // manually folded line
}
Connection line Mode status
// src/Render/draws/
// Link lines (temporary)
export interface LinkDrawState {
// Omitted
linkType: // Link type
linkManualing: boolean // Whether the inflection point is being manipulated.
}
Connection cable Mode switching method
// src/Render/draws/
/**
* Modify the current link type
* @param linkType
*/
changeLinkType(linkType: ) {
= linkType
? .on?.linkTypeChange? ()
}
Connection cable Mode switching button
<! -- src/ -->!
<button @click="onLinkTypeChange()"
:disabled="currentLinkType === ">Link line: auto</button>
<button @click="onLinkTypeChange()"
:disabled="currentLinkType === ">Link line: straight</button>
<button @click="onLinkTypeChange()"
:disabled="currentLinkType === ">Link line: manual</button>
Connection line Mode switch event
// src/
const currentLinkType = ref()
function onLinkTypeChange(linkType: ) {
(render?.draws[] as ).changeLinkType(linkType)
}
Current pair Record current cable mode
// src/Render/draws/
export class LinkDraw extends implements {
// summarize
override draw() {
// summarize
// connection point
for (const point of points) {
// summarize
// unselect
if (group && !('selected')) {
// summarize
const anchor = (`#${}`)
if (anchor) {
// summarize
('mouseup', () => {
if () {
// summarize
// 不同connection point
if (() !== ()) {
// summarize
if (toGroup) {
// summarize
if (fromPoint) {
// summarize
if (toPoint) {
if (()) {
= [
...,
{
// summarize
linkType: // recording line typology
}
]
}
// summarize
}
}
}
}
// summarize
}
})
// summarize
}
}
}
}
}
straightness
Drawing a line is relatively simple. You can draw a line from the starting point to the end point by determining the pattern of the lines recorded in the pair:
// src/Render/draws/
export class LinkDraw extends implements {
// summarize
override draw() {
// summarize
// connection line
for (const pair of pairs) {
if ( === ) {
// summarize,Manual Folding Line
} else if ( === ) {
// straightness
if (fromGroup && toGroup && fromPoint && toPoint) {
const fromAnchor = (`#${}`)
const toAnchor = (`#${}`)
// Anchor information
const fromAnchorPos = (fromAnchor)
const toAnchorPos = (toAnchor)
const linkLine = new ({
name: 'link-line',
// 用于删除connection line
groupId: (),
pointId: ,
pairId: ,
linkType: ,
points: _.flatten([
[
(),
()
],
[(), ()]
]),
stroke: 'red',
strokeWidth: 2
})
(linkLine)
}
} else {
// summarize,原算法画connection line逻辑
}
}
}
}
broken line (continuous figure made up of straight line segments)
To draw a polyline, there are 3 kinds of "points" defined: 1) Connection point, which is the original one. 2) Point of inflection (to be inflected), which is blue and has never been dragged. 2, point of inflection (to be inflection), blue, never dragged, once dragged, will be added to the inflection point record. 3, inflection point (already inflection), green, has been dragged, can still be dragged, but will not add new inflection point records.
Note the comments in the code below, key:
- The fromGroup records manualPoints.
- Linking lines are drawn from Start -> Turning Points -> LinkPoints.
- Draws a temporary dashed Line while the inflection point is being dragged.
- The point of inflection (to be inflected) and the point of inflection (already inflected) are handled separately.
The main difference between dealing with a point of inflection (to be inflected) and a point of inflection (already inflected) is:
- To handle inflection points (to be inflected), linkPoints are traversed in pairs.
- To handle inflection points (already inflected), the start and end points are skipped when traversing linkPoints.
- Dragging an inflection point (to be inflected) adds a new inflection point record.
- Dragging an inflection point (already inflected) does not add a new inflection point record.
// src/Render/draws/
export class LinkDraw extends implements {
// summarize
override draw() {
// summarize
// connection line
for (const pair of pairs) {
if ( === ) {
// Manual Folding Line
if (fromGroup && toGroup && fromPoint && toPoint) {
const fromAnchor = (`#${}`)
const toAnchor = (`#${}`)
// Anchor information
const fromAnchorPos = (fromAnchor)
const toAnchorPos = (toAnchor)
// inflexion point (math., a point of a curve at which the curvature changes sign)(abducted)record (in sports etc)
const manualPoints: Array<{ x: number; y: number }> = (
('manualPoints')
)
? ('manualPoints')
: []
// connection point + inflexion point (math., a point of a curve at which the curvature changes sign)
const linkPoints = [
[
(),
()
],
...((o) => [, ]),
[(), ()]
]
// connection line
const linkLine = new ({
name: 'link-line',
// 用于删除connection line
groupId: (),
pointId: ,
pairId: ,
linkType: ,
points: _.flatten(linkPoints),
stroke: 'red',
strokeWidth: 2
})
(linkLine)
// Drag effect in progress
const manualingLine = new ({
stroke: '#ff0000',
strokeWidth: 2,
points: [],
dash: [4, 4]
})
(manualingLine)
// inflexion point (math., a point of a curve at which the curvature changes sign)
// inflexion point (math., a point of a curve at which the curvature changes sign)(awaiting abduction)
for (let i = 0; i < - 1; i++) {
const circle = new ({
id: nanoid(),
pairId: ,
x: (linkPoints[i][0] + linkPoints[i + 1][0]) / 2,
y: (linkPoints[i][1] + linkPoints[i + 1][1]) / 2,
radius: ( / 2),
stroke: 'rgba(0,0,255,0.1)',
strokeWidth: (1),
name: 'link-manual-point',
// opacity: 0,
linkManualIndex: i // 当前inflexion point (math., a point of a curve at which the curvature changes sign)位置
})
// hover effect
('mouseenter', () => {
('rgba(0,0,255,0.8)')
= 'pointer'
})
('mouseleave', () => {
if (!) {
('rgba(0,0,255,0.1)')
= 'default'
}
})
// inflexion point (math., a point of a curve at which the curvature changes sign)操作
('mousedown', () => {
const pos = ()
// record (in sports etc)操作开始state of affairs
({
// Starting coordinates
dragStartX: ,
dragStartY: ,
// in operation
dragStart: true
})
// marking status - in operationinflexion point (math., a point of a curve at which the curvature changes sign)
= true
})
('mousemove', () => {
if () {
// in operation
const pos = ()
if (pos) {
// paste paste (e.g. on a computer screen)
const { pos: transformerPos } = ({
x: ,
y: ,
width: 1,
height: 1
})
// 移动inflexion point (math., a point of a curve at which the curvature changes sign)
(transformerPos)
// Drag effect in progress
const tempPoints = [...linkPoints]
( + 1, 0, [
( - ),
( - )
])
(_.flatten(tempPoints))
}
}
})
('mouseup', () => {
const pos = ()
if (
( - ) > ||
( - ) >
) {
// Operation travel distance reaches threshold
// stage state of affairs
const stageState = ()
// record (in sports etc)(stick)inflexion point (math., a point of a curve at which the curvature changes sign)
(, 0, {
x: ( - ),
y: ( - )
})
('manualPoints', manualPoints)
}
// End of operation
({
dragStart: false
})
// state End of operation
= false
// destroy (by melting or burning)
()
()
// Update History
()
// repaint
()
})
(circle)
}
// inflexion point (math., a point of a curve at which the curvature changes sign)(abducted)
for (let i = 1; i < - 1; i++) {
const circle = new ({
id: nanoid(),
pairId: ,
x: linkPoints[i][0],
y: linkPoints[i][1],
radius: ( / 2),
stroke: 'rgba(0,100,0,0.1)',
strokeWidth: (1),
name: 'link-manual-point',
// opacity: 0,
linkManualIndex: i // 当前inflexion point (math., a point of a curve at which the curvature changes sign)位置
})
// hover effect
('mouseenter', () => {
('rgba(0,100,0,1)')
= 'pointer'
})
('mouseleave', () => {
if (!) {
('rgba(0,100,0,0.1)')
= 'default'
}
})
// inflexion point (math., a point of a curve at which the curvature changes sign)操作
('mousedown', () => {
const pos = ()
// record (in sports etc)操作开始state of affairs
({
dragStartX: ,
dragStartY: ,
dragStart: true
})
// marking status - in operationinflexion point (math., a point of a curve at which the curvature changes sign)
= true
})
('mousemove', () => {
if () {
// in operation
const pos = ()
if (pos) {
// paste paste (e.g. on a computer screen)
const { pos: transformerPos } = ({
x: ,
y: ,
width: 1,
height: 1
})
// 移动inflexion point (math., a point of a curve at which the curvature changes sign)
(transformerPos)
// Drag effect in progress
const tempPoints = [...linkPoints]
tempPoints[] = [
( - ),
( - )
]
(_.flatten(tempPoints))
}
}
})
('mouseup', () => {
const pos = ()
if (
( - ) > ||
( - ) >
) {
// Operation travel distance reaches threshold
// stage state of affairs
const stageState = ()
// record (in sports etc)(update)inflexion point (math., a point of a curve at which the curvature changes sign)
manualPoints[ - 1] = {
x: ( - ),
y: ( - )
}
('manualPoints', manualPoints)
}
// End of operation
({
dragStart: false
})
// state End of operation
= false
// destroy (by melting or burning)
()
()
// Update History
()
// repaint
()
})
(circle)
}
}
} else if ( === ) {
// summarize,straightness
} else {
// summarize,原算法画connection line逻辑
}
}
}
}
Finally, regarding the linkManualing state, it will be used in 2 places to avoid conflicts with other interactions:
// src/Render/handlers/
// summarize
export class DragHandlers implements {
// summarize
handlers = {
stage: {
mousedown: (e: <GlobalEventHandlersEventMap['mousedown']>) => {
// Inflection point in operation,Prevents abnormal dragging
if (!([] as ).) {
// summarize
}
},
// summarize
}
}
}
// src/Render/tools/
// summarize
export class LinkTool {
// summarize
pointsVisible(visible: boolean, group?: ) {
// summarize
// Inflection point in operation,No repainting here
if (!([] as ).) {
// repaint
()
}
}
// summarize
}
Done!
More Stars please!
source code (computing)
gitee source code
sample address (computing)