javascript - How do you create an SVG cursor-tracking element? -
i have following xml code create svg image has little circle follows user's cursor around. area tracks cursor , displays circle doesn't line rest of image. not sure why is. love enlighten me (i started learning svgs couple days ago).
if change preserveaspectratio xmidymin none circle has different set of problems. doesn't follow cursor far down , goes farther right should.
also, not javascript, if see ways code can simplified or if can figure out how switch on jquery, appreciate that.
<?xml version="1.0" encoding="utf-8" standalone="no" ?> <!doctype svg public "-//w3c//dtd svg 20010904//en" "http://www.w3.org/tr/2001/rec-svg-20010904/dtd/svg10.dtd" [ <!attlist svg xmlns:a3 cdata #implied a3:scriptimplementation cdata #implied> <!attlist script a3:scriptimplementation cdata #implied> ]> <svg viewbox="0 0 720 1278" preserveaspectratio="xmidymin" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a3="http://ns.adobe.com/adobesvgviewerextensions/3.0/" a3:scriptimplementation="adobe" onload="init(evt)" onzoom="updatetracker(evt)" onscroll="updatetracker(evt)" onresize="updatetracker(evt)"> <script type="text/ecmascript" a3:scriptimplementation="adobe"> <![cdata[ var elems = { tracker: false, cursor: false, trans: true, scale: true, mx: true, my: true, ux: true, uy: true }; var frame = { x_trans: 0, y_trans: 0, zoom: 1, x_scale: 1, y_scale: 1 }; function init(e) { if (window.svgdocument == null) svgdocument = e.target.ownerdocument; // find nodes id , store in elems object (var id in elems) getelement(id, elems[id]); } function getelement(id, usefirstchild) { // find node specified id var node = svgdocument.getelementbyid(id); if (usefirstchild) { // grab first child of node // used text node of tspan , text elements elems[id] = node.firstchild; } else { // not need first child use node found elems[id] = node; } } function updatetracker(e) { // top-most svg element var svgroot = svgdocument.documentelement; // current zoom , pan settings var trans = svgroot.currenttranslate; var scale = svgroot.currentscale; // determine translation needed move upper-left // corner of our tracking rectangle upper-left of // current view. // zeros used reinforce translating // origin of rectangle upper-left corner of // current view. frame.x_trans = (0.0 - trans.x) / scale; frame.y_trans = (0.0 - trans.y) / scale; // have moved rectangles corner // upper-left position, let scale rectangle fit // current view. x , y scales maintained seperately // handle possible anamorphic scaling viewbox frame.zoom = scale; frame.x_scale = 1 / scale; frame.y_scale = 1 / scale; // current viewbox var vbox = svgroot.getattributens(null, "viewbox"); if (vbox) { // have viewbox so, update our translation , scale // take viewbox account // break viewbox parameters array make life easier var params = vbox.split(/\s+/); // determine scaling viewbox // note these calculations assume outermost // svg element has height , width attributes set 100%. var h_scale = window.innerwidth / params[2]; var v_scale = window.innerheight / params[3]; // update our calculated transform frame.x_trans = frame.x_trans / h_scale + parsefloat(params[0]); frame.y_trans = frame.y_trans / v_scale + parsefloat(params[0]); frame.x_scale = frame.x_scale / h_scale; frame.y_scale = frame.y_scale / v_scale; } // apply changes tracking rectangle updatetrackertransform(); } function updatecursor(e) { // mouse x , y coordinates var x = e.clientx; var y = e.clienty; // calculate user-coordinate using scaling , // translation values calculated tracking // rectangle var nx = x * frame.x_scale + frame.x_trans; var ny = y * frame.y_scale + frame.y_trans; // update cursor position elems.cursor.setattributens(null, "cx", nx); elems.cursor.setattributens(null, "cy", ny); // update our text fields elems.mx.data = x; elems.my.data = y; elems.ux.data = nx; elems.uy.data = ny; } function updatetrackertransform() { // build text versions of translate , scale transformation var trans = "translate(" + frame.x_trans + "," + frame.y_trans + ")" var scale = "scale(" + 1 / frame.zoom + "," + 1 / frame.zoom + ")"; // apply transformation our tracking rectangle elems.tracker.setattributens(null, "transform", trans + " " + scale); // update our text fields elems.trans.data = trans; elems.scale.data = scale; }]]> </script> <!-- create cursor element --> <circle id="cursor" cx="100" cy="100" r="10" fill="orange" /> <!-- group of elements collectively refered tracker --> <g id="tracker"> <!-- draw visible rectangle show tracking area --> <rect x="0" y="0" width="100%" height="100%" fill="blue" opacity="0.25" /> <!-- - actual tracking rectangle. needed - track cursor. place "tracker" id here , remove group - , of other elements in group --> <rect x="0" y="0" width="100%" height="100%" opacity="0" onmousemove="updatecursor(evt)" /> </g> </svg>
i accidentally stumbled upon solution. there better way it?
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 720 1278"> <title>this'll great</title> <style> * { vector-effect:non-scaling-stroke } rect { fill: blue; } circle { fill:orange; opacity:0.75; } </style> <rect cx="50%" cy="0" width="720" height="1278" id="origin" /> <circle cx="50%" cy="116" r="72" id="dot" /> <script> var svg = document.documentelement, pt = svg.createsvgpoint(), dot = document.queryselector('#dot'); svg.addeventlistener('mousemove',function(evt){ var loc = cursorpoint(evt); dot.setattribute('cx',loc.x); dot.setattribute('cy',loc.y); },false); function rotateelement(el,originx,originy,towardsx,towardsy){ var degrees = math.atan2(towardsy-originy,towardsx-originx)*180/math.pi + 90; el.setattribute( 'transform', 'translate('+originx+','+originy+') translate('+(-originx)+','+(-originy)+')' ); } // point in global svg space function cursorpoint(evt){ pt.x = evt.clientx; pt.y = evt.clienty; return pt.matrixtransform(svg.getscreenctm().inverse()); } </script> </svg>
Comments
Post a Comment