如何在div之间绘制响应线 [英] How to draw responsive lines between divs

查看:53
本文介绍了如何在div之间绘制响应线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我要翻译成代码的照片.

Here's a photo of what I'm trying to translate into code.

我还需要布置一些概念"区域,并且很难找出一种可以着手工作的方法,以实现这一目标.我最初的想法是将所有内容布置成行以外的所有行,以便我可以根据每个屏幕尺寸来调整它们的位置,然后回来,并使用媒体查询切换它们,以便为元素的每次移动做一组行.对于小尺寸的平板电脑和手机,我认为我只是将粗略草图放大,并且各线所指向的每个部分上都有一些小图标,这会打开一个弹出窗口以给出说明.

I have a few more "Concept" areas I'm going to need to lay out and am having difficulty figuring out a method to embark upon in order to achieve this in a manner that works responsively. My original idea was to just lay everything out except the lines so I can adjust their positions accordingly to each screen size then come back and do a set of lines for each shift of elements using media queries to toggle them. For small tablet and cell phone sizes I figured I'd just make the rough sketch bigger and have little icons on each part the lines are pointing to that opens a popup window giving the explanation.

到目前为止,我在这里找到了几篇文章,展示了如何使用SVG和Canvas绘制线条,但是我注意到,当我重新设计时,他们给出的示例仅适用于为其设计的窗口大小调整小提琴窗口的大小,一切都变了.

So far I've found a few posts on here that showed how to draw the lines both with SVG and Canvas, but I noticed that the examples they gave only worked for the window size they designed it for, when I re-sized the fiddle window everything went way off.

我碰到了另外几篇文章,其中对jsPlumb给予了高度评价,尽管我绝对肯定会开始学习和使用它,但到目前为止,除了我想做的事情之外,它似乎不适合我想做的事情事实上,无论它们位于何处,它都会在源和目标之间建立并保持一条线.我觉得它的可拖动性对于我想做的事情是不必要的,并且无法确定是否有一种方法可以将其打开和关闭,我不希望人们试图向下滚动他们的电话并陷入刷卡屏幕周围的框.

I came across a couple more posts where jsPlumb was heavily praised, though I am most definitely going to start learning and using it, so far it doesn't seem appropriate for what I want to do with this in particular other than the fact it creates and maintains a line between the source and target no matter where they're located. I feel the draggable nature of it was unnecessary for what I want to do and couldn't find out if there was a way to toggle it on and off, I don't want people trying to scroll down on their phone and getting stuck swiping the boxes around the screen.

事实证明,jsPlumb上确实没有太多内容,但是研究它使我进入了GoJS,它看起来与jsPlumb非常相似,但又一次,我无法在其上找到大量信息,或者许多视频,深入探讨了如何使用它来做事.

It turns out that there really isn't much on jsPlumb, but looking into it led me to GoJS, which seems very similar to jsPlumb but once again, I wasn't able to find an extensive amount of info on it or many videos of people going in depth with how to do things with it.

我遇到了SVGjs并对其进行了研究,但是从我看到的示例中看,它似乎与我所看到的第一个SVG和Canvas示例几乎一样,但似乎并没有提供灵活性.最重要的是,我现在可以使用javascript进行婴儿说话",因此尽管我能理解得足够多,可以识别出我不理解并查找的内容,但我还是不太流利.为了跟上我所发现的有关这些库的信息的语气,这些库是为那些已经非常了解JS深度而无需更多解释的人编写的.

I came across SVGjs and looked into it, but from the examples I've seen it seems pretty much the same thing as the first SVG and Canvas examples I saw which didn't appear to provide flexibility. On top of this I'm just now at a point where I can "baby talk" in javascript so though I can understand it enough to be able to identify what I don't understand and look it up, I'm not fluent enough to keep up with the tone of the info I am finding about these libraries which is written for those who already know the depths of JS well enough to not need more explaining.

我知道通常情况下,你们还是喜欢看我们到目前为止修改过的代码示例,以解决实际的编码问题,而不是问您如何做?您是否已经为我们完成了所有编码工作,但是我在某个时刻,我什至不知道该怎么做才能做到这一点.因此,我希望你们能看到我已经真正地尝试了以一种我迄今为止能够做到的最好的方式来实现这一目标,并且不要让我的票数下降而大声疾呼.我真的不知道从这里去哪里.

I know normally you guys prefer to see an example of code we tinkered with so far to have actual coding issues to be resolved, vs. asking you how to do something n have you do all the coding work for us, but I'm at a point where I don't even know what to try in order to accomplish this. So I hope you guys can see I've genuinely tried to approach this the best way I'm able to so far and don't stone me with the down votes lol. I truly don't know where to go from here.

推荐答案

客观地,您似乎试图在HTML元素中任意锚定的两个点之间绘制许多连接器线.在类似的项目中,我使用了以下配方:

Objectively, it looks like you are trying to draw a number of connector lines between two points arbitrarily anchored within HTML elements. In a similar project I used this recipe:

  • 一个透明的div,高度为px,底部边框为2px宽,底部边框为z-index,位于其他内容的顶部.
  • 关于要连接的点的一些trig数学,从中我计算出距离和角度
  • 用作CSS div的宽度和旋转度.我也将其设为不可选择,因此不会干扰其他元素的选择/单击.

结果是一个div,它的一个底角位于A点,另一个位于B点,产生了一条非常漂亮的线,我可以完全控制它.

Result was a div with one bottom corner at point A and the other at point B, producing a very nice line over which I had full control.

您需要做两次以获取肘部连接.您可以在页面渲染或重新绘制等之后触发绘制.

You would need to do that twice to get your elbow connection. You could trigger the draw after the page render or redraw etc.

下面的代码段中的工作示例-可能在全屏模式下和在Codepen上运行效果最佳. http://codepen.io/JEE42/pen/aBOQGj ,以备不时之需.

Working example in snippet below - probably run best in full-screen, and at codepen http://codepen.io/JEE42/pen/aBOQGj in case you want to play.

/*
muConnector - a class to create a line joining two elements.

To use, call new with id's of both elements and optonal lineStyle (which must be a valid css border line def such as '1px solid #000' , e.g.
var c1=new Connector(id1, id2, lineStyle)

Default line style is '1px solid #666666'

Whatever you use for drag control, call moved(e, ele) per increment of movement, where e=event and ele=the jq element being moved.

*/

var Connector = function(params) {
if (typeof(params) == "undefined") { return false }; // If no params then abandon.
// Process input params.
var ele1=params.ele1 || '';   // First element to link
var ele2=params.ele2 || '';   // Second element to link
if ( ele1.length === 0 || ele2.length === 0)  { return false }; // If not two element id's then abandon. 

var className=params.class || 'muConnector'

var lineStyle=params.lineStyle || '1px solid #666666';   // CSS style for connector line.

this.gapX1=params.gapX1 || 0;  // First element gap before start of connector, etc
this.gapY1=params.gapY1 || 0;  
this.gapX2=params.gapX2 || 0;
this.gapY2=params.gapY2 || 0;


this.gap=params.gap || 0; // use a single gap setting.
if ( this.gap > 0 ) {
	this.gapX1 = this.gap
	this.gapY1 = this.gap
	this.gapX2 = this.gap
	this.gapY2 = this.gap
}

var pos = function() { // only used for standalone drag processing.
	this.left = 0;
	this.top = 0;
}
		
this.PseudoGuid = new (function() { // Make a GUID to use in unique id assignment - from and credit to http://stackoverflow.com/questions/226689/unique-element-id-even-if-element-doesnt-have-one
	this.empty = "00000000-0000-0000-0000-000000000000";
	this.GetNew = function() {
		var fC = function() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1).toUpperCase(); }
		return (fC() + fC() + "-" + fC() + "-" + fC() + "-" + fC() + "-" + fC() + fC() + fC());
	};
})();

