├── README.md ├── LICENSE ├── vectorUtil.js └── pathPoints └── connection-straight.js /README.md: -------------------------------------------------------------------------------- 1 | ### es6模块 2 | 主函数在 pathPoints/connection-straight.js 中 3 | 4 | #### 参数 example 5 | 6 | ``` 7 | { 8 | entryPoint = [0, 0], 9 | entryDirection = [0, 1], 10 | entryExt = 10, 11 | exitPoint = [10, 10], 12 | exitDirection = [1, 0], 13 | exitExt = 10 14 | }, 15 | turnRatio=0.5 16 | ``` 17 | 18 | #### entryPoint 19 | 起点坐标 20 | 21 | #### entryDirection 22 | 起点方向(单位向量) 23 | 24 | #### entryExt 25 | 起点延申线长度 26 | 27 | #### exitPoint 28 | 终点坐标 29 | 30 | #### exitDirection 31 | 终点方向 32 | 33 | #### exitExt 34 | 终点延伸线 35 | 36 | #### turnRatio 37 | 折弯处比例 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vectorUtil.js: -------------------------------------------------------------------------------- 1 | 2 | // 向量相加 或者 向量与坐标相加 3 | export const add = function(vectorA,vectorB){ 4 | return [vectorA[0]+vectorB[0],vectorA[1]+vectorB[1]] 5 | } 6 | 7 | // 向量乘以常量系数 8 | export const multiply = function(vector,k){ 9 | return [vector[0]*k,vector[1]*k] 10 | } 11 | 12 | // 两点之间的向量,a点指向b点 13 | export const vectorFromPoints = function(pointA,pointB){ 14 | return [pointB[0]-pointA[0],pointB[1]-pointA[1]] 15 | } 16 | 17 | // 判断向量是否平行 18 | export const isParallel = function(vectorA,vectorB){ 19 | if(vectorA[0]*vectorB[1] - vectorA[1]*vectorB[0] === 0) return true; 20 | 21 | return false; 22 | } 23 | 24 | //向量点积 25 | export const dot= function(vectorA, vectorB){ 26 | return vectorA[0]*vectorB[0] + vectorA[1]*vectorB[1]; 27 | } 28 | // 向量叉乘 29 | export const cross = function (vectorA,vectorB){ 30 | return vectorA[0]*vectorB[1]- vectorA[1]*vectorB[0]; 31 | } 32 | 33 | // 向量夹角 34 | export const angleFrom = function(vector){ 35 | return Math.acos(vector[0]/Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1])) 36 | } 37 | 38 | // 获取向量的单位向量 39 | export const getUnitVector = function(vector){ 40 | var m = Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]) 41 | return [vector[0]/m,vector[1]/m] 42 | } 43 | 44 | // 判断向量 x,y 坐标相等 45 | export const equals=function(vector,target){ 46 | return vector[0] === target [0] && vector[1] === target[1] 47 | } 48 | 49 | -------------------------------------------------------------------------------- /pathPoints/connection-straight.js: -------------------------------------------------------------------------------- 1 | 2 | import { add, multiply, vectorFromPoints ,isParallel ,dot ,getUnitVector,equals } from "../vectorUtil" 3 | 4 | //中线智能 避让 5 | 6 | // let turnRatio = 0.5 7 | 8 | //描述方向 使用svg 平面轴 上:[0,-1] 右:[1,0] 下 [1,1] 左 [-1,0] 9 | // path 指除了延申线之外的连接线 10 | function generateConnectionPoints({entryPoint = [0, 0], entryDirection = [0, 1], entryExt = 10, exitPoint = [10, 10], exitDirection = [1, 0], exitExt = 10},turnRatio=0.5) { 11 | // 1. 获得入方向和出方向 ——参数中已获得; 当exitDirection 未定义时 12 | if(exitDirection === null || exitDirection.join() == '0,0'){ 13 | let entryToExit = vectorFromPoints(exitPoint,entryPoint) 14 | if(Math.abs(entryToExit[0])>Math.abs(entryToExit[1])){ 15 | exitDirection = [entryToExit[0]/Math.abs(entryToExit[0]),0] 16 | }else{ 17 | exitDirection = [0,entryToExit[1]/Math.abs(entryToExit[1])] 18 | } 19 | } 20 | 21 | // 2. 获得直接 path 的水平和竖直方向 22 | let pathStartP = add(entryPoint, multiply(entryDirection, entryExt)); 23 | let pathEndP = add(exitPoint, multiply(exitDirection, exitExt)); 24 | 25 | // 出口方向需要取反 26 | exitDirection = multiply(exitDirection,-1); 27 | 28 | //直接path的向量 29 | // let pathVec = vectorFromPoints(pathEndP,pathStartP); 30 | // path的水平向量 31 | let pathHorizenVec = [pathEndP[0]-pathStartP[0],0]; 32 | // path 的竖直向量 33 | let pathVerticalVec = [0,pathEndP[1] - pathStartP[1]]; 34 | 35 | 36 | //3.计算path 的起始方向: 两方向与入方向平行的一项,如果是同向则取之,反之则取非平行的一项 37 | let comp = [pathHorizenVec,pathVerticalVec] 38 | let pathStart ; 39 | let startParallelVec =comp.find(vec=>isParallel(vec,entryDirection)); 40 | 41 | if(dot(startParallelVec,entryDirection)>0){ 42 | pathStart = startParallelVec 43 | }else{ 44 | pathStart =anotherOne(comp,startParallelVec); 45 | } 46 | 47 | // 4.计算path 的末方向: 两方向与末方向平行的一项,如果是同向则取之,反之则取非平行的一项 48 | let pathEnd; 49 | let endParallelVec =comp.find(vec=>isParallel(vec,exitDirection)); 50 | 51 | if(dot(endParallelVec,exitDirection)>0){ 52 | pathEnd = endParallelVec 53 | }else{ 54 | pathEnd =anotherOne(comp,endParallelVec); 55 | 56 | } 57 | 58 | //5.如果path的起末为同方向,则分为两段,否则为1段 59 | let splitNum= dot(pathStart,pathEnd)>0?2:1; 60 | 61 | let pathMiddle = anotherOne(comp,pathEnd); 62 | 63 | //6.计算path中的转折点 返回数据中加入了单位向量 64 | let points=[]; 65 | points.push({ 66 | position:entryPoint, 67 | direction:null 68 | },{ 69 | position:pathStartP, 70 | direction:entryDirection 71 | }); 72 | if(splitNum == 1){ 73 | let point1 = add(pathStartP,pathStart) 74 | let dir1 = getUnictVecByStraight(pathStart) 75 | let point2 = add(point1,pathEnd) 76 | let dir2 = getUnictVecByStraight(pathEnd) 77 | points.push({ 78 | position:point1, 79 | direction:dir1 80 | },{ 81 | position:point2, 82 | direction:dir2 83 | }) 84 | }else{ 85 | 86 | let point1= add(pathStartP,multiply(pathStart,turnRatio)); 87 | 88 | let dir1 = getUnictVecByStraight(pathStart); 89 | 90 | let point2 = add(point1,pathMiddle); 91 | let dir2 = getUnictVecByStraight(pathMiddle); 92 | let point3 = add (point2,multiply(pathEnd,1-turnRatio)); 93 | let dir3 =getUnictVecByStraight(pathEnd) 94 | 95 | 96 | points.push({ 97 | position:point1, 98 | direction:dir1 99 | },{ 100 | position:point2, 101 | direction:dir2, 102 | type:"pathMiddleP" 103 | },{ 104 | position:point3, 105 | direction:dir3 106 | }) 107 | } 108 | points.push({ 109 | position:exitPoint, 110 | direction:exitDirection 111 | }); 112 | 113 | return points.filter(v=>v.direction !== false); 114 | 115 | } 116 | 117 | // 两个元素的数组中的另一个 118 | function anotherOne(comp,a){ 119 | return comp.find(v=>v !=a ) 120 | } 121 | 122 | // 获取竖直和水平向量的单位向量 123 | function getUnictVecByStraight(vector){ 124 | if( vector[0] == 0 && vector[1] == 0) 125 | return false 126 | else if(vector[0] == 0) 127 | return [0,vector[1]/Math.abs(vector[1])] 128 | else if (vector[1] == 0) 129 | return [vector[0]/Math.abs(vector[0]),0] 130 | else 131 | return getUnitVector(vector) 132 | } 133 | 134 | export default generateConnectionPoints; --------------------------------------------------------------------------------