How would you create a jQuery / svg click-drag outline effect?

Not sure what to call it, but I'm looking for a way to create a point highlight / highlight effect using javascript / svg when you click and drag an area and then go to mouseUp (this can be added if this is not the original part).

The jQuery library would be nice if it existed. I looked around a bit and did not find exactly what I was looking for. I assume that the theory will receive coordination from the first click, track the coordinates of the mouse and adjust the field accordingly.

But not writing it from scratch would be nice.

+6
source share
2 answers

Here is the demo I made for you :)

Demo (static): http://jsfiddle.net/HNH2f/1/

Demo (animated): http://jsfiddle.net/HNH2f/2/

You can use CSS to control the visual style of the selection area. You can pass one or two functions to the trackMarquee method; both will be called with four arguments: the borders x1, y1, x2, y2 of the selection area. The first function will be called when the selection is highlighted. The second function (if any) will be called every time you move the step (so that you can, for example, calculate which elements are in this bounding box).

When you start dragging an SVG document (or any item that you select to track), it will create <rect class="marquee" /> ; when dragging, it will adjust the size of the rectangle. Use CSS (as shown in the demo) to create this rectangle as you want. I use the stroke-dasharray property to make the border dotted.

For posterity, here is the code (for accidentally disabling JSFiddle):

 (function createMarquee(global){ var svgNS = 'http://www.w3.org/2000/svg', svg = document.createElementNS(svgNS,'svg'), pt = svg.createSVGPoint(); // Usage: trackMarquee( mySVG, function(x1,y1,x2,y2){}, function(x1,y1,x2,y2){} ); // The first function (if present) will be called when the marquee is released // The second function (if present) will be called as the marquee is changed // Use the CSS selector `rect.marquee` to select the marquee for visual styling global.trackMarquee = function(forElement,onRelease,onDrag){ forElement.addEventListener('mousedown',function(evt){ var point0 = getLocalCoordinatesFromMouseEvent(forElement,evt); var marquee = document.createElementNS(svgNS,'rect'); marquee.setAttribute('class','marquee'); updateMarquee(marquee,point0,point0); forElement.appendChild(marquee); document.documentElement.addEventListener('mousemove',trackMouseMove,false); document.documentElement.addEventListener('mouseup',stopTrackingMove,false); function trackMouseMove(evt){ var point1 = getLocalCoordinatesFromMouseEvent(forElement,evt); updateMarquee(marquee,point0,point1); if (onDrag) callWithBBox(onDrag,marquee); } function stopTrackingMove(){ document.documentElement.removeEventListener('mousemove',trackMouseMove,false); document.documentElement.removeEventListener('mouseup',stopTrackingMove,false); forElement.removeChild(marquee); if (onRelease) callWithBBox(onRelease,marquee); } },false); }; function callWithBBox(func,rect){ var x = rect.getAttribute('x')*1, y = rect.getAttribute('y')*1, w = rect.getAttribute('width')*1, h = rect.getAttribute('height')*1; func(x,y,x+w,y+h); } function updateMarquee(rect,p0,p1){ var xs = [p0.x,p1.x].sort(sortByNumber), ys = [p0.y,p1.y].sort(sortByNumber); rect.setAttribute('x',xs[0]); rect.setAttribute('y',ys[0]); rect.setAttribute('width', xs[1]-xs[0]); rect.setAttribute('height',ys[1]-ys[0]); } function getLocalCoordinatesFromMouseEvent(el,evt){ pt.x = evt.clientX; pt.y = evt.clientY; return pt.matrixTransform(el.getScreenCTM().inverse()); } function sortByNumber(a,b){ return ab } })(window); 
+15
source

You are lucky that I just did it myself. I am using jQuery SVG plugin ( http://keith-wood.name/svg.html )

 $("#paper2").mousedown(function(ev) { ev.preventDefault(); var pX= (ev.pageX - this.offsetLeft) * viewBox[2]/parseInt($("#paper2").css("width")); var pY= (ev.pageY - this.offsetTop) * viewBox[3]/parseInt($("#paper2").css("height")); var rect = svg2.rect( pX, //X pY, //Y 1,1, //width and height { //Settings, you can make the box dotted here fill: 'black', "fill-opacity": 0.3, stroke: 'red', strokeWidth: 3, id:rect } ) $("#paper2").mousemove(function(ev) { ev.preventDefault(); var rect= $('#rect'); var pX= (ev.pageX - this.offsetLeft) * viewBox[2]/parseInt($("#paper2").css("width")) - rect.attr("x"); var pY= (ev.pageY - this.offsetTop) * viewBox[3]/parseInt($("#paper2").css("height")) - rect.attr("y"); rect.attr("width", pX); rect.attr("height", pY); }); $("#paper2").mouseup(function(ev) { ev.preventDefault(); var div= $("#paper2"); div.unbind('mousemove'); div.unbind('mouseup'); }) }); 

paper2 is the div in which I have the svg element (so the svg element and div have the same height / width). This is how I created the svg2 element:

 var svg2; var root2; $(document).ready(function() { $("#paper2").svg({ onLoad: function() { svg2= $("#paper2").svg('get'); svg2.configure({id: 'svg2'}); var div= $("#paper2"); root2= svg2.root(); $("#svg2").attr("viewBox", viewBox[0]+','+viewBox[1]+','+viewBox[2]+','+viewBox[3]); }, settings: {} }); } 

If you are not using viewbox on the svg element, you do not need this in calculations:

  * viewBox[2]/parseInt($("#paper2").css("*****")); 

viewbox [2] will be the width of the viewport, and viewbox [3] will be the height of the viewbox.

+4
source

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


All Articles