this.id = this.PseudoGuid.GetNew(); // use guid to avoid id-clashes with manual code.
this.ele1=($('#'+ele1));
this.ele2=($('#'+ele2));

// Append the div that is the link line into the DOM
this.lineID='L' + this.id;
$('body').append("<div id='" + this.lineID + "' class='" + className + "' style=  ></div>")
this.line = $('#L'+ this.id);
this.line.css({ position: 'absolute', 'border-left': this.lineStyle, 'z-index': -100 }) 

// We may need to store the offsets of each element that we are connecting.
this.offsets=[];
this.offsets[ele1]=new pos;
this.offsets[ele2]=new pos;

this.link(); // show the initial link
}

/*
Approach: draw a zero width rectangle where the top left is located at the centre of ele1. 
Compute and make rectangle height equal to the distance between centres of ele1 and ele2.
Now rotate the rectangle to the angle between the points.
Note tracks the edges of the elements so as not to overlay / underlay.
Also can accommodate a gap between edge of element and start of line.

*/	
Connector.prototype.link=function link() {

	var originX = this.ele1.offset().left + this.ele1.outerWidth() / 2;
	var originY = this.ele1.offset().top + this.ele1.outerHeight() / 2;
  
	var targetX = this.ele2.offset().left + this.ele2.outerWidth() / 2;
	var targetY = this.ele2.offset().top + this.ele2.outerHeight() / 2;
	
	var l = this.hyp((targetX - originX),(targetY - originY));
	var angle = 180 / 3.1415 * Math.acos((targetY - originY) / l);
	if(targetX > originX) { angle = angle * -1 }
	
	// Compute adjustments to edge of element plus gaps.
	var adj1=this.edgeAdjust(angle, this.gapX1 + this.ele1.width() / 2, this.gapY1 + this.ele1.height() / 2)
	var adj2=this.edgeAdjust(angle, this.gapX2 + this.ele2.width() / 2, this.gapY2 + this.ele2.height() / 2)

 
	l = l - ( adj1.hp + adj2.hp)
	
	this.line.css({ left: originX, height: l, width: 0, top: originY +  adj1.hp })
		.css('-webkit-transform', 'rotate(' + angle + 'deg)')
		.css('-moz-transform', 'rotate(' + angle + 'deg)')
		.css('-o-transform', 'rotate(' + angle + 'deg)')
		.css('-ms-transform', 'rotate(' + angle + 'deg)')
		.css('transform', 'rotate(' + angle + 'deg)')
		.css('transform-origin', '0 ' + ( -1 * adj1.hp) + 'px');

}

Connector.prototype.Round = function(value, places) {
    var multiplier = Math.pow(10, places);
    return (Math.round(value * multiplier) / multiplier);
}
	
Connector.prototype.edgeAdjust = function (a, w1, h1) {
	var w=0, h=0
	
	// compute corner angles
	var ca=[]
	ca[0]=Math.atan(w1/h1) * 180 / 3.1415926 // RADIANS !!!
	ca[1]=180 - ca[0]
	ca[2]=ca[0] + 180
	ca[3]=ca[1] + 180
	
	// Based on the possible sector and angle combinations work out the adjustments.
	if ( (this.Round(a,0) === 0)  ) {
		h=h1
		w=0
	}
	else if ( (this.Round(a,0) === 180)  ) {
		h=h1
		w=0
	}
	else if ( (a > 0 && a <= ca[0]) || (a < 0 && a >= (-1*ca[0]))  ) {
		h=h1
		w=-1 * Math.tan(a * ( 3.1415926 / 180)) * h1
	}
	
	else if (  a > ca[0] && a <= 90 ) {
		h=Math.tan((90-a) * ( 3.1415926 / 180)) * w1
		w=w1
	}
	else if (  a > 90 && a <= ca[1]  ) {
		h=-1 * Math.tan((a-90) * ( 3.1415926 / 180)) * w1
		w=w1
	}
	else if (  a > ca[1] && a <= 180  ) {
		h=h1
		w=-1 * Math.tan((180 - a) * ( 3.1415926 / 180)) * h1
	}
	else if (  a > -180 && a <= (-1 * ca[1])  ) {
		h=h1
		w= Math.tan((a - 180) * ( 3.1415926 / 180)) * h1
	}	
	else if (  a > (-1 * ca[1])  && a <=  0 ) {
		h=Math.tan((a-90) * ( 3.1415926 / 180)) * w1
		w= w1
	}	

	// We now have the width and height offsets - compute the hypotenuse.
	var hp=this.hyp(w, h)
	
	return {hp: hp }	
}		

