Snap To Grid Functionality Using Javascript

Everyone, I am working on SVG, the problem that I am facing is that I want to implement Snap To Grid functionality in my application, I made a grid using a line in SVG, I also implemented a drag and drop function in this. Now I want to implement Snap to Grid functionality. Any help would be awesome, much appreciated, the svg file name (DndD.svg) save it with that name Regards: Zain

Here is the code

<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <object data="DndD.svg" id="oo" style="width: 800px" height="500px"> </object> <span id="trail" style="visibility: hidden"></span> </body> <script type="text/javascript"> var far=document.getElementById("oo") far.addEventListener("load", function (){ var svgDoc=far.contentDocument; var svgRoot=svgDoc.documentElement; var r=svgDoc.getElementById("rectangle") r.onmousemove=function(evt){ var x=evt.pageX var y=evt.pageY document.getElementById('trail').style.visibility="visible"; document.getElementById('trail').style.position="absolute"; document.getElementById('trail').style.left=evt.clientX+10; document.getElementById('trail').style.top=evt.clientY; document.getElementById("trail").innerHTML=x+","+y } var line2; var count=0 var xx=0 var yy=0 line2="line_id"+count for(var i=0;i<=48;i++){ xx=xx+10 var line=svgDoc.createElementNS("http://www.w3.org/2000/svg", "line") line.setAttribute("id", line2) line.setAttribute("x1", xx) line.setAttribute("y1", "0") line.setAttribute("x2", xx) line.setAttribute("y2", "400") line.setAttribute("stroke", "red") line.setAttribute("stroke-width", "1") line.setAttribute("pointer-events", "none") svgRoot.appendChild(line) } for(var i=0;i<=39;i++){ yy=yy+10 var line=svgDoc.createElementNS("http://www.w3.org/2000/svg", "line") line.setAttribute("id", line2) line.setAttribute("x1", "0") line.setAttribute("y1", yy) line.setAttribute("x2", "500") line.setAttribute("y2", yy) line.setAttribute("stroke", "red") line.setAttribute("stroke-width", "1") line.setAttribute("pointer-events", "none") svgRoot.appendChild(line) } var rec = svgDoc.createElementNS("http://www.w3.org/2000/svg", "rect"); rec.setAttribute("id", "btn_rect"); rec.setAttribute("fill","orange") rec.setAttribute("stroke","black") rec.setAttribute( "x","100px") rec.setAttribute( "y","100px") rec.setAttribute( "width","45px") rec.setAttribute( "height","45px") rec.setAttribute( "rx","3px") rec.setAttribute( "ry","3px") svgRoot.appendChild(rec); },false) </script> </html> SVG CODE other file <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="Init(evt)" onmousedown="Grab(evt)" onmousemove="Drag(evt)" onmouseup="Drop(evt)" > <rect x="0" y="0" width="500px" height="400px" fill="black" stroke="black" id="rectangle" pointer-events="none"/> <script> <![CDATA[ var SVGDocument = null; var SVGRoot = null; SVG_lay=new Array(); var TrueCoords = null; var GrabPoint = null; var BackDrop2 = null; var DragTarget = null; function Init(evt) { SVGDocument = evt.target.ownerDocument; SVGRoot = SVGDocument.documentElement; // these svg points hold x and y values... // very handy, but they do not display on the screen (just so you know) TrueCoords = SVGRoot.createSVGPoint(); GrabPoint = SVGRoot.createSVGPoint(); // this will serve as the canvas over which items are dragged. // having the drag events occur on the mousemove over a backdrop // (instead of the dragged element) prevents the dragged element // from being inadvertantly dropped when the mouse is moved rapidly BackDrop2 = SVGDocument.getElementById('BackDrop1'); } function Grab(evt) { // find out which element we moused down on var targetElement = evt.target; //SVG_lay.push(targetElement); // you cannot drag the background itself, so ignore any attempts to mouse down on it if ( BackDrop2 != targetElement ) { //set the item moused down on as the element to be dragged DragTarget = targetElement; // move this element to the "top" of the display, so it is (almost) // always over other elements (exception: in this case, elements that are // "in the folder" (children of the folder group) with only maintain // hierarchy within that group DragTarget.parentNode.appendChild( DragTarget ); // turn off all pointer events to the dragged element, this does 2 things: // 1) allows us to drag text elements without selecting the text // 2) allows us to find out where the dragged element is dropped (see Drop) DragTarget.setAttributeNS(null, 'pointer-events', 'none'); // we need to find the current position and translation of the grabbed element, // so that we only apply the differential between the current location // and the new location var transMatrix = DragTarget.getCTM(); GrabPoint.x = TrueCoords.x - Number(transMatrix.e); GrabPoint.y = TrueCoords.y - Number(transMatrix.f); } }; function Drag(evt) { // account for zooming and panning GetTrueCoords(evt); // if we don't currently have an element in tow, don't do anything if (DragTarget) { // account for the offset between the element origin and the // exact place we grabbed it... this way, the drag will look more natural var newX = TrueCoords.x - GrabPoint.x; var newY = TrueCoords.y - GrabPoint.y; // apply a new tranform translation to the dragged element, to display // it in its new location DragTarget.setAttributeNS(null, 'transform', 'translate(' + newX + ',' + newY + ')'); } }; function Drop(evt) { // if we aren't currently dragging an element, don't do anything if ( DragTarget ) { // since the element currently being dragged has its pointer-events turned off, // we are afforded the opportunity to find out the element it being dropped on var targetElement = evt.target; // turn the pointer-events back on, so we can grab this item later DragTarget.setAttributeNS(null, 'pointer-events', 'all'); if ( 'BackDrop1' == targetElement.parentNode.id ) { // if the dragged element is dropped on an element that is a child // of the folder group, it is inserted as a child of that group targetElement.parentNode.appendChild( DragTarget ); alert(DragTarget.id + ' has been dropped into a folder, and has been inserted as a child of the containing group.'); } else { // for this example, you cannot drag an item out of the folder once it in there; // however, you could just as easily do so here // alert(DragTarget.id + ' has been dropped on top of ' + targetElement.id); if( 'bin' == targetElement.id ) { //targetElement.parentNode.appendChild( DragTarget ); var ch=SVGDocument.getElementById(DragTarget.id); var pa=ch.parentNode; pa.removeChild(ch); } } // set the global variable to null, so nothing will be dragged until we // grab the next element DragTarget = null; } }; function GetTrueCoords(evt) { // find the current zoom level and pan setting, and adjust the reported // mouse position accordingly var newScale = SVGRoot.currentScale; var translation = SVGRoot.currentTranslate; TrueCoords.x = (evt.clientX - translation.x)/newScale; TrueCoords.y = (evt.clientY - translation.y)/newScale; }; ]]></script> </svg> 
+4
source share
1 answer

Ok, I wrote a binding function:

 function snap(value, gridSize, roundFunction) { if (roundFunction === undefined) roundFunction = Math.round; return gridSize * roundFunction(value / gridSize); } alert(snap(14, 10)); alert(snap(16, 10)); 

Perhaps this will help you. What will he do? the latch (14, 10) will snap “14” to a grid with a length of 10. The nearest grid is 10 (14 - 10 = 4, 20 - 14 = 6). But "16" will be tied to "20".

Regards, Kevin

+7
source

Source: https://habr.com/ru/post/1333014/


All Articles