[英]Connect Line Between 2 Elements - Javascript
我目前正在研究使用 Javascript 創建單線圖的方法。我目前能夠使用以下 function 連接兩個 html 元素:
adjustLine (from, to, line) {
var fT = from.offsetTop + from.offsetHeight/2;
var tT = to.offsetTop + to.offsetHeight/2;
var fL = from.offsetLeft + from.offsetWidth/2;
var tL = to.offsetLeft + to.offsetWidth/2;
var CA = Math.abs(tT - fT);
var CO = Math.abs(tL - fL);
var H = Math.sqrt(CA*CA + CO*CO);
var ANG = 180 / Math.PI * Math.acos( CA/H );
if(tT > fT){
var top = (tT-fT)/2 + fT;
}else{
var top = (fT-tT)/2 + tT;
}
if(tL > fL){
var left = (tL-fL)/2 + fL;
}else{
var left = (fL-tL)/2 + tL;
}
if(( fT < tT && fL < tL) || ( tT < fT && tL < fL) || (fT > tT && fL > tL) || (tT > fT && tL > fL)){
ANG *= -1;
}
top-= H/2;
line.style["-webkit-transform"] = 'rotate('+ ANG +'deg)';
line.style["-moz-transform"] = 'rotate('+ ANG +'deg)';
line.style["-ms-transform"] = 'rotate('+ ANG +'deg)';
line.style["-o-transform"] = 'rotate('+ ANG +'deg)';
line.style["-transform"] = 'rotate('+ ANG +'deg)';
line.style.top = top+'px';
line.style.left = left+'px';
line.style.height = H + 'px';
}
function 有 3 個參數:
這工作正常並輸出以下結果:
然而,連接 html 元素的線是一條直線,我想要一個更自然的圖表流程,如下所示:
關於我如何 go 這樣做有什么建議嗎? 任何幫助是極大的贊賞!
編輯
我正在使用 html2canvas 創建生成的 output 的圖像。這是我的代碼:
var myDiv = document.getElementById('content');
html2canvas(myDiv, {useCORS: true, allowTaint : true}).then(function (canvas) {
var imgData = canvas.toDataURL("image/png", 1.0);
var imgData2 = canvas2.toDataURL("image/png", 1.0);
var pdf = new jsPDF('l', 'pt', [HTML_Width, HTML_Height]);
pdf.internal.scaleFactor = 30;
pdf.addImage(imgData, 'PNG', 0, 0, HTML_Width, HTML_Height);
pdf.addPage();
pdf.addImage(imgData2, 'PNG', 0, 0, HTML_Width_2, HTML_Height_2);
pdf.save("my_file.pdf");
});
所以這里是我的 SVG 解決方案!
const xmlns = 'http://www.w3.org/2000/svg', svgLink = 'http://www.w3.org/1999/xlink', elmSVG = document.getElementById('elmSVG'), bot_inversor = 80, top_fotovolta = 300; for (let i=0;i<4;i++) { let x = 10 + (i*60), fotovolta = document.createElementNS(xmlns, 'use'); fotovolta.setAttributeNS(svgLink, 'xlink:href', '#fotovoltaico'); fotovolta.setAttributeNS(null, 'x', x); fotovolta.setAttributeNS(null, 'y', top_fotovolta); fotovolta.setAttributeNS(null, 'width', '50'); fotovolta.setAttributeNS(null, 'height', '70'); elmSVG.appendChild(fotovolta); adjustLines(i); } function adjustLines(item) { let left = (item<2) // the hard part... , b1 = 25 + (item *60) + (left?0:20), b2 = b1 + (left?20:-20), a1 = 105 + (item *10) + (left?0:10), a2 = a1 + (left?5:-5), l1 = 50 + (left?item:3-item) *30, l2 = l1 + 10; let jLine1 = document.createElementNS(xmlns, 'polyline'); jLine1.setAttributeNS(null, 'points', `${b1},${top_fotovolta} ${b1},${bot_inversor+l1} ${a1},${bot_inversor+l1} ${a1},${bot_inversor}`); elmSVG.appendChild(jLine1); let jLine2 = document.createElementNS(xmlns, 'polyline'); jLine2.setAttributeNS(null, 'points', `${b2},${top_fotovolta} ${b2},${bot_inversor+l2} ${a2},${bot_inversor+l2} ${a2},${bot_inversor}`); elmSVG.appendChild(jLine2); }
#elmSVG { width: 250px; height: 380px; background-color: #b4f0f0; margin: 1em; } #elmSVG * { fill:none; stroke:#2f363d; stroke-width:2px; }.curveSVG { stroke-linecap:round; }
<h2>Connecting Lines</h2> <svg id="elmSVG" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 380"> <defs> <symbol id="inversor" viewBox="0 0 70 70"> <rect x="0" y="0" width="70" height="70" /> <line x1="70" x2="0" y1="0" y2="70" /> <line x1="10" x2="30" y1="15" y2="15" /> <line x1="10" x2="30" y1="20" y2="20" /> <path d="M 40,55 Q 45,45 50,55 T 60,55" class="curveSVG" /> </symbol> <symbol id="fotovoltaico" viewBox="0 0 50 70"> <rect x="0" y="0" width="50" height="70" /> <line x1="0" x2="25" y1="0" y2="20" /> <line x1="50" x2="25" y1="0" y2="20" /> </symbol> </defs> <use xlink:href="#inversor" x="90" y="10" width="70" height="70" /> </svg>
<canvas>
的其他解決方案
const eCanvas = document.getElementById('elmCanvas'), cCanvas = eCanvas.getContext('2d'), bot_inversor = 80, top_fotovolta = 300; // set background color cCanvas.fillStyle = 'rgb(178, 240, 240)' cCanvas.fillRect(0, 0, eCanvas.width, eCanvas.height ) Draw_Inversor( cCanvas, (eCanvas.width/2 - 70/2), 10) for (let i=0;i<4;i++) { Draw_Fotovoltaico( cCanvas, 10+(i*60), top_fotovolta ); Draw_connectsLines( cCanvas, i, 4, (eCanvas.width/2), (10+(i*60)+25) ); } function Draw_Inversor( ctx, x, y ) { ctx.beginPath(); ctx.moveTo(x+70, y); ctx.lineTo(x, y+70); ctx.lineTo(x, y); ctx.lineTo(x+70, y); ctx.lineTo(x+70, y+70); ctx.lineTo(x, y+70); ctx.moveTo(x+10, y+15); ctx.lineTo(x+30, y+15); ctx.moveTo(x+10, y+20); ctx.lineTo(x+30, y+20); ctx.moveTo(x+50, y+55); ctx.arc(x+45, y+55, 5, 0, Math.PI, true); ctx.moveTo(x+60, y+55); ctx.arc(x+55, y+55, 5, 0, Math.PI, false); ctx.stroke(); } function Draw_Fotovoltaico( ctx, x, y ) { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x+25, y+20); ctx.lineTo(x+50, y); ctx.lineTo(x, y); ctx.lineTo(x, y+70); ctx.lineTo(x+50, y+70); ctx.lineTo(x+50, y); ctx.stroke(); } function Draw_connectsLines( ctx, no, maxOcc, topCenter, botCenter ) { let mid = maxOcc/2, left = no < mid, decal = left? no:(maxOcc/2)-no+1, topL1 = 50+ (decal *30), topL2 = topL1 +10, topX1 = topCenter + (left? -(mid-decal)*10: +(mid-decal)*10 ), topX2 = topX1 +(left?+5:-5), botX1 = botCenter + (left?-10:+10), botX2 = botCenter + (left?+10:-10); ctx.beginPath(); ctx.moveTo(topX1, bot_inversor); ctx.lineTo(topX1, bot_inversor +topL1 ); ctx.lineTo(botX1, bot_inversor +topL1 ); ctx.lineTo(botX1, top_fotovolta ); ctx.stroke(); ctx.beginPath(); ctx.moveTo(topX2, bot_inversor); ctx.lineTo(topX2, bot_inversor +topL2 ); ctx.lineTo(botX2, bot_inversor +topL2 ); ctx.lineTo(botX2, top_fotovolta ); ctx.stroke(); }
#elmCanvas { margin: 1em; }
<canvas id="elmCanvas" width="250" height="400"></canvas>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.