Connector.prototype.hyp = function hyp(X, Y) {
return Math.abs(Math.sqrt( (X * X) + ( Y * Y) ))
}


Connector.prototype.moved=function moved(e, ele) {
	var id=ele.attr('id');
	this.link()
}





var line;
$( document ).ready(function() {
    console.log( "ready!" );

	var c1=new Connector({ele1: 'a', ele2: 'b', lineStyle: '1px solid red' })
	Setup(c1, 'a');
	Setup(c1, 'b');
	
	var c2=new Connector({ele1: 'a', ele2: 'c', lineStyle: '1px solid red' })
	Setup(c2, 'a');
	Setup(c2, 'c');

	var c3=new Connector({ele1: 'a', ele2: 'd', lineStyle: '1px solid red' })
	Setup(c3, 'a');
	Setup(c3, 'd');
	
	var c4=new Connector({ele1: 'b', ele2: 'c'})
	Setup(c4, 'b');
	Setup(c4, 'c');	

	var c5=new Connector({ele1: 'b', ele2: 'd'})
	Setup(c5, 'b');
	Setup(c5, 'd');	
	
	var c6=new Connector({ele1: 'c', ele2: 'd'})
	Setup(c6, 'c');
	Setup(c6, 'd');


	function Setup(connector, id) {
		var ele=$('#'+id);
		ele.on('mousedown.muConnector', function(e){
			
			//#critical: tell the connector about the starting position when the mouse goes down.
			connector.offsets[id].left=e.pageX - ele.offset().left;
			connector.offsets[id].top=e.pageY - ele.offset().top;
		
			e.preventDefault();
			
			//hook the mouse move			
			ele.on('mousemove.muConnector', function(e){
			   ele.css({left: e.pageX - connector.offsets[id].left, top: e.pageY - connector.offsets[id].top}); //element position = mouse - offset
			  connector.moved(e, ele); // #critical: call the moved() function to update the connector position.
			});
			
			//define mouse up to cancel moving and mouse up, they are recreated each mousedown
			$(document).on('mouseup', function(e){
			  ele.off('mousemove.muConnector');
			  //$(document).off('.muConnector');
			});
			
		});
	}		

});

.thing {
  width: 200px;
  height: 100px;
  background: transparent;
  position: absolute;
  border: 1px solid #666666;
}

.thing span {
  display: block;
  margin-left: 95px;
  margin-top: 40px;
}

.muConnector {
  position: absolute;
  border-left: 1px dashed red;
  z-index: 100;
  -webkit-transform-origin: top left;
  -moz-transform-origin: top left;
  -o-transform-origin: top left;
  -ms-transform-origin: top left;
  transform-origin: top left;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span>Drag any box...</span>

  <div id="a" class='thing' style='left:400px; top: 100px;'>
    <span>o</span>
  </div>
  
  
  <div id="b" class='thing' style='left:600px; top: 300px;'>
    <span>o</span>
  </div>

  <div id="c" class='thing' style='left:400px; top: 500px;'>
    <span>o</span>
  </div>
  
  
  <div id="d" class='thing' style='left:200px; top: 300px;'>
    <span>o</span>
  </div>

这篇关于如何在div之间绘制响应线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