1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251 |
- // svg-pan-zoom v3.6.2
- // https://github.com/bumbu/svg-pan-zoom
- (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
- var SvgUtils = require("./svg-utilities");
- module.exports = {
- enable: function(instance) {
- // Select (and create if necessary) defs
- var defs = instance.svg.querySelector("defs");
- if (!defs) {
- defs = document.createElementNS(SvgUtils.svgNS, "defs");
- instance.svg.appendChild(defs);
- }
- // Check for style element, and create it if it doesn't exist
- var styleEl = defs.querySelector("style#svg-pan-zoom-controls-styles");
- if (!styleEl) {
- var style = document.createElementNS(SvgUtils.svgNS, "style");
- style.setAttribute("id", "svg-pan-zoom-controls-styles");
- style.setAttribute("type", "text/css");
- style.textContent =
- ".svg-pan-zoom-control { cursor: pointer; fill: black; fill-opacity: 0.333; } .svg-pan-zoom-control:hover { fill-opacity: 0.8; } .svg-pan-zoom-control-background { fill: white; fill-opacity: 0.5; } .svg-pan-zoom-control-background { fill-opacity: 0.8; }";
- defs.appendChild(style);
- }
- // Zoom Group
- var zoomGroup = document.createElementNS(SvgUtils.svgNS, "g");
- zoomGroup.setAttribute("id", "svg-pan-zoom-controls");
- zoomGroup.setAttribute(
- "transform",
- "translate(" +
- (instance.width - 70) +
- " " +
- (instance.height - 76) +
- ") scale(0.75)"
- );
- zoomGroup.setAttribute("class", "svg-pan-zoom-control");
- // Control elements
- zoomGroup.appendChild(this._createZoomIn(instance));
- zoomGroup.appendChild(this._createZoomReset(instance));
- zoomGroup.appendChild(this._createZoomOut(instance));
- // Finally append created element
- instance.svg.appendChild(zoomGroup);
- // Cache control instance
- instance.controlIcons = zoomGroup;
- },
- _createZoomIn: function(instance) {
- var zoomIn = document.createElementNS(SvgUtils.svgNS, "g");
- zoomIn.setAttribute("id", "svg-pan-zoom-zoom-in");
- zoomIn.setAttribute("transform", "translate(30.5 5) scale(0.015)");
- zoomIn.setAttribute("class", "svg-pan-zoom-control");
- zoomIn.addEventListener(
- "click",
- function() {
- instance.getPublicInstance().zoomIn();
- },
- false
- );
- zoomIn.addEventListener(
- "touchstart",
- function() {
- instance.getPublicInstance().zoomIn();
- },
- false
- );
- var zoomInBackground = document.createElementNS(SvgUtils.svgNS, "rect"); // TODO change these background space fillers to rounded rectangles so they look prettier
- zoomInBackground.setAttribute("x", "0");
- zoomInBackground.setAttribute("y", "0");
- zoomInBackground.setAttribute("width", "1500"); // larger than expected because the whole group is transformed to scale down
- zoomInBackground.setAttribute("height", "1400");
- zoomInBackground.setAttribute("class", "svg-pan-zoom-control-background");
- zoomIn.appendChild(zoomInBackground);
- var zoomInShape = document.createElementNS(SvgUtils.svgNS, "path");
- zoomInShape.setAttribute(
- "d",
- "M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z"
- );
- zoomInShape.setAttribute("class", "svg-pan-zoom-control-element");
- zoomIn.appendChild(zoomInShape);
- return zoomIn;
- },
- _createZoomReset: function(instance) {
- // reset
- var resetPanZoomControl = document.createElementNS(SvgUtils.svgNS, "g");
- resetPanZoomControl.setAttribute("id", "svg-pan-zoom-reset-pan-zoom");
- resetPanZoomControl.setAttribute("transform", "translate(5 35) scale(0.4)");
- resetPanZoomControl.setAttribute("class", "svg-pan-zoom-control");
- resetPanZoomControl.addEventListener(
- "click",
- function() {
- instance.getPublicInstance().reset();
- },
- false
- );
- resetPanZoomControl.addEventListener(
- "touchstart",
- function() {
- instance.getPublicInstance().reset();
- },
- false
- );
- var resetPanZoomControlBackground = document.createElementNS(
- SvgUtils.svgNS,
- "rect"
- ); // TODO change these background space fillers to rounded rectangles so they look prettier
- resetPanZoomControlBackground.setAttribute("x", "2");
- resetPanZoomControlBackground.setAttribute("y", "2");
- resetPanZoomControlBackground.setAttribute("width", "182"); // larger than expected because the whole group is transformed to scale down
- resetPanZoomControlBackground.setAttribute("height", "58");
- resetPanZoomControlBackground.setAttribute(
- "class",
- "svg-pan-zoom-control-background"
- );
- resetPanZoomControl.appendChild(resetPanZoomControlBackground);
- var resetPanZoomControlShape1 = document.createElementNS(
- SvgUtils.svgNS,
- "path"
- );
- resetPanZoomControlShape1.setAttribute(
- "d",
- "M33.051,20.632c-0.742-0.406-1.854-0.609-3.338-0.609h-7.969v9.281h7.769c1.543,0,2.701-0.188,3.473-0.562c1.365-0.656,2.048-1.953,2.048-3.891C35.032,22.757,34.372,21.351,33.051,20.632z"
- );
- resetPanZoomControlShape1.setAttribute(
- "class",
- "svg-pan-zoom-control-element"
- );
- resetPanZoomControl.appendChild(resetPanZoomControlShape1);
- var resetPanZoomControlShape2 = document.createElementNS(
- SvgUtils.svgNS,
- "path"
- );
- resetPanZoomControlShape2.setAttribute(
- "d",
- "M170.231,0.5H15.847C7.102,0.5,0.5,5.708,0.5,11.84v38.861C0.5,56.833,7.102,61.5,15.847,61.5h154.384c8.745,0,15.269-4.667,15.269-10.798V11.84C185.5,5.708,178.976,0.5,170.231,0.5z M42.837,48.569h-7.969c-0.219-0.766-0.375-1.383-0.469-1.852c-0.188-0.969-0.289-1.961-0.305-2.977l-0.047-3.211c-0.03-2.203-0.41-3.672-1.142-4.406c-0.732-0.734-2.103-1.102-4.113-1.102h-7.05v13.547h-7.055V14.022h16.524c2.361,0.047,4.178,0.344,5.45,0.891c1.272,0.547,2.351,1.352,3.234,2.414c0.731,0.875,1.31,1.844,1.737,2.906s0.64,2.273,0.64,3.633c0,1.641-0.414,3.254-1.242,4.84s-2.195,2.707-4.102,3.363c1.594,0.641,2.723,1.551,3.387,2.73s0.996,2.98,0.996,5.402v2.32c0,1.578,0.063,2.648,0.19,3.211c0.19,0.891,0.635,1.547,1.333,1.969V48.569z M75.579,48.569h-26.18V14.022h25.336v6.117H56.454v7.336h16.781v6H56.454v8.883h19.125V48.569z M104.497,46.331c-2.44,2.086-5.887,3.129-10.34,3.129c-4.548,0-8.125-1.027-10.731-3.082s-3.909-4.879-3.909-8.473h6.891c0.224,1.578,0.662,2.758,1.316,3.539c1.196,1.422,3.246,2.133,6.15,2.133c1.739,0,3.151-0.188,4.236-0.562c2.058-0.719,3.087-2.055,3.087-4.008c0-1.141-0.504-2.023-1.512-2.648c-1.008-0.609-2.607-1.148-4.796-1.617l-3.74-0.82c-3.676-0.812-6.201-1.695-7.576-2.648c-2.328-1.594-3.492-4.086-3.492-7.477c0-3.094,1.139-5.664,3.417-7.711s5.623-3.07,10.036-3.07c3.685,0,6.829,0.965,9.431,2.895c2.602,1.93,3.966,4.73,4.093,8.402h-6.938c-0.128-2.078-1.057-3.555-2.787-4.43c-1.154-0.578-2.587-0.867-4.301-0.867c-1.907,0-3.428,0.375-4.565,1.125c-1.138,0.75-1.706,1.797-1.706,3.141c0,1.234,0.561,2.156,1.682,2.766c0.721,0.406,2.25,0.883,4.589,1.43l6.063,1.43c2.657,0.625,4.648,1.461,5.975,2.508c2.059,1.625,3.089,3.977,3.089,7.055C108.157,41.624,106.937,44.245,104.497,46.331z M139.61,48.569h-26.18V14.022h25.336v6.117h-18.281v7.336h16.781v6h-16.781v8.883h19.125V48.569z M170.337,20.14h-10.336v28.43h-7.266V20.14h-10.383v-6.117h27.984V20.14z"
- );
- resetPanZoomControlShape2.setAttribute(
- "class",
- "svg-pan-zoom-control-element"
- );
- resetPanZoomControl.appendChild(resetPanZoomControlShape2);
- return resetPanZoomControl;
- },
- _createZoomOut: function(instance) {
- // zoom out
- var zoomOut = document.createElementNS(SvgUtils.svgNS, "g");
- zoomOut.setAttribute("id", "svg-pan-zoom-zoom-out");
- zoomOut.setAttribute("transform", "translate(30.5 70) scale(0.015)");
- zoomOut.setAttribute("class", "svg-pan-zoom-control");
- zoomOut.addEventListener(
- "click",
- function() {
- instance.getPublicInstance().zoomOut();
- },
- false
- );
- zoomOut.addEventListener(
- "touchstart",
- function() {
- instance.getPublicInstance().zoomOut();
- },
- false
- );
- var zoomOutBackground = document.createElementNS(SvgUtils.svgNS, "rect"); // TODO change these background space fillers to rounded rectangles so they look prettier
- zoomOutBackground.setAttribute("x", "0");
- zoomOutBackground.setAttribute("y", "0");
- zoomOutBackground.setAttribute("width", "1500"); // larger than expected because the whole group is transformed to scale down
- zoomOutBackground.setAttribute("height", "1400");
- zoomOutBackground.setAttribute("class", "svg-pan-zoom-control-background");
- zoomOut.appendChild(zoomOutBackground);
- var zoomOutShape = document.createElementNS(SvgUtils.svgNS, "path");
- zoomOutShape.setAttribute(
- "d",
- "M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z"
- );
- zoomOutShape.setAttribute("class", "svg-pan-zoom-control-element");
- zoomOut.appendChild(zoomOutShape);
- return zoomOut;
- },
- disable: function(instance) {
- if (instance.controlIcons) {
- instance.controlIcons.parentNode.removeChild(instance.controlIcons);
- instance.controlIcons = null;
- }
- }
- };
- },{"./svg-utilities":5}],2:[function(require,module,exports){
- var SvgUtils = require("./svg-utilities"),
- Utils = require("./utilities");
- var ShadowViewport = function(viewport, options) {
- this.init(viewport, options);
- };
- /**
- * Initialization
- *
- * @param {SVGElement} viewport
- * @param {Object} options
- */
- ShadowViewport.prototype.init = function(viewport, options) {
- // DOM Elements
- this.viewport = viewport;
- this.options = options;
- // State cache
- this.originalState = { zoom: 1, x: 0, y: 0 };
- this.activeState = { zoom: 1, x: 0, y: 0 };
- this.updateCTMCached = Utils.proxy(this.updateCTM, this);
- // Create a custom requestAnimationFrame taking in account refreshRate
- this.requestAnimationFrame = Utils.createRequestAnimationFrame(
- this.options.refreshRate
- );
- // ViewBox
- this.viewBox = { x: 0, y: 0, width: 0, height: 0 };
- this.cacheViewBox();
- // Process CTM
- var newCTM = this.processCTM();
- // Update viewport CTM and cache zoom and pan
- this.setCTM(newCTM);
- // Update CTM in this frame
- this.updateCTM();
- };
- /**
- * Cache initial viewBox value
- * If no viewBox is defined, then use viewport size/position instead for viewBox values
- */
- ShadowViewport.prototype.cacheViewBox = function() {
- var svgViewBox = this.options.svg.getAttribute("viewBox");
- if (svgViewBox) {
- var viewBoxValues = svgViewBox
- .split(/[\s\,]/)
- .filter(function(v) {
- return v;
- })
- .map(parseFloat);
- // Cache viewbox x and y offset
- this.viewBox.x = viewBoxValues[0];
- this.viewBox.y = viewBoxValues[1];
- this.viewBox.width = viewBoxValues[2];
- this.viewBox.height = viewBoxValues[3];
- var zoom = Math.min(
- this.options.width / this.viewBox.width,
- this.options.height / this.viewBox.height
- );
- // Update active state
- this.activeState.zoom = zoom;
- this.activeState.x = (this.options.width - this.viewBox.width * zoom) / 2;
- this.activeState.y = (this.options.height - this.viewBox.height * zoom) / 2;
- // Force updating CTM
- this.updateCTMOnNextFrame();
- this.options.svg.removeAttribute("viewBox");
- } else {
- this.simpleViewBoxCache();
- }
- };
- /**
- * Recalculate viewport sizes and update viewBox cache
- */
- ShadowViewport.prototype.simpleViewBoxCache = function() {
- var bBox = this.viewport.getBBox();
- this.viewBox.x = bBox.x;
- this.viewBox.y = bBox.y;
- this.viewBox.width = bBox.width;
- this.viewBox.height = bBox.height;
- };
- /**
- * Returns a viewbox object. Safe to alter
- *
- * @return {Object} viewbox object
- */
- ShadowViewport.prototype.getViewBox = function() {
- return Utils.extend({}, this.viewBox);
- };
- /**
- * Get initial zoom and pan values. Save them into originalState
- * Parses viewBox attribute to alter initial sizes
- *
- * @return {CTM} CTM object based on options
- */
- ShadowViewport.prototype.processCTM = function() {
- var newCTM = this.getCTM();
- if (this.options.fit || this.options.contain) {
- var newScale;
- if (this.options.fit) {
- newScale = Math.min(
- this.options.width / this.viewBox.width,
- this.options.height / this.viewBox.height
- );
- } else {
- newScale = Math.max(
- this.options.width / this.viewBox.width,
- this.options.height / this.viewBox.height
- );
- }
- newCTM.a = newScale; //x-scale
- newCTM.d = newScale; //y-scale
- newCTM.e = -this.viewBox.x * newScale; //x-transform
- newCTM.f = -this.viewBox.y * newScale; //y-transform
- }
- if (this.options.center) {
- var offsetX =
- (this.options.width -
- (this.viewBox.width + this.viewBox.x * 2) * newCTM.a) *
- 0.5,
- offsetY =
- (this.options.height -
- (this.viewBox.height + this.viewBox.y * 2) * newCTM.a) *
- 0.5;
- newCTM.e = offsetX;
- newCTM.f = offsetY;
- }
- // Cache initial values. Based on activeState and fix+center opitons
- this.originalState.zoom = newCTM.a;
- this.originalState.x = newCTM.e;
- this.originalState.y = newCTM.f;
- return newCTM;
- };
- /**
- * Return originalState object. Safe to alter
- *
- * @return {Object}
- */
- ShadowViewport.prototype.getOriginalState = function() {
- return Utils.extend({}, this.originalState);
- };
- /**
- * Return actualState object. Safe to alter
- *
- * @return {Object}
- */
- ShadowViewport.prototype.getState = function() {
- return Utils.extend({}, this.activeState);
- };
- /**
- * Get zoom scale
- *
- * @return {Float} zoom scale
- */
- ShadowViewport.prototype.getZoom = function() {
- return this.activeState.zoom;
- };
- /**
- * Get zoom scale for pubilc usage
- *
- * @return {Float} zoom scale
- */
- ShadowViewport.prototype.getRelativeZoom = function() {
- return this.activeState.zoom / this.originalState.zoom;
- };
- /**
- * Compute zoom scale for pubilc usage
- *
- * @return {Float} zoom scale
- */
- ShadowViewport.prototype.computeRelativeZoom = function(scale) {
- return scale / this.originalState.zoom;
- };
- /**
- * Get pan
- *
- * @return {Object}
- */
- ShadowViewport.prototype.getPan = function() {
- return { x: this.activeState.x, y: this.activeState.y };
- };
- /**
- * Return cached viewport CTM value that can be safely modified
- *
- * @return {SVGMatrix}
- */
- ShadowViewport.prototype.getCTM = function() {
- var safeCTM = this.options.svg.createSVGMatrix();
- // Copy values manually as in FF they are not itterable
- safeCTM.a = this.activeState.zoom;
- safeCTM.b = 0;
- safeCTM.c = 0;
- safeCTM.d = this.activeState.zoom;
- safeCTM.e = this.activeState.x;
- safeCTM.f = this.activeState.y;
- return safeCTM;
- };
- /**
- * Set a new CTM
- *
- * @param {SVGMatrix} newCTM
- */
- ShadowViewport.prototype.setCTM = function(newCTM) {
- var willZoom = this.isZoomDifferent(newCTM),
- willPan = this.isPanDifferent(newCTM);
- if (willZoom || willPan) {
- // Before zoom
- if (willZoom) {
- // If returns false then cancel zooming
- if (
- this.options.beforeZoom(
- this.getRelativeZoom(),
- this.computeRelativeZoom(newCTM.a)
- ) === false
- ) {
- newCTM.a = newCTM.d = this.activeState.zoom;
- willZoom = false;
- } else {
- this.updateCache(newCTM);
- this.options.onZoom(this.getRelativeZoom());
- }
- }
- // Before pan
- if (willPan) {
- var preventPan = this.options.beforePan(this.getPan(), {
- x: newCTM.e,
- y: newCTM.f
- }),
- // If prevent pan is an object
- preventPanX = false,
- preventPanY = false;
- // If prevent pan is Boolean false
- if (preventPan === false) {
- // Set x and y same as before
- newCTM.e = this.getPan().x;
- newCTM.f = this.getPan().y;
- preventPanX = preventPanY = true;
- } else if (Utils.isObject(preventPan)) {
- // Check for X axes attribute
- if (preventPan.x === false) {
- // Prevent panning on x axes
- newCTM.e = this.getPan().x;
- preventPanX = true;
- } else if (Utils.isNumber(preventPan.x)) {
- // Set a custom pan value
- newCTM.e = preventPan.x;
- }
- // Check for Y axes attribute
- if (preventPan.y === false) {
- // Prevent panning on x axes
- newCTM.f = this.getPan().y;
- preventPanY = true;
- } else if (Utils.isNumber(preventPan.y)) {
- // Set a custom pan value
- newCTM.f = preventPan.y;
- }
- }
- // Update willPan flag
- // Check if newCTM is still different
- if ((preventPanX && preventPanY) || !this.isPanDifferent(newCTM)) {
- willPan = false;
- } else {
- this.updateCache(newCTM);
- this.options.onPan(this.getPan());
- }
- }
- // Check again if should zoom or pan
- if (willZoom || willPan) {
- this.updateCTMOnNextFrame();
- }
- }
- };
- ShadowViewport.prototype.isZoomDifferent = function(newCTM) {
- return this.activeState.zoom !== newCTM.a;
- };
- ShadowViewport.prototype.isPanDifferent = function(newCTM) {
- return this.activeState.x !== newCTM.e || this.activeState.y !== newCTM.f;
- };
- /**
- * Update cached CTM and active state
- *
- * @param {SVGMatrix} newCTM
- */
- ShadowViewport.prototype.updateCache = function(newCTM) {
- this.activeState.zoom = newCTM.a;
- this.activeState.x = newCTM.e;
- this.activeState.y = newCTM.f;
- };
- ShadowViewport.prototype.pendingUpdate = false;
- /**
- * Place a request to update CTM on next Frame
- */
- ShadowViewport.prototype.updateCTMOnNextFrame = function() {
- if (!this.pendingUpdate) {
- // Lock
- this.pendingUpdate = true;
- // Throttle next update
- this.requestAnimationFrame.call(window, this.updateCTMCached);
- }
- };
- /**
- * Update viewport CTM with cached CTM
- */
- ShadowViewport.prototype.updateCTM = function() {
- var ctm = this.getCTM();
- // Updates SVG element
- SvgUtils.setCTM(this.viewport, ctm, this.defs);
- // Free the lock
- this.pendingUpdate = false;
- // Notify about the update
- if (this.options.onUpdatedCTM) {
- this.options.onUpdatedCTM(ctm);
- }
- };
- module.exports = function(viewport, options) {
- return new ShadowViewport(viewport, options);
- };
- },{"./svg-utilities":5,"./utilities":7}],3:[function(require,module,exports){
- var svgPanZoom = require("./svg-pan-zoom.js");
- // UMD module definition
- (function(window, document) {
- // AMD
- if (typeof define === "function" && define.amd) {
- define("svg-pan-zoom", function() {
- return svgPanZoom;
- });
- // CMD
- } else if (typeof module !== "undefined" && module.exports) {
- module.exports = svgPanZoom;
- // Browser
- // Keep exporting globally as module.exports is available because of browserify
- window.svgPanZoom = svgPanZoom;
- }
- })(window, document);
- },{"./svg-pan-zoom.js":4}],4:[function(require,module,exports){
- var Wheel = require("./uniwheel"),
- ControlIcons = require("./control-icons"),
- Utils = require("./utilities"),
- SvgUtils = require("./svg-utilities"),
- ShadowViewport = require("./shadow-viewport");
- var SvgPanZoom = function(svg, options) {
- this.init(svg, options);
- };
- var optionsDefaults = {
- viewportSelector: ".svg-pan-zoom_viewport", // Viewport selector. Can be querySelector string or SVGElement
- panEnabled: true, // enable or disable panning (default enabled)
- controlIconsEnabled: false, // insert icons to give user an option in addition to mouse events to control pan/zoom (default disabled)
- zoomEnabled: true, // enable or disable zooming (default enabled)
- dblClickZoomEnabled: true, // enable or disable zooming by double clicking (default enabled)
- mouseWheelZoomEnabled: true, // enable or disable zooming by mouse wheel (default enabled)
- preventMouseEventsDefault: true, // enable or disable preventDefault for mouse events
- zoomScaleSensitivity: 0.1, // Zoom sensitivity
- minZoom: 0.5, // Minimum Zoom level
- maxZoom: 10, // Maximum Zoom level
- fit: true, // enable or disable viewport fit in SVG (default true)
- contain: false, // enable or disable viewport contain the svg (default false)
- center: true, // enable or disable viewport centering in SVG (default true)
- refreshRate: "auto", // Maximum number of frames per second (altering SVG's viewport)
- beforeZoom: null,
- onZoom: null,
- beforePan: null,
- onPan: null,
- customEventsHandler: null,
- eventsListenerElement: null,
- onUpdatedCTM: null
- };
- var passiveListenerOption = { passive: true };
- SvgPanZoom.prototype.init = function(svg, options) {
- var that = this;
- this.svg = svg;
- this.defs = svg.querySelector("defs");
- // Add default attributes to SVG
- SvgUtils.setupSvgAttributes(this.svg);
- // Set options
- this.options = Utils.extend(Utils.extend({}, optionsDefaults), options);
- // Set default state
- this.state = "none";
- // Get dimensions
- var boundingClientRectNormalized = SvgUtils.getBoundingClientRectNormalized(
- svg
- );
- this.width = boundingClientRectNormalized.width;
- this.height = boundingClientRectNormalized.height;
- // Init shadow viewport
- this.viewport = ShadowViewport(
- SvgUtils.getOrCreateViewport(this.svg, this.options.viewportSelector),
- {
- svg: this.svg,
- width: this.width,
- height: this.height,
- fit: this.options.fit,
- contain: this.options.contain,
- center: this.options.center,
- refreshRate: this.options.refreshRate,
- // Put callbacks into functions as they can change through time
- beforeZoom: function(oldScale, newScale) {
- if (that.viewport && that.options.beforeZoom) {
- return that.options.beforeZoom(oldScale, newScale);
- }
- },
- onZoom: function(scale) {
- if (that.viewport && that.options.onZoom) {
- return that.options.onZoom(scale);
- }
- },
- beforePan: function(oldPoint, newPoint) {
- if (that.viewport && that.options.beforePan) {
- return that.options.beforePan(oldPoint, newPoint);
- }
- },
- onPan: function(point) {
- if (that.viewport && that.options.onPan) {
- return that.options.onPan(point);
- }
- },
- onUpdatedCTM: function(ctm) {
- if (that.viewport && that.options.onUpdatedCTM) {
- return that.options.onUpdatedCTM(ctm);
- }
- }
- }
- );
- // Wrap callbacks into public API context
- var publicInstance = this.getPublicInstance();
- publicInstance.setBeforeZoom(this.options.beforeZoom);
- publicInstance.setOnZoom(this.options.onZoom);
- publicInstance.setBeforePan(this.options.beforePan);
- publicInstance.setOnPan(this.options.onPan);
- publicInstance.setOnUpdatedCTM(this.options.onUpdatedCTM);
- if (this.options.controlIconsEnabled) {
- ControlIcons.enable(this);
- }
- // Init events handlers
- this.lastMouseWheelEventTime = Date.now();
- this.setupHandlers();
- };
- /**
- * Register event handlers
- */
- SvgPanZoom.prototype.setupHandlers = function() {
- var that = this,
- prevEvt = null; // use for touchstart event to detect double tap
- this.eventListeners = {
- // Mouse down group
- mousedown: function(evt) {
- var result = that.handleMouseDown(evt, prevEvt);
- prevEvt = evt;
- return result;
- },
- touchstart: function(evt) {
- var result = that.handleMouseDown(evt, prevEvt);
- prevEvt = evt;
- return result;
- },
- // Mouse up group
- mouseup: function(evt) {
- return that.handleMouseUp(evt);
- },
- touchend: function(evt) {
- return that.handleMouseUp(evt);
- },
- // Mouse move group
- mousemove: function(evt) {
- return that.handleMouseMove(evt);
- },
- touchmove: function(evt) {
- return that.handleMouseMove(evt);
- },
- // Mouse leave group
- mouseleave: function(evt) {
- return that.handleMouseUp(evt);
- },
- touchleave: function(evt) {
- return that.handleMouseUp(evt);
- },
- touchcancel: function(evt) {
- return that.handleMouseUp(evt);
- }
- };
- // Init custom events handler if available
- // eslint-disable-next-line eqeqeq
- if (this.options.customEventsHandler != null) {
- this.options.customEventsHandler.init({
- svgElement: this.svg,
- eventsListenerElement: this.options.eventsListenerElement,
- instance: this.getPublicInstance()
- });
- // Custom event handler may halt builtin listeners
- var haltEventListeners = this.options.customEventsHandler
- .haltEventListeners;
- if (haltEventListeners && haltEventListeners.length) {
- for (var i = haltEventListeners.length - 1; i >= 0; i--) {
- if (this.eventListeners.hasOwnProperty(haltEventListeners[i])) {
- delete this.eventListeners[haltEventListeners[i]];
- }
- }
- }
- }
- // Bind eventListeners
- for (var event in this.eventListeners) {
- // Attach event to eventsListenerElement or SVG if not available
- (this.options.eventsListenerElement || this.svg).addEventListener(
- event,
- this.eventListeners[event],
- !this.options.preventMouseEventsDefault ? passiveListenerOption : false
- );
- }
- // Zoom using mouse wheel
- if (this.options.mouseWheelZoomEnabled) {
- this.options.mouseWheelZoomEnabled = false; // set to false as enable will set it back to true
- this.enableMouseWheelZoom();
- }
- };
- /**
- * Enable ability to zoom using mouse wheel
- */
- SvgPanZoom.prototype.enableMouseWheelZoom = function() {
- if (!this.options.mouseWheelZoomEnabled) {
- var that = this;
- // Mouse wheel listener
- this.wheelListener = function(evt) {
- return that.handleMouseWheel(evt);
- };
- // Bind wheelListener
- var isPassiveListener = !this.options.preventMouseEventsDefault;
- Wheel.on(
- this.options.eventsListenerElement || this.svg,
- this.wheelListener,
- isPassiveListener
- );
- this.options.mouseWheelZoomEnabled = true;
- }
- };
- /**
- * Disable ability to zoom using mouse wheel
- */
- SvgPanZoom.prototype.disableMouseWheelZoom = function() {
- if (this.options.mouseWheelZoomEnabled) {
- var isPassiveListener = !this.options.preventMouseEventsDefault;
- Wheel.off(
- this.options.eventsListenerElement || this.svg,
- this.wheelListener,
- isPassiveListener
- );
- this.options.mouseWheelZoomEnabled = false;
- }
- };
- /**
- * Handle mouse wheel event
- *
- * @param {Event} evt
- */
- SvgPanZoom.prototype.handleMouseWheel = function(evt) {
- if (!this.options.zoomEnabled || this.state !== "none") {
- return;
- }
- if (this.options.preventMouseEventsDefault) {
- if (evt.preventDefault) {
- evt.preventDefault();
- } else {
- evt.returnValue = false;
- }
- }
- // Default delta in case that deltaY is not available
- var delta = evt.deltaY || 1,
- timeDelta = Date.now() - this.lastMouseWheelEventTime,
- divider = 3 + Math.max(0, 30 - timeDelta);
- // Update cache
- this.lastMouseWheelEventTime = Date.now();
- // Make empirical adjustments for browsers that give deltaY in pixels (deltaMode=0)
- if ("deltaMode" in evt && evt.deltaMode === 0 && evt.wheelDelta) {
- delta = evt.deltaY === 0 ? 0 : Math.abs(evt.wheelDelta) / evt.deltaY;
- }
- delta =
- -0.3 < delta && delta < 0.3
- ? delta
- : ((delta > 0 ? 1 : -1) * Math.log(Math.abs(delta) + 10)) / divider;
- var inversedScreenCTM = this.svg.getScreenCTM().inverse(),
- relativeMousePoint = SvgUtils.getEventPoint(evt, this.svg).matrixTransform(
- inversedScreenCTM
- ),
- zoom = Math.pow(1 + this.options.zoomScaleSensitivity, -1 * delta); // multiplying by neg. 1 so as to make zoom in/out behavior match Google maps behavior
- this.zoomAtPoint(zoom, relativeMousePoint);
- };
- /**
- * Zoom in at a SVG point
- *
- * @param {SVGPoint} point
- * @param {Float} zoomScale Number representing how much to zoom
- * @param {Boolean} zoomAbsolute Default false. If true, zoomScale is treated as an absolute value.
- * Otherwise, zoomScale is treated as a multiplied (e.g. 1.10 would zoom in 10%)
- */
- SvgPanZoom.prototype.zoomAtPoint = function(zoomScale, point, zoomAbsolute) {
- var originalState = this.viewport.getOriginalState();
- if (!zoomAbsolute) {
- // Fit zoomScale in set bounds
- if (
- this.getZoom() * zoomScale <
- this.options.minZoom * originalState.zoom
- ) {
- zoomScale = (this.options.minZoom * originalState.zoom) / this.getZoom();
- } else if (
- this.getZoom() * zoomScale >
- this.options.maxZoom * originalState.zoom
- ) {
- zoomScale = (this.options.maxZoom * originalState.zoom) / this.getZoom();
- }
- } else {
- // Fit zoomScale in set bounds
- zoomScale = Math.max(
- this.options.minZoom * originalState.zoom,
- Math.min(this.options.maxZoom * originalState.zoom, zoomScale)
- );
- // Find relative scale to achieve desired scale
- zoomScale = zoomScale / this.getZoom();
- }
- var oldCTM = this.viewport.getCTM(),
- relativePoint = point.matrixTransform(oldCTM.inverse()),
- modifier = this.svg
- .createSVGMatrix()
- .translate(relativePoint.x, relativePoint.y)
- .scale(zoomScale)
- .translate(-relativePoint.x, -relativePoint.y),
- newCTM = oldCTM.multiply(modifier);
- if (newCTM.a !== oldCTM.a) {
- this.viewport.setCTM(newCTM);
- }
- };
- /**
- * Zoom at center point
- *
- * @param {Float} scale
- * @param {Boolean} absolute Marks zoom scale as relative or absolute
- */
- SvgPanZoom.prototype.zoom = function(scale, absolute) {
- this.zoomAtPoint(
- scale,
- SvgUtils.getSvgCenterPoint(this.svg, this.width, this.height),
- absolute
- );
- };
- /**
- * Zoom used by public instance
- *
- * @param {Float} scale
- * @param {Boolean} absolute Marks zoom scale as relative or absolute
- */
- SvgPanZoom.prototype.publicZoom = function(scale, absolute) {
- if (absolute) {
- scale = this.computeFromRelativeZoom(scale);
- }
- this.zoom(scale, absolute);
- };
- /**
- * Zoom at point used by public instance
- *
- * @param {Float} scale
- * @param {SVGPoint|Object} point An object that has x and y attributes
- * @param {Boolean} absolute Marks zoom scale as relative or absolute
- */
- SvgPanZoom.prototype.publicZoomAtPoint = function(scale, point, absolute) {
- if (absolute) {
- // Transform zoom into a relative value
- scale = this.computeFromRelativeZoom(scale);
- }
- // If not a SVGPoint but has x and y then create a SVGPoint
- if (Utils.getType(point) !== "SVGPoint") {
- if ("x" in point && "y" in point) {
- point = SvgUtils.createSVGPoint(this.svg, point.x, point.y);
- } else {
- throw new Error("Given point is invalid");
- }
- }
- this.zoomAtPoint(scale, point, absolute);
- };
- /**
- * Get zoom scale
- *
- * @return {Float} zoom scale
- */
- SvgPanZoom.prototype.getZoom = function() {
- return this.viewport.getZoom();
- };
- /**
- * Get zoom scale for public usage
- *
- * @return {Float} zoom scale
- */
- SvgPanZoom.prototype.getRelativeZoom = function() {
- return this.viewport.getRelativeZoom();
- };
- /**
- * Compute actual zoom from public zoom
- *
- * @param {Float} zoom
- * @return {Float} zoom scale
- */
- SvgPanZoom.prototype.computeFromRelativeZoom = function(zoom) {
- return zoom * this.viewport.getOriginalState().zoom;
- };
- /**
- * Set zoom to initial state
- */
- SvgPanZoom.prototype.resetZoom = function() {
- var originalState = this.viewport.getOriginalState();
- this.zoom(originalState.zoom, true);
- };
- /**
- * Set pan to initial state
- */
- SvgPanZoom.prototype.resetPan = function() {
- this.pan(this.viewport.getOriginalState());
- };
- /**
- * Set pan and zoom to initial state
- */
- SvgPanZoom.prototype.reset = function() {
- this.resetZoom();
- this.resetPan();
- };
- /**
- * Handle double click event
- * See handleMouseDown() for alternate detection method
- *
- * @param {Event} evt
- */
- SvgPanZoom.prototype.handleDblClick = function(evt) {
- if (this.options.preventMouseEventsDefault) {
- if (evt.preventDefault) {
- evt.preventDefault();
- } else {
- evt.returnValue = false;
- }
- }
- // Check if target was a control button
- if (this.options.controlIconsEnabled) {
- var targetClass = evt.target.getAttribute("class") || "";
- if (targetClass.indexOf("svg-pan-zoom-control") > -1) {
- return false;
- }
- }
- var zoomFactor;
- if (evt.shiftKey) {
- zoomFactor = 1 / ((1 + this.options.zoomScaleSensitivity) * 2); // zoom out when shift key pressed
- } else {
- zoomFactor = (1 + this.options.zoomScaleSensitivity) * 2;
- }
- var point = SvgUtils.getEventPoint(evt, this.svg).matrixTransform(
- this.svg.getScreenCTM().inverse()
- );
- this.zoomAtPoint(zoomFactor, point);
- };
- /**
- * Handle click event
- *
- * @param {Event} evt
- */
- SvgPanZoom.prototype.handleMouseDown = function(evt, prevEvt) {
- if (this.options.preventMouseEventsDefault) {
- if (evt.preventDefault) {
- evt.preventDefault();
- } else {
- evt.returnValue = false;
- }
- }
- Utils.mouseAndTouchNormalize(evt, this.svg);
- // Double click detection; more consistent than ondblclick
- if (this.options.dblClickZoomEnabled && Utils.isDblClick(evt, prevEvt)) {
- this.handleDblClick(evt);
- } else {
- // Pan mode
- this.state = "pan";
- this.firstEventCTM = this.viewport.getCTM();
- this.stateOrigin = SvgUtils.getEventPoint(evt, this.svg).matrixTransform(
- this.firstEventCTM.inverse()
- );
- }
- };
- /**
- * Handle mouse move event
- *
- * @param {Event} evt
- */
- SvgPanZoom.prototype.handleMouseMove = function(evt) {
- if (this.options.preventMouseEventsDefault) {
- if (evt.preventDefault) {
- evt.preventDefault();
- } else {
- evt.returnValue = false;
- }
- }
- if (this.state === "pan" && this.options.panEnabled) {
- // Pan mode
- var point = SvgUtils.getEventPoint(evt, this.svg).matrixTransform(
- this.firstEventCTM.inverse()
- ),
- viewportCTM = this.firstEventCTM.translate(
- point.x - this.stateOrigin.x,
- point.y - this.stateOrigin.y
- );
- this.viewport.setCTM(viewportCTM);
- }
- };
- /**
- * Handle mouse button release event
- *
- * @param {Event} evt
- */
- SvgPanZoom.prototype.handleMouseUp = function(evt) {
- if (this.options.preventMouseEventsDefault) {
- if (evt.preventDefault) {
- evt.preventDefault();
- } else {
- evt.returnValue = false;
- }
- }
- if (this.state === "pan") {
- // Quit pan mode
- this.state = "none";
- }
- };
- /**
- * Adjust viewport size (only) so it will fit in SVG
- * Does not center image
- */
- SvgPanZoom.prototype.fit = function() {
- var viewBox = this.viewport.getViewBox(),
- newScale = Math.min(
- this.width / viewBox.width,
- this.height / viewBox.height
- );
- this.zoom(newScale, true);
- };
- /**
- * Adjust viewport size (only) so it will contain the SVG
- * Does not center image
- */
- SvgPanZoom.prototype.contain = function() {
- var viewBox = this.viewport.getViewBox(),
- newScale = Math.max(
- this.width / viewBox.width,
- this.height / viewBox.height
- );
- this.zoom(newScale, true);
- };
- /**
- * Adjust viewport pan (only) so it will be centered in SVG
- * Does not zoom/fit/contain image
- */
- SvgPanZoom.prototype.center = function() {
- var viewBox = this.viewport.getViewBox(),
- offsetX =
- (this.width - (viewBox.width + viewBox.x * 2) * this.getZoom()) * 0.5,
- offsetY =
- (this.height - (viewBox.height + viewBox.y * 2) * this.getZoom()) * 0.5;
- this.getPublicInstance().pan({ x: offsetX, y: offsetY });
- };
- /**
- * Update content cached BorderBox
- * Use when viewport contents change
- */
- SvgPanZoom.prototype.updateBBox = function() {
- this.viewport.simpleViewBoxCache();
- };
- /**
- * Pan to a rendered position
- *
- * @param {Object} point {x: 0, y: 0}
- */
- SvgPanZoom.prototype.pan = function(point) {
- var viewportCTM = this.viewport.getCTM();
- viewportCTM.e = point.x;
- viewportCTM.f = point.y;
- this.viewport.setCTM(viewportCTM);
- };
- /**
- * Relatively pan the graph by a specified rendered position vector
- *
- * @param {Object} point {x: 0, y: 0}
- */
- SvgPanZoom.prototype.panBy = function(point) {
- var viewportCTM = this.viewport.getCTM();
- viewportCTM.e += point.x;
- viewportCTM.f += point.y;
- this.viewport.setCTM(viewportCTM);
- };
- /**
- * Get pan vector
- *
- * @return {Object} {x: 0, y: 0}
- */
- SvgPanZoom.prototype.getPan = function() {
- var state = this.viewport.getState();
- return { x: state.x, y: state.y };
- };
- /**
- * Recalculates cached svg dimensions and controls position
- */
- SvgPanZoom.prototype.resize = function() {
- // Get dimensions
- var boundingClientRectNormalized = SvgUtils.getBoundingClientRectNormalized(
- this.svg
- );
- this.width = boundingClientRectNormalized.width;
- this.height = boundingClientRectNormalized.height;
- // Recalculate original state
- var viewport = this.viewport;
- viewport.options.width = this.width;
- viewport.options.height = this.height;
- viewport.processCTM();
- // Reposition control icons by re-enabling them
- if (this.options.controlIconsEnabled) {
- this.getPublicInstance().disableControlIcons();
- this.getPublicInstance().enableControlIcons();
- }
- };
- /**
- * Unbind mouse events, free callbacks and destroy public instance
- */
- SvgPanZoom.prototype.destroy = function() {
- var that = this;
- // Free callbacks
- this.beforeZoom = null;
- this.onZoom = null;
- this.beforePan = null;
- this.onPan = null;
- this.onUpdatedCTM = null;
- // Destroy custom event handlers
- // eslint-disable-next-line eqeqeq
- if (this.options.customEventsHandler != null) {
- this.options.customEventsHandler.destroy({
- svgElement: this.svg,
- eventsListenerElement: this.options.eventsListenerElement,
- instance: this.getPublicInstance()
- });
- }
- // Unbind eventListeners
- for (var event in this.eventListeners) {
- (this.options.eventsListenerElement || this.svg).removeEventListener(
- event,
- this.eventListeners[event],
- !this.options.preventMouseEventsDefault ? passiveListenerOption : false
- );
- }
- // Unbind wheelListener
- this.disableMouseWheelZoom();
- // Remove control icons
- this.getPublicInstance().disableControlIcons();
- // Reset zoom and pan
- this.reset();
- // Remove instance from instancesStore
- instancesStore = instancesStore.filter(function(instance) {
- return instance.svg !== that.svg;
- });
- // Delete options and its contents
- delete this.options;
- // Delete viewport to make public shadow viewport functions uncallable
- delete this.viewport;
- // Destroy public instance and rewrite getPublicInstance
- delete this.publicInstance;
- delete this.pi;
- this.getPublicInstance = function() {
- return null;
- };
- };
- /**
- * Returns a public instance object
- *
- * @return {Object} Public instance object
- */
- SvgPanZoom.prototype.getPublicInstance = function() {
- var that = this;
- // Create cache
- if (!this.publicInstance) {
- this.publicInstance = this.pi = {
- // Pan
- enablePan: function() {
- that.options.panEnabled = true;
- return that.pi;
- },
- disablePan: function() {
- that.options.panEnabled = false;
- return that.pi;
- },
- isPanEnabled: function() {
- return !!that.options.panEnabled;
- },
- pan: function(point) {
- that.pan(point);
- return that.pi;
- },
- panBy: function(point) {
- that.panBy(point);
- return that.pi;
- },
- getPan: function() {
- return that.getPan();
- },
- // Pan event
- setBeforePan: function(fn) {
- that.options.beforePan =
- fn === null ? null : Utils.proxy(fn, that.publicInstance);
- return that.pi;
- },
- setOnPan: function(fn) {
- that.options.onPan =
- fn === null ? null : Utils.proxy(fn, that.publicInstance);
- return that.pi;
- },
- // Zoom and Control Icons
- enableZoom: function() {
- that.options.zoomEnabled = true;
- return that.pi;
- },
- disableZoom: function() {
- that.options.zoomEnabled = false;
- return that.pi;
- },
- isZoomEnabled: function() {
- return !!that.options.zoomEnabled;
- },
- enableControlIcons: function() {
- if (!that.options.controlIconsEnabled) {
- that.options.controlIconsEnabled = true;
- ControlIcons.enable(that);
- }
- return that.pi;
- },
- disableControlIcons: function() {
- if (that.options.controlIconsEnabled) {
- that.options.controlIconsEnabled = false;
- ControlIcons.disable(that);
- }
- return that.pi;
- },
- isControlIconsEnabled: function() {
- return !!that.options.controlIconsEnabled;
- },
- // Double click zoom
- enableDblClickZoom: function() {
- that.options.dblClickZoomEnabled = true;
- return that.pi;
- },
- disableDblClickZoom: function() {
- that.options.dblClickZoomEnabled = false;
- return that.pi;
- },
- isDblClickZoomEnabled: function() {
- return !!that.options.dblClickZoomEnabled;
- },
- // Mouse wheel zoom
- enableMouseWheelZoom: function() {
- that.enableMouseWheelZoom();
- return that.pi;
- },
- disableMouseWheelZoom: function() {
- that.disableMouseWheelZoom();
- return that.pi;
- },
- isMouseWheelZoomEnabled: function() {
- return !!that.options.mouseWheelZoomEnabled;
- },
- // Zoom scale and bounds
- setZoomScaleSensitivity: function(scale) {
- that.options.zoomScaleSensitivity = scale;
- return that.pi;
- },
- setMinZoom: function(zoom) {
- that.options.minZoom = zoom;
- return that.pi;
- },
- setMaxZoom: function(zoom) {
- that.options.maxZoom = zoom;
- return that.pi;
- },
- // Zoom event
- setBeforeZoom: function(fn) {
- that.options.beforeZoom =
- fn === null ? null : Utils.proxy(fn, that.publicInstance);
- return that.pi;
- },
- setOnZoom: function(fn) {
- that.options.onZoom =
- fn === null ? null : Utils.proxy(fn, that.publicInstance);
- return that.pi;
- },
- // Zooming
- zoom: function(scale) {
- that.publicZoom(scale, true);
- return that.pi;
- },
- zoomBy: function(scale) {
- that.publicZoom(scale, false);
- return that.pi;
- },
- zoomAtPoint: function(scale, point) {
- that.publicZoomAtPoint(scale, point, true);
- return that.pi;
- },
- zoomAtPointBy: function(scale, point) {
- that.publicZoomAtPoint(scale, point, false);
- return that.pi;
- },
- zoomIn: function() {
- this.zoomBy(1 + that.options.zoomScaleSensitivity);
- return that.pi;
- },
- zoomOut: function() {
- this.zoomBy(1 / (1 + that.options.zoomScaleSensitivity));
- return that.pi;
- },
- getZoom: function() {
- return that.getRelativeZoom();
- },
- // CTM update
- setOnUpdatedCTM: function(fn) {
- that.options.onUpdatedCTM =
- fn === null ? null : Utils.proxy(fn, that.publicInstance);
- return that.pi;
- },
- // Reset
- resetZoom: function() {
- that.resetZoom();
- return that.pi;
- },
- resetPan: function() {
- that.resetPan();
- return that.pi;
- },
- reset: function() {
- that.reset();
- return that.pi;
- },
- // Fit, Contain and Center
- fit: function() {
- that.fit();
- return that.pi;
- },
- contain: function() {
- that.contain();
- return that.pi;
- },
- center: function() {
- that.center();
- return that.pi;
- },
- // Size and Resize
- updateBBox: function() {
- that.updateBBox();
- return that.pi;
- },
- resize: function() {
- that.resize();
- return that.pi;
- },
- getSizes: function() {
- return {
- width: that.width,
- height: that.height,
- realZoom: that.getZoom(),
- viewBox: that.viewport.getViewBox()
- };
- },
- // Destroy
- destroy: function() {
- that.destroy();
- return that.pi;
- }
- };
- }
- return this.publicInstance;
- };
- /**
- * Stores pairs of instances of SvgPanZoom and SVG
- * Each pair is represented by an object {svg: SVGSVGElement, instance: SvgPanZoom}
- *
- * @type {Array}
- */
- var instancesStore = [];
- var svgPanZoom = function(elementOrSelector, options) {
- var svg = Utils.getSvg(elementOrSelector);
- if (svg === null) {
- return null;
- } else {
- // Look for existent instance
- for (var i = instancesStore.length - 1; i >= 0; i--) {
- if (instancesStore[i].svg === svg) {
- return instancesStore[i].instance.getPublicInstance();
- }
- }
- // If instance not found - create one
- instancesStore.push({
- svg: svg,
- instance: new SvgPanZoom(svg, options)
- });
- // Return just pushed instance
- return instancesStore[
- instancesStore.length - 1
- ].instance.getPublicInstance();
- }
- };
- module.exports = svgPanZoom;
- },{"./control-icons":1,"./shadow-viewport":2,"./svg-utilities":5,"./uniwheel":6,"./utilities":7}],5:[function(require,module,exports){
- var Utils = require("./utilities"),
- _browser = "unknown";
- // http://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
- if (/*@cc_on!@*/ false || !!document.documentMode) {
- // internet explorer
- _browser = "ie";
- }
- module.exports = {
- svgNS: "http://www.w3.org/2000/svg",
- xmlNS: "http://www.w3.org/XML/1998/namespace",
- xmlnsNS: "http://www.w3.org/2000/xmlns/",
- xlinkNS: "http://www.w3.org/1999/xlink",
- evNS: "http://www.w3.org/2001/xml-events",
- /**
- * Get svg dimensions: width and height
- *
- * @param {SVGSVGElement} svg
- * @return {Object} {width: 0, height: 0}
- */
- getBoundingClientRectNormalized: function(svg) {
- if (svg.clientWidth && svg.clientHeight) {
- return { width: svg.clientWidth, height: svg.clientHeight };
- } else if (!!svg.getBoundingClientRect()) {
- return svg.getBoundingClientRect();
- } else {
- throw new Error("Cannot get BoundingClientRect for SVG.");
- }
- },
- /**
- * Gets g element with class of "viewport" or creates it if it doesn't exist
- *
- * @param {SVGSVGElement} svg
- * @return {SVGElement} g (group) element
- */
- getOrCreateViewport: function(svg, selector) {
- var viewport = null;
- if (Utils.isElement(selector)) {
- viewport = selector;
- } else {
- viewport = svg.querySelector(selector);
- }
- // Check if there is just one main group in SVG
- if (!viewport) {
- var childNodes = Array.prototype.slice
- .call(svg.childNodes || svg.children)
- .filter(function(el) {
- return el.nodeName !== "defs" && el.nodeName !== "#text";
- });
- // Node name should be SVGGElement and should have no transform attribute
- // Groups with transform are not used as viewport because it involves parsing of all transform possibilities
- if (
- childNodes.length === 1 &&
- childNodes[0].nodeName === "g" &&
- childNodes[0].getAttribute("transform") === null
- ) {
- viewport = childNodes[0];
- }
- }
- // If no favorable group element exists then create one
- if (!viewport) {
- var viewportId =
- "viewport-" + new Date().toISOString().replace(/\D/g, "");
- viewport = document.createElementNS(this.svgNS, "g");
- viewport.setAttribute("id", viewportId);
- // Internet Explorer (all versions?) can't use childNodes, but other browsers prefer (require?) using childNodes
- var svgChildren = svg.childNodes || svg.children;
- if (!!svgChildren && svgChildren.length > 0) {
- for (var i = svgChildren.length; i > 0; i--) {
- // Move everything into viewport except defs
- if (svgChildren[svgChildren.length - i].nodeName !== "defs") {
- viewport.appendChild(svgChildren[svgChildren.length - i]);
- }
- }
- }
- svg.appendChild(viewport);
- }
- // Parse class names
- var classNames = [];
- if (viewport.getAttribute("class")) {
- classNames = viewport.getAttribute("class").split(" ");
- }
- // Set class (if not set already)
- if (!~classNames.indexOf("svg-pan-zoom_viewport")) {
- classNames.push("svg-pan-zoom_viewport");
- viewport.setAttribute("class", classNames.join(" "));
- }
- return viewport;
- },
- /**
- * Set SVG attributes
- *
- * @param {SVGSVGElement} svg
- */
- setupSvgAttributes: function(svg) {
- // Setting default attributes
- svg.setAttribute("xmlns", this.svgNS);
- svg.setAttributeNS(this.xmlnsNS, "xmlns:xlink", this.xlinkNS);
- svg.setAttributeNS(this.xmlnsNS, "xmlns:ev", this.evNS);
- // Needed for Internet Explorer, otherwise the viewport overflows
- if (svg.parentNode !== null) {
- var style = svg.getAttribute("style") || "";
- if (style.toLowerCase().indexOf("overflow") === -1) {
- svg.setAttribute("style", "overflow: hidden; " + style);
- }
- }
- },
- /**
- * How long Internet Explorer takes to finish updating its display (ms).
- */
- internetExplorerRedisplayInterval: 300,
- /**
- * Forces the browser to redisplay all SVG elements that rely on an
- * element defined in a 'defs' section. It works globally, for every
- * available defs element on the page.
- * The throttling is intentionally global.
- *
- * This is only needed for IE. It is as a hack to make markers (and 'use' elements?)
- * visible after pan/zoom when there are multiple SVGs on the page.
- * See bug report: https://connect.microsoft.com/IE/feedback/details/781964/
- * also see svg-pan-zoom issue: https://github.com/bumbu/svg-pan-zoom/issues/62
- */
- refreshDefsGlobal: Utils.throttle(
- function() {
- var allDefs = document.querySelectorAll("defs");
- var allDefsCount = allDefs.length;
- for (var i = 0; i < allDefsCount; i++) {
- var thisDefs = allDefs[i];
- thisDefs.parentNode.insertBefore(thisDefs, thisDefs);
- }
- },
- this ? this.internetExplorerRedisplayInterval : null
- ),
- /**
- * Sets the current transform matrix of an element
- *
- * @param {SVGElement} element
- * @param {SVGMatrix} matrix CTM
- * @param {SVGElement} defs
- */
- setCTM: function(element, matrix, defs) {
- var that = this,
- s =
- "matrix(" +
- matrix.a +
- "," +
- matrix.b +
- "," +
- matrix.c +
- "," +
- matrix.d +
- "," +
- matrix.e +
- "," +
- matrix.f +
- ")";
- element.setAttributeNS(null, "transform", s);
- if ("transform" in element.style) {
- element.style.transform = s;
- } else if ("-ms-transform" in element.style) {
- element.style["-ms-transform"] = s;
- } else if ("-webkit-transform" in element.style) {
- element.style["-webkit-transform"] = s;
- }
- // IE has a bug that makes markers disappear on zoom (when the matrix "a" and/or "d" elements change)
- // see http://stackoverflow.com/questions/17654578/svg-marker-does-not-work-in-ie9-10
- // and http://srndolha.wordpress.com/2013/11/25/svg-line-markers-may-disappear-in-internet-explorer-11/
- if (_browser === "ie" && !!defs) {
- // this refresh is intended for redisplaying the SVG during zooming
- defs.parentNode.insertBefore(defs, defs);
- // this refresh is intended for redisplaying the other SVGs on a page when panning a given SVG
- // it is also needed for the given SVG itself, on zoomEnd, if the SVG contains any markers that
- // are located under any other element(s).
- window.setTimeout(function() {
- that.refreshDefsGlobal();
- }, that.internetExplorerRedisplayInterval);
- }
- },
- /**
- * Instantiate an SVGPoint object with given event coordinates
- *
- * @param {Event} evt
- * @param {SVGSVGElement} svg
- * @return {SVGPoint} point
- */
- getEventPoint: function(evt, svg) {
- var point = svg.createSVGPoint();
- Utils.mouseAndTouchNormalize(evt, svg);
- point.x = evt.clientX;
- point.y = evt.clientY;
- return point;
- },
- /**
- * Get SVG center point
- *
- * @param {SVGSVGElement} svg
- * @return {SVGPoint}
- */
- getSvgCenterPoint: function(svg, width, height) {
- return this.createSVGPoint(svg, width / 2, height / 2);
- },
- /**
- * Create a SVGPoint with given x and y
- *
- * @param {SVGSVGElement} svg
- * @param {Number} x
- * @param {Number} y
- * @return {SVGPoint}
- */
- createSVGPoint: function(svg, x, y) {
- var point = svg.createSVGPoint();
- point.x = x;
- point.y = y;
- return point;
- }
- };
- },{"./utilities":7}],6:[function(require,module,exports){
- // uniwheel 0.1.2 (customized)
- // A unified cross browser mouse wheel event handler
- // https://github.com/teemualap/uniwheel
- module.exports = (function(){
- //Full details: https://developer.mozilla.org/en-US/docs/Web/Reference/Events/wheel
- var prefix = "", _addEventListener, _removeEventListener, support, fns = [];
- var passiveListenerOption = {passive: true};
- var activeListenerOption = {passive: false};
- // detect event model
- if ( window.addEventListener ) {
- _addEventListener = "addEventListener";
- _removeEventListener = "removeEventListener";
- } else {
- _addEventListener = "attachEvent";
- _removeEventListener = "detachEvent";
- prefix = "on";
- }
- // detect available wheel event
- support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
- document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
- "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox
- function createCallback(element,callback) {
- var fn = function(originalEvent) {
- !originalEvent && ( originalEvent = window.event );
- // create a normalized event object
- var event = {
- // keep a ref to the original event object
- originalEvent: originalEvent,
- target: originalEvent.target || originalEvent.srcElement,
- type: "wheel",
- deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
- deltaX: 0,
- delatZ: 0,
- preventDefault: function() {
- originalEvent.preventDefault ?
- originalEvent.preventDefault() :
- originalEvent.returnValue = false;
- }
- };
- // calculate deltaY (and deltaX) according to the event
- if ( support == "mousewheel" ) {
- event.deltaY = - 1/40 * originalEvent.wheelDelta;
- // Webkit also support wheelDeltaX
- originalEvent.wheelDeltaX && ( event.deltaX = - 1/40 * originalEvent.wheelDeltaX );
- } else {
- event.deltaY = originalEvent.detail;
- }
- // it's time to fire the callback
- return callback( event );
- };
- fns.push({
- element: element,
- fn: fn,
- });
- return fn;
- }
- function getCallback(element) {
- for (var i = 0; i < fns.length; i++) {
- if (fns[i].element === element) {
- return fns[i].fn;
- }
- }
- return function(){};
- }
- function removeCallback(element) {
- for (var i = 0; i < fns.length; i++) {
- if (fns[i].element === element) {
- return fns.splice(i,1);
- }
- }
- }
- function _addWheelListener(elem, eventName, callback, isPassiveListener ) {
- var cb;
- if (support === "wheel") {
- cb = callback;
- } else {
- cb = createCallback(elem, callback);
- }
- elem[_addEventListener](
- prefix + eventName,
- cb,
- isPassiveListener ? passiveListenerOption : activeListenerOption
- );
- }
- function _removeWheelListener(elem, eventName, callback, isPassiveListener ) {
- var cb;
- if (support === "wheel") {
- cb = callback;
- } else {
- cb = getCallback(elem);
- }
- elem[_removeEventListener](
- prefix + eventName,
- cb,
- isPassiveListener ? passiveListenerOption : activeListenerOption
- );
- removeCallback(elem);
- }
- function addWheelListener( elem, callback, isPassiveListener ) {
- _addWheelListener(elem, support, callback, isPassiveListener );
- // handle MozMousePixelScroll in older Firefox
- if( support == "DOMMouseScroll" ) {
- _addWheelListener(elem, "MozMousePixelScroll", callback, isPassiveListener );
- }
- }
- function removeWheelListener(elem, callback, isPassiveListener){
- _removeWheelListener(elem, support, callback, isPassiveListener);
- // handle MozMousePixelScroll in older Firefox
- if( support == "DOMMouseScroll" ) {
- _removeWheelListener(elem, "MozMousePixelScroll", callback, isPassiveListener);
- }
- }
- return {
- on: addWheelListener,
- off: removeWheelListener
- };
- })();
- },{}],7:[function(require,module,exports){
- module.exports = {
- /**
- * Extends an object
- *
- * @param {Object} target object to extend
- * @param {Object} source object to take properties from
- * @return {Object} extended object
- */
- extend: function(target, source) {
- target = target || {};
- for (var prop in source) {
- // Go recursively
- if (this.isObject(source[prop])) {
- target[prop] = this.extend(target[prop], source[prop]);
- } else {
- target[prop] = source[prop];
- }
- }
- return target;
- },
- /**
- * Checks if an object is a DOM element
- *
- * @param {Object} o HTML element or String
- * @return {Boolean} returns true if object is a DOM element
- */
- isElement: function(o) {
- return (
- o instanceof HTMLElement ||
- o instanceof SVGElement ||
- o instanceof SVGSVGElement || //DOM2
- (o &&
- typeof o === "object" &&
- o !== null &&
- o.nodeType === 1 &&
- typeof o.nodeName === "string")
- );
- },
- /**
- * Checks if an object is an Object
- *
- * @param {Object} o Object
- * @return {Boolean} returns true if object is an Object
- */
- isObject: function(o) {
- return Object.prototype.toString.call(o) === "[object Object]";
- },
- /**
- * Checks if variable is Number
- *
- * @param {Integer|Float} n
- * @return {Boolean} returns true if variable is Number
- */
- isNumber: function(n) {
- return !isNaN(parseFloat(n)) && isFinite(n);
- },
- /**
- * Search for an SVG element
- *
- * @param {Object|String} elementOrSelector DOM Element or selector String
- * @return {Object|Null} SVG or null
- */
- getSvg: function(elementOrSelector) {
- var element, svg;
- if (!this.isElement(elementOrSelector)) {
- // If selector provided
- if (
- typeof elementOrSelector === "string" ||
- elementOrSelector instanceof String
- ) {
- // Try to find the element
- element = document.querySelector(elementOrSelector);
- if (!element) {
- throw new Error(
- "Provided selector did not find any elements. Selector: " +
- elementOrSelector
- );
- return null;
- }
- } else {
- throw new Error("Provided selector is not an HTML object nor String");
- return null;
- }
- } else {
- element = elementOrSelector;
- }
- if (element.tagName.toLowerCase() === "svg") {
- svg = element;
- } else {
- if (element.tagName.toLowerCase() === "object") {
- svg = element.contentDocument.documentElement;
- } else {
- if (element.tagName.toLowerCase() === "embed") {
- svg = element.getSVGDocument().documentElement;
- } else {
- if (element.tagName.toLowerCase() === "img") {
- throw new Error(
- 'Cannot script an SVG in an "img" element. Please use an "object" element or an in-line SVG.'
- );
- } else {
- throw new Error("Cannot get SVG.");
- }
- return null;
- }
- }
- }
- return svg;
- },
- /**
- * Attach a given context to a function
- * @param {Function} fn Function
- * @param {Object} context Context
- * @return {Function} Function with certain context
- */
- proxy: function(fn, context) {
- return function() {
- return fn.apply(context, arguments);
- };
- },
- /**
- * Returns object type
- * Uses toString that returns [object SVGPoint]
- * And than parses object type from string
- *
- * @param {Object} o Any object
- * @return {String} Object type
- */
- getType: function(o) {
- return Object.prototype.toString
- .apply(o)
- .replace(/^\[object\s/, "")
- .replace(/\]$/, "");
- },
- /**
- * If it is a touch event than add clientX and clientY to event object
- *
- * @param {Event} evt
- * @param {SVGSVGElement} svg
- */
- mouseAndTouchNormalize: function(evt, svg) {
- // If no clientX then fallback
- if (evt.clientX === void 0 || evt.clientX === null) {
- // Fallback
- evt.clientX = 0;
- evt.clientY = 0;
- // If it is a touch event
- if (evt.touches !== void 0 && evt.touches.length) {
- if (evt.touches[0].clientX !== void 0) {
- evt.clientX = evt.touches[0].clientX;
- evt.clientY = evt.touches[0].clientY;
- } else if (evt.touches[0].pageX !== void 0) {
- var rect = svg.getBoundingClientRect();
- evt.clientX = evt.touches[0].pageX - rect.left;
- evt.clientY = evt.touches[0].pageY - rect.top;
- }
- // If it is a custom event
- } else if (evt.originalEvent !== void 0) {
- if (evt.originalEvent.clientX !== void 0) {
- evt.clientX = evt.originalEvent.clientX;
- evt.clientY = evt.originalEvent.clientY;
- }
- }
- }
- },
- /**
- * Check if an event is a double click/tap
- * TODO: For touch gestures use a library (hammer.js) that takes in account other events
- * (touchmove and touchend). It should take in account tap duration and traveled distance
- *
- * @param {Event} evt
- * @param {Event} prevEvt Previous Event
- * @return {Boolean}
- */
- isDblClick: function(evt, prevEvt) {
- // Double click detected by browser
- if (evt.detail === 2) {
- return true;
- }
- // Try to compare events
- else if (prevEvt !== void 0 && prevEvt !== null) {
- var timeStampDiff = evt.timeStamp - prevEvt.timeStamp, // should be lower than 250 ms
- touchesDistance = Math.sqrt(
- Math.pow(evt.clientX - prevEvt.clientX, 2) +
- Math.pow(evt.clientY - prevEvt.clientY, 2)
- );
- return timeStampDiff < 250 && touchesDistance < 10;
- }
- // Nothing found
- return false;
- },
- /**
- * Returns current timestamp as an integer
- *
- * @return {Number}
- */
- now:
- Date.now ||
- function() {
- return new Date().getTime();
- },
- // From underscore.
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time. Normally, the throttled function will run
- // as much as it can, without ever going more than once per `wait` duration;
- // but if you'd like to disable the execution on the leading edge, pass
- // `{leading: false}`. To disable execution on the trailing edge, ditto.
- throttle: function(func, wait, options) {
- var that = this;
- var context, args, result;
- var timeout = null;
- var previous = 0;
- if (!options) {
- options = {};
- }
- var later = function() {
- previous = options.leading === false ? 0 : that.now();
- timeout = null;
- result = func.apply(context, args);
- if (!timeout) {
- context = args = null;
- }
- };
- return function() {
- var now = that.now();
- if (!previous && options.leading === false) {
- previous = now;
- }
- var remaining = wait - (now - previous);
- context = this; // eslint-disable-line consistent-this
- args = arguments;
- if (remaining <= 0 || remaining > wait) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- if (!timeout) {
- context = args = null;
- }
- } else if (!timeout && options.trailing !== false) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
- },
- /**
- * Create a requestAnimationFrame simulation
- *
- * @param {Number|String} refreshRate
- * @return {Function}
- */
- createRequestAnimationFrame: function(refreshRate) {
- var timeout = null;
- // Convert refreshRate to timeout
- if (refreshRate !== "auto" && refreshRate < 60 && refreshRate > 1) {
- timeout = Math.floor(1000 / refreshRate);
- }
- if (timeout === null) {
- return window.requestAnimationFrame || requestTimeout(33);
- } else {
- return requestTimeout(timeout);
- }
- }
- };
- /**
- * Create a callback that will execute after a given timeout
- *
- * @param {Function} timeout
- * @return {Function}
- */
- function requestTimeout(timeout) {
- return function(callback) {
- window.setTimeout(callback, timeout);
- };
- }
- },{}]},{},[3]);
|