How to Draw Lines With Css

How to draw responsive lines between divs

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

enter image description here

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.

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.

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.

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.

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.

Answer #1:

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:

  • a transparent div with height of a few px, a 2px width coloured bottom border and with z-index placing it on top of other content.
  • some trig math on the points to be joined from which I calculated distance and angle
  • which I used as CSS div width and rotation. I also made it non-selectable so it would not interfere with other element selection / clicking.

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.

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>                          

Answer #2:

To fix your problem with resizing and everything, position the element using percentage and also create the sizes in percentage. If you don't know how to use position things with percentage, use the javascript below:

                          var              window_width = $(window).width(),         window_height = $(window).height(),         unique_name,         parallax_name_list = [],         parallax_positions = [];              var              vtg = {              pos:                              function(obj){              var              posType =              "offset";         determineObject(obj, posType, window_width, window_height);     },              coord:                              function(){         detectObjectCoords();     }, }                              function                determineObject(obj, posType, window_width, window_height){              if              (($("#"+obj).length ==              0)&&($("."+obj).length ==              0)){              throw              new              Error("VTG_SCRIPT_ERROR: Could not find element '"+obj+"'");              return;         }              else              if              (($("#"+obj).length ==              1)&&($("."+obj).length ==              1)){              throw              new              Error("VTG_SCRIPT_ERROR: Classnames and IDs cannot not have the same name.");              return;         }              else              {                 detectObjectType(obj, posType, window_width, window_height);         } }                              function                detectObjectType(obj, posType, window_width, window_height){              var              object_type;              if              ($("#"+obj).length ==              1){              var              object_type =              "id";     positionObject(obj, object_type, posType, window_width, window_height); }              else              {              var              object_type =              "classname";     positionObject(obj, object_type, posType, window_width, window_height); } }                              function                positionObject(obj,                  type, posType, window_width, window_height){              var              draggable,     pos = posType,     idclass,              type,     dot =              ".",     name;              if              (type              ==              "id"){     draggable = $("#"+obj).draggable();     idclass =              "#";     name = idclass + obj;     unique_name = name; }              else              {      draggable = $("."+obj).draggable();     idclass =              ".";     name = idclass + obj;     unique_name = name; }              var              elem = $(name).position(),     elem_top = elem.top/$(window).height() *              100,     elem_left = elem.left/$(window).width() *              100;              if              ((isNaN(elem_top))&&(isNaN(elem_left))){              console.log("%cCould not calculate the position of the requested object!","font-weight: bold; color: #CC181E;");              return;         }              else              {              console.debug("$('"+name+"').css({ position: 'absolute', top: '"+elem_top+"%', left: '"+elem_left+"%'});");          } }                              function                detectObjectCoords(                ){              var              elm = $(unique_name).position(),         coords_top = elm.top/$(window).height() *              100,         coords_left = elm.left/$(window).width() *              100;              console.clear();              console.log("%cUpdating console","color: #34A953;");              console.debug("$('"+unique_name+"').css({ position: 'absolute', top: '"+coords_top+"%', left: '"+coords_left+"%'});");              return; }                              function                error(msg){              throw              new              Error              ("VTG_SCRIPT_ERROR: "              + msg); }                              function                checkType(name){              var              new_name              if              ($("#"              + name).length ==              1){             new_name =              "#"              + name;              return              new_name;         }              else              if              ($("."              + name).length ==              1){             new_name =              "."              + name;              return              new_name;         }              else              {             error("The element could not be found.");              return              false;         } }                              function                empty(word){              if              (word ==              ""){              return              true;     }              else              {              return              false;     } }                      

This piece of code is from a framework i am currently working on. It requires the jQuery library. To use it, type in > vtg.pos("your object class/id"); and you should be able to drag your object around until you have refreshed the page. Once you are happy with the position, type vtg.coord(); in the console and copy the returned code and paste the code into your html/js file. If you are unsure what to copy, the returned code should look similar to this:

$('#your item').css({ position: 'absolute', top: '30.841007053291534%', left: '42.31259266123054%'});

You can use my code top position the lines you wanted

Answer #3:

I'm still unclear about exactly what you want to do, but perhaps the first diagram of the GoJS Introduction's second page demonstrates what you want: http://gojs.net/latest/intro/buildingObjects.html. That diagram is live! Now that diagram does not allow the user to draw new comments, but such functionality could be provided in an editor version of the diagram.

A sample also demonstrates a different style for comments, balloon comments, in http://gojs.net/latest/samples/comments.html. You can find a lot more samples at http://gojs.net.

How to Draw Lines With Css

Source: https://www.py4u.net/discuss/358742

0 Response to "How to Draw Lines With Css"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel