<!DOCTYPE html> <html prefix="og: http://ogp.me/ns#" lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>escapegame-2022/tsubasa/blender_three.js/OrbitControls.js at master - SKIP/escapegame-2022</title> <meta property="og:title" content="escapegame-2022/tsubasa/blender_three.js/OrbitControls.js at master - SKIP/escapegame-2022" /> <meta property="og:type" content="object" /> <meta property="og:url" content="http://localhost:8880/SKIP/escapegame-2022/blob/master/tsubasa/blender_three.js/OrbitControls.js" /> <meta property="og:image" content="https://www.yatex.org/gitbucket/SKIP/_avatar" /> <link rel="icon" href="https://www.yatex.org/gitbucket/assets/common/images/gitbucket.png?20240601154850" type="image/vnd.microsoft.icon" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="https://www.yatex.org/gitbucket/assets/vendors/google-fonts/css/source-sans-pro.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/bootstrap-3.4.1/css/bootstrap.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/octicons-4.4.0/octicons.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/bootstrap-datetimepicker-4.17.44/css/bootstrap-datetimepicker.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/colorpicker/css/bootstrap-colorpicker.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/color-themes-for-google-code-prettify/github-v2.min.css?20240601154850" type="text/css" rel="stylesheet"/> <link href="https://www.yatex.org/gitbucket/assets/vendors/facebox/facebox.css?20240601154850" rel="stylesheet"/> <link href="https://www.yatex.org/gitbucket/assets/vendors/AdminLTE-2.4.2/css/AdminLTE.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/AdminLTE-2.4.2/css/skins/skin-green-light.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/font-awesome-4.7.0/css/font-awesome.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/jquery-ui/jquery-ui.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/jquery-ui/jquery-ui.structure.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/jquery-ui/jquery-ui.theme.min.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/common/css/gitbucket.css?20240601154850" rel="stylesheet"> <link href="https://www.yatex.org/gitbucket/assets/vendors/tipped/tipped.css?20240601154850" rel="stylesheet"> <script src="https://www.yatex.org/gitbucket/assets/vendors/jquery/jquery-3.5.1.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/jquery-ui/jquery-ui.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/dropzone/dropzone.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/common/js/validation.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/common/js/gitbucket.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/bootstrap-3.4.1/js/bootstrap.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/bootstrap3-typeahead/bootstrap3-typeahead.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/bootstrap-datetimepicker-4.17.44/js/moment.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/bootstrap-datetimepicker-4.17.44/js/bootstrap-datetimepicker.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/colorpicker/js/bootstrap-colorpicker.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/google-code-prettify/prettify.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/elastic/jquery.elastic.source.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/facebox/facebox.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/jquery-hotkeys/jquery.hotkeys.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/jquery-textcomplete-1.8.4/jquery.textcomplete.min.js?20240601154850"></script> <script src="https://www.yatex.org/gitbucket/assets/vendors/tipped/tipped.min.js?20240601154850"></script> <meta name="go-import" content="www.yatex.org/gitbucket/SKIP/escapegame-2022 git https://www.yatex.org/gitbucket/git/SKIP/escapegame-2022.git" /> <script src="https://www.yatex.org/gitbucket/assets/vendors/AdminLTE-2.4.2/js/adminlte.min.js?20240601154850" type="text/javascript"></script> <style type="text/css">.content, .sidebar, .skin-green-light div.main-sidebar { background: #efe; }</style> </head> <body class="skin-green-light page-load sidebar-mini "> <div class="wrapper"> <header class="main-header"> <a href="https://www.yatex.org/gitbucket/" class="logo"> <span class="logo-mini"><img src="https://www.yatex.org/gitbucket/assets/common/images/gitbucket.svg?20240601154850" alt="GitBucket" /></span> <span class="logo-lg"> <img src="https://www.yatex.org/gitbucket/assets/common/images/gitbucket.svg?20240601154850" alt="GitBucket" /> <span class="header-title strong">GitBucket</span> </span> </a> <nav class="navbar navbar-static-top" role="navigation"> <!-- Sidebar toggle button--> <a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button" title="Toggle navigation"> <span class="sr-only">Toggle navigation</span> </a> <form id="search" action="https://www.yatex.org/gitbucket/search" method="GET" class="pc navbar-form navbar-left" role="search"> <div class="form-group"> <input type="text" name="query" id="navbar-search-input" class="form-control" placeholder="Find a repository" aria-label="Search"/> </div> </form> <ul class="pc nav navbar-nav"> <li><a href="https://www.yatex.org/gitbucket/dashboard/pulls">Pull requests</a></li> <li><a href="https://www.yatex.org/gitbucket/dashboard/issues">Issues</a></li> <li><a href="https://www.yatex.org/gitbucket/gist">Snippets</a></li> </ul> <div class="navbar-custom-menu"> <ul class="nav navbar-nav"> <li class="dropdown notifications-menu"> <a class="dropdown-toggle menu" data-toggle="dropdown" href="#" aria-label="Create new…"> <i class="octicon octicon-plus" style="color: black;"></i><span class="caret" style="color: black; vertical-align: middle;"></span> </a> <ul class="dropdown-menu pull-right" style="width: auto;"> <li> <ul class="menu"> <li><a href="https://www.yatex.org/gitbucket/new">New repository</a></li> <li><a href="https://www.yatex.org/gitbucket/groups/new">New group</a></li> </ul> </li> </ul> </li> <li class="dropdown notifications-menu"> <a class="dropdown-toggle menu" data-toggle="dropdown" href="#" data-toggle="tooltip" data-placement="bottom" title="Signed is as j2311"> <img src="https://www.gravatar.com/avatar/6887b4acd79bba29f3b92ca6ba6a6d17?s=16&d=retro&r=g" class="avatar-mini" style="width: 16px; height: 16px;" alt="@j2311" /><span class="caret" style="color: black; vertical-align: middle;"></span> </a> <ul class="dropdown-menu pull-right" style="width: auto;"> <li> <ul class="menu"> <li><a href="https://www.yatex.org/gitbucket/j2311">Your profile</a></li> <li><a href="https://www.yatex.org/gitbucket/j2311/_edit">Account settings</a></li> <li><a href="https://www.yatex.org/gitbucket/signout">Sign out</a></li> </ul> </li> </ul> </li> </ul> </div> </nav> </header> <div class="main-sidebar"> <div class="sidebar"> <ul class="sidebar-menu"> <li class = "menu-item-hover active"> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022"> <i class="menu-icon octicon octicon-code"></i> <span>Files</span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/branches"> <i class="menu-icon octicon octicon-git-branch"></i> <span>Branches</span> <span class="pull-right-container"><span class="label label-primary pull-right">1</span></span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/releases"> <i class="menu-icon octicon octicon-tag"></i> <span>Releases</span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/issues"> <i class="menu-icon octicon octicon-issue-opened"></i> <span>Issues</span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/pulls"> <i class="menu-icon octicon octicon-git-pull-request"></i> <span>Pull requests</span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/issues/labels"> <i class="menu-icon octicon octicon-tag"></i> <span>Labels</span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/issues/priorities"> <i class="menu-icon octicon octicon-flame"></i> <span>Priorities</span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/issues/milestones"> <i class="menu-icon octicon octicon-milestone"></i> <span>Milestones</span> </a> </li> <li class = "menu-item-hover "> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/wiki"> <i class="menu-icon octicon octicon-book"></i> <span>Wiki</span> </a> </li> </ul> </div> </div> <div class="content-wrapper"> <div class="content body clearfix"> <div class="headbar"> <div class="container"> <div class="head"> <div class="pull-right"> <div class="btn-group" > <button class="dropdown-toggle btn btn-default btn-sm" data-toggle="dropdown"> <span class="strong" > Not watching </span> <span class="caret"></span> </button> <ul class="dropdown-menu pull-right"> <li> <a href="#" class="watch" data-id="watching"> <i class="octicon"></i> <span class="notification-label strong">Watching</span> <div class="muted small">Notify all conversations.</div> </a> </li> <li> <a href="#" class="watch" data-id="not_watching"> <i class="octicon octicon-check"></i> <span class="notification-label strong">Not watching</span> <div class="muted small">Notify when participating.</div> </a> </li> <li> <a href="#" class="watch" data-id="ignoring"> <i class="octicon"></i> <span class="notification-label strong">Ignoring</span> <div class="muted small">Never notify.</div> </a> </li> </ul> </div> <script> $(function(){ $('a.watch').click(function(){ var selected = $(this); var notification = selected.data('id'); $.post('https://www.yatex.org/gitbucket/SKIP/escapegame-2022/watch', { notification : notification }, function(){ $('a.watch i.octicon-check').removeClass('octicon-check'); $('a.watch[data-id=' + notification + '] i').addClass('octicon-check'); // Update button label var label = selected.find('span.notification-label').text().trim(); selected.parents('div.btn-group').find('button>span.strong').text(label); } ); return false; }); }); </script> <a class="btn btn-default btn-sm" href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/fork" rel="facebox"> <span class="strong"><i class="octicon octicon-repo-forked"></i>Fork</span><span class="muted">: 7</span> </a> <form id="fork-form" method="post" action="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/fork" style="display: none;"> <input type="hidden" name="account" value="j2311"/> </form> </div> <i class="mega-octicon octicon-repo"></i> <a href="https://www.yatex.org/gitbucket/SKIP">SKIP</a> / <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022" class="strong">escapegame-2022</a> </div> </div> </div> <style> .prettyprint { tab-size: 8 } </style> <div class="head"> <div class="pull-right hide-if-blame"><div class="btn-group"> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/blob/7a630f0bef6ef4e4fa22f5c34a655f7c38f16adc/tsubasa/blender_three.js/OrbitControls.js" data-hotkey="y" style="display: none;">Transfer to URL with SHA</a> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/find/master" class="btn btn-sm btn-default" data-hotkey="t">Find file</a> </div></div> <div class="line-age-legend"> <span>Newer</span> <ol> <li class="heat1"></li> <li class="heat2"></li> <li class="heat3"></li> <li class="heat4"></li> <li class="heat5"></li> <li class="heat6"></li> <li class="heat7"></li> <li class="heat8"></li> <li class="heat9"></li> <li class="heat10"></li> </ol> <span>Older</span> </div> <div id="branchCtrlWrapper" style="display:inline;"> <div class="btn-group" style="min-width: 200px;"> <button class="dropdown-toggle btn btn-default btn-sm" data-toggle="dropdown"> <span class="muted">branch:</span> <span class="strong" style="display:inline-block; vertical-align:bottom; overflow-x:hidden; max-width:200px; text-overflow:ellipsis"> master </span> <span class="caret"></span> </button> <ul class="dropdown-menu"> <li> <ul class="nav nav-tabs"> <li class="active" id="branch-control-tab-branches"><a href="javascript:void(0);" class="nav-item" id="nav-item-branches">Branches</a></li> <li id="branch-control-tab-tags"><a href="javascript:void(0);" class="nav-item" id="nav-item-tags">Tags</a></li> <li><button id="branch-control-close" class="pull-right">×</button></li> </ul> <li> <input id="branch-control-input" type="text" class="form-control input-sm dropdown-filter-input"/> </li> <li><a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/blob/master/tsubasa/blender_three.js/OrbitControls.js"> <i class="octicon octicon-check"></i> master</a></li> </li> </ul> </div> <script> $(function(){ $('#branch-control-input').parent().click(function(e) { e.stopPropagation(); }); $('#branch-control-close').click(function() { $('[data-toggle="dropdown"]').parent().removeClass('open'); }); $('#branch-control-input').keyup(function() { updateBranchControlListFilter(); }); $('.btn-group').click(function() { $('#branch-control-input').val(''); //$('.dropdown-menu li').show(); $('#create-branch').hide(); }); $('#nav-item-branches').click(function(e) { e.stopPropagation(); updateBranchControlList('branches'); }); $('#nav-item-tags').click(function(e) { e.stopPropagation(); updateBranchControlList('tags'); }); function updateBranchControlList(active) { if (active == 'branches') { $('li#branch-control-tab-branches').addClass('active'); $('li#branch-control-tab-tags').removeClass('active'); $('li.branch-control-item-branch').show(); $('li.branch-control-item-branch > a').addClass('active'); $('li.branch-control-item-tag').hide(); $('li.branch-control-item-tag > a').removeClass('active'); $('#branch-control-input').attr('placeholder', 'Find branch ...'); } else if (active == 'tags') { $('li#branch-control-tab-branches').removeClass('active'); $('li#branch-control-tab-tags').addClass('active'); $('li.branch-control-item-branch').hide(); $('li.branch-control-item-branch > a').removeClass('active'); $('li.branch-control-item-tag').show(); $('li.branch-control-item-tag > a').addClass('active'); $('#branch-control-input').attr('placeholder', 'Find tag ...'); } updateBranchControlListFilter(); } function updateBranchControlListFilter() { const inputVal = $('#branch-control-input').val(); $.each($('#branch-control-input').parent().parent().find('a.active').not('.nav-item'), function(index, elem) { if (!inputVal || !elem.text.trim() || elem.text.trim().toLowerCase().indexOf(inputVal.toLowerCase()) >= 0) { $(elem).parent().show(); } else { $(elem).parent().hide(); } }); if ($('li#branch-control-tab-branches.active').length > 0) { } } // Initialize the branch control list updateBranchControlList('branches'); }); </script> </div> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/tree/master">escapegame-2022</a> / <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/tree/master/tsubasa">tsubasa</a> / <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/tree/master/tsubasa/blender_three.js">blender_three.js</a> / OrbitControls.js </div> <div class="box-header" style="line-height: 28px;"> <img src="https://www.gravatar.com/avatar/96a94f732f7c0250e2958855bb031406?s=20&d=retro&r=g" class="avatar-mini" style="width: 20px; height: 20px;" alt="@tsubasa" /> tsubasa <span class="muted"> <span data-toggle="tooltip" title="2022-12-06 14:38:48"> on 6 Dec 2022 </span> </span> <span class="label label-default">26 KB</span> <a href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/commit/7a630f0bef6ef4e4fa22f5c34a655f7c38f16adc" class="commit-message">add</a> <div class="btn-group pull-right"> <a class="btn btn-sm btn-default" href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/raw/7a630f0bef6ef4e4fa22f5c34a655f7c38f16adc/tsubasa/blender_three.js/OrbitControls.js">Raw</a> <a class="btn btn-sm btn-default blame-action" href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/blame/7a630f0bef6ef4e4fa22f5c34a655f7c38f16adc/tsubasa/blender_three.js/OrbitControls.js" data-url="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/get-blame/7a630f0bef6ef4e4fa22f5c34a655f7c38f16adc/tsubasa/blender_three.js/OrbitControls.js" data-repository="https://www.yatex.org/gitbucket/SKIP/escapegame-2022">Blame</a> <a class="btn btn-sm btn-default" href="https://www.yatex.org/gitbucket/SKIP/escapegame-2022/commits/master/tsubasa/blender_three.js/OrbitControls.js">History</a> </div> </div> <div class="box-content-bottom"> <pre class="prettyprint linenums blob no-renderable ">( function () { // This set of controls performs orbiting, dollying (zooming), and panning. // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). // // Orbit - left mouse / touch: one-finger move // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish // Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move const _changeEvent = { type: 'change' }; const _startEvent = { type: 'start' }; const _endEvent = { type: 'end' }; class OrbitControls extends THREE.EventDispatcher { constructor( object, domElement ) { super(); this.object = object; this.domElement = domElement; this.domElement.style.touchAction = 'none'; // disable touch scroll // Set to false to disable this control this.enabled = true; // "target" sets the location of focus, where the object orbits around this.target = new THREE.Vector3(); // How far you can dolly in and out ( PerspectiveCamera only ) this.minDistance = 0; this.maxDistance = Infinity; // How far you can zoom in and out ( OrthographicCamera only ) this.minZoom = 0; this.maxZoom = Infinity; // How far you can orbit vertically, upper and lower limits. // Range is 0 to Math.PI radians. this.minPolarAngle = 0; // radians this.maxPolarAngle = Math.PI; // radians // How far you can orbit horizontally, upper and lower limits. // If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI ) this.minAzimuthAngle = - Infinity; // radians this.maxAzimuthAngle = Infinity; // radians // Set to true to enable damping (inertia) // If damping is enabled, you must call controls.update() in your animation loop this.enableDamping = false; this.dampingFactor = 0.05; // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. // Set to false to disable zooming this.enableZoom = true; this.zoomSpeed = 1.0; // Set to false to disable rotating this.enableRotate = true; this.rotateSpeed = 1.0; // Set to false to disable panning this.enablePan = true; this.panSpeed = 1.0; this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up this.keyPanSpeed = 7.0; // pixels moved per arrow key push // Set to true to automatically rotate around the target // If auto-rotate is enabled, you must call controls.update() in your animation loop this.autoRotate = false; this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60 // The four arrow keys this.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' }; // Mouse buttons this.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; // Touch fingers this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN }; // for reset this.target0 = this.target.clone(); this.position0 = this.object.position.clone(); this.zoom0 = this.object.zoom; // the target DOM element for key events this._domElementKeyEvents = null; // // public methods // this.getPolarAngle = function () { return spherical.phi; }; this.getAzimuthalAngle = function () { return spherical.theta; }; this.getDistance = function () { return this.object.position.distanceTo( this.target ); }; this.listenToKeyEvents = function ( domElement ) { domElement.addEventListener( 'keydown', onKeyDown ); this._domElementKeyEvents = domElement; }; this.saveState = function () { scope.target0.copy( scope.target ); scope.position0.copy( scope.object.position ); scope.zoom0 = scope.object.zoom; }; this.reset = function () { scope.target.copy( scope.target0 ); scope.object.position.copy( scope.position0 ); scope.object.zoom = scope.zoom0; scope.object.updateProjectionMatrix(); scope.dispatchEvent( _changeEvent ); scope.update(); state = STATE.NONE; }; // this method is exposed, but perhaps it would be better if we can make it private... this.update = function () { const offset = new THREE.Vector3(); // so camera.up is the orbit axis const quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); const quatInverse = quat.clone().invert(); const lastPosition = new THREE.Vector3(); const lastQuaternion = new THREE.Quaternion(); const twoPI = 2 * Math.PI; return function update() { const position = scope.object.position; offset.copy( position ).sub( scope.target ); // rotate offset to "y-axis-is-up" space offset.applyQuaternion( quat ); // angle from z-axis around y-axis spherical.setFromVector3( offset ); if ( scope.autoRotate && state === STATE.NONE ) { rotateLeft( getAutoRotationAngle() ); } if ( scope.enableDamping ) { spherical.theta += sphericalDelta.theta * scope.dampingFactor; spherical.phi += sphericalDelta.phi * scope.dampingFactor; } else { spherical.theta += sphericalDelta.theta; spherical.phi += sphericalDelta.phi; } // restrict theta to be between desired limits let min = scope.minAzimuthAngle; let max = scope.maxAzimuthAngle; if ( isFinite( min ) && isFinite( max ) ) { if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI; if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI; if ( min <= max ) { spherical.theta = Math.max( min, Math.min( max, spherical.theta ) ); } else { spherical.theta = spherical.theta > ( min + max ) / 2 ? Math.max( min, spherical.theta ) : Math.min( max, spherical.theta ); } } // restrict phi to be between desired limits spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); spherical.makeSafe(); spherical.radius *= scale; // restrict radius to be between desired limits spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); // move target to panned location if ( scope.enableDamping === true ) { scope.target.addScaledVector( panOffset, scope.dampingFactor ); } else { scope.target.add( panOffset ); } offset.setFromSpherical( spherical ); // rotate offset back to "camera-up-vector-is-up" space offset.applyQuaternion( quatInverse ); position.copy( scope.target ).add( offset ); scope.object.lookAt( scope.target ); if ( scope.enableDamping === true ) { sphericalDelta.theta *= 1 - scope.dampingFactor; sphericalDelta.phi *= 1 - scope.dampingFactor; panOffset.multiplyScalar( 1 - scope.dampingFactor ); } else { sphericalDelta.set( 0, 0, 0 ); panOffset.set( 0, 0, 0 ); } scale = 1; // update condition is: // min(camera displacement, camera rotation in radians)^2 > EPS // using small-angle approximation cos(x/2) = 1 - x^2 / 8 if ( zoomChanged || lastPosition.distanceToSquared( scope.object.position ) > EPS || 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { scope.dispatchEvent( _changeEvent ); lastPosition.copy( scope.object.position ); lastQuaternion.copy( scope.object.quaternion ); zoomChanged = false; return true; } return false; }; }(); this.dispose = function () { scope.domElement.removeEventListener( 'contextmenu', onContextMenu ); scope.domElement.removeEventListener( 'pointerdown', onPointerDown ); scope.domElement.removeEventListener( 'pointercancel', onPointerCancel ); scope.domElement.removeEventListener( 'wheel', onMouseWheel ); scope.domElement.removeEventListener( 'pointermove', onPointerMove ); scope.domElement.removeEventListener( 'pointerup', onPointerUp ); if ( scope._domElementKeyEvents !== null ) { scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown ); } //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? }; // // internals // const scope = this; const STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_PAN: 4, TOUCH_DOLLY_PAN: 5, TOUCH_DOLLY_ROTATE: 6 }; let state = STATE.NONE; const EPS = 0.000001; // current position in spherical coordinates const spherical = new THREE.Spherical(); const sphericalDelta = new THREE.Spherical(); let scale = 1; const panOffset = new THREE.Vector3(); let zoomChanged = false; const rotateStart = new THREE.Vector2(); const rotateEnd = new THREE.Vector2(); const rotateDelta = new THREE.Vector2(); const panStart = new THREE.Vector2(); const panEnd = new THREE.Vector2(); const panDelta = new THREE.Vector2(); const dollyStart = new THREE.Vector2(); const dollyEnd = new THREE.Vector2(); const dollyDelta = new THREE.Vector2(); const pointers = []; const pointerPositions = {}; function getAutoRotationAngle() { return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; } function getZoomScale() { return Math.pow( 0.95, scope.zoomSpeed ); } function rotateLeft( angle ) { sphericalDelta.theta -= angle; } function rotateUp( angle ) { sphericalDelta.phi -= angle; } const panLeft = function () { const v = new THREE.Vector3(); return function panLeft( distance, objectMatrix ) { v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix v.multiplyScalar( - distance ); panOffset.add( v ); }; }(); const panUp = function () { const v = new THREE.Vector3(); return function panUp( distance, objectMatrix ) { if ( scope.screenSpacePanning === true ) { v.setFromMatrixColumn( objectMatrix, 1 ); } else { v.setFromMatrixColumn( objectMatrix, 0 ); v.crossVectors( scope.object.up, v ); } v.multiplyScalar( distance ); panOffset.add( v ); }; }(); // deltaX and deltaY are in pixels; right and down are positive const pan = function () { const offset = new THREE.Vector3(); return function pan( deltaX, deltaY ) { const element = scope.domElement; if ( scope.object.isPerspectiveCamera ) { // perspective const position = scope.object.position; offset.copy( position ).sub( scope.target ); let targetDistance = offset.length(); // half of the fov is center to top of screen targetDistance *= Math.tan( scope.object.fov / 2 * Math.PI / 180.0 ); // we use only clientHeight here so aspect ratio does not distort speed panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); } else if ( scope.object.isOrthographicCamera ) { // orthographic panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); } else { // camera neither orthographic nor perspective console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); scope.enablePan = false; } }; }(); function dollyOut( dollyScale ) { if ( scope.object.isPerspectiveCamera ) { scale /= dollyScale; } else if ( scope.object.isOrthographicCamera ) { scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); scope.object.updateProjectionMatrix(); zoomChanged = true; } else { console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); scope.enableZoom = false; } } function dollyIn( dollyScale ) { if ( scope.object.isPerspectiveCamera ) { scale *= dollyScale; } else if ( scope.object.isOrthographicCamera ) { scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); scope.object.updateProjectionMatrix(); zoomChanged = true; } else { console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); scope.enableZoom = false; } } // // event callbacks - update the object state // function handleMouseDownRotate( event ) { rotateStart.set( event.clientX, event.clientY ); } function handleMouseDownDolly( event ) { dollyStart.set( event.clientX, event.clientY ); } function handleMouseDownPan( event ) { panStart.set( event.clientX, event.clientY ); } function handleMouseMoveRotate( event ) { rotateEnd.set( event.clientX, event.clientY ); rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); const element = scope.domElement; rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); rotateStart.copy( rotateEnd ); scope.update(); } function handleMouseMoveDolly( event ) { dollyEnd.set( event.clientX, event.clientY ); dollyDelta.subVectors( dollyEnd, dollyStart ); if ( dollyDelta.y > 0 ) { dollyOut( getZoomScale() ); } else if ( dollyDelta.y < 0 ) { dollyIn( getZoomScale() ); } dollyStart.copy( dollyEnd ); scope.update(); } function handleMouseMovePan( event ) { panEnd.set( event.clientX, event.clientY ); panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); pan( panDelta.x, panDelta.y ); panStart.copy( panEnd ); scope.update(); } function handleMouseWheel( event ) { if ( event.deltaY < 0 ) { dollyIn( getZoomScale() ); } else if ( event.deltaY > 0 ) { dollyOut( getZoomScale() ); } scope.update(); } function handleKeyDown( event ) { let needsUpdate = false; switch ( event.code ) { case scope.keys.UP: if ( event.ctrlKey || event.metaKey || event.shiftKey ) { rotateUp( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight ); } else { pan( 0, scope.keyPanSpeed ); } needsUpdate = true; break; case scope.keys.BOTTOM: if ( event.ctrlKey || event.metaKey || event.shiftKey ) { rotateUp( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight ); } else { pan( 0, - scope.keyPanSpeed ); } needsUpdate = true; break; case scope.keys.LEFT: if ( event.ctrlKey || event.metaKey || event.shiftKey ) { rotateLeft( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight ); } else { pan( scope.keyPanSpeed, 0 ); } needsUpdate = true; break; case scope.keys.RIGHT: if ( event.ctrlKey || event.metaKey || event.shiftKey ) { rotateLeft( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight ); } else { pan( - scope.keyPanSpeed, 0 ); } needsUpdate = true; break; } if ( needsUpdate ) { // prevent the browser from scrolling on cursor keys event.preventDefault(); scope.update(); } } function handleTouchStartRotate() { if ( pointers.length === 1 ) { rotateStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY ); } else { const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX ); const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY ); rotateStart.set( x, y ); } } function handleTouchStartPan() { if ( pointers.length === 1 ) { panStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY ); } else { const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX ); const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY ); panStart.set( x, y ); } } function handleTouchStartDolly() { const dx = pointers[ 0 ].pageX - pointers[ 1 ].pageX; const dy = pointers[ 0 ].pageY - pointers[ 1 ].pageY; const distance = Math.sqrt( dx * dx + dy * dy ); dollyStart.set( 0, distance ); } function handleTouchStartDollyPan() { if ( scope.enableZoom ) handleTouchStartDolly(); if ( scope.enablePan ) handleTouchStartPan(); } function handleTouchStartDollyRotate() { if ( scope.enableZoom ) handleTouchStartDolly(); if ( scope.enableRotate ) handleTouchStartRotate(); } function handleTouchMoveRotate( event ) { if ( pointers.length == 1 ) { rotateEnd.set( event.pageX, event.pageY ); } else { const position = getSecondPointerPosition( event ); const x = 0.5 * ( event.pageX + position.x ); const y = 0.5 * ( event.pageY + position.y ); rotateEnd.set( x, y ); } rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); const element = scope.domElement; rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); rotateStart.copy( rotateEnd ); } function handleTouchMovePan( event ) { if ( pointers.length === 1 ) { panEnd.set( event.pageX, event.pageY ); } else { const position = getSecondPointerPosition( event ); const x = 0.5 * ( event.pageX + position.x ); const y = 0.5 * ( event.pageY + position.y ); panEnd.set( x, y ); } panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); pan( panDelta.x, panDelta.y ); panStart.copy( panEnd ); } function handleTouchMoveDolly( event ) { const position = getSecondPointerPosition( event ); const dx = event.pageX - position.x; const dy = event.pageY - position.y; const distance = Math.sqrt( dx * dx + dy * dy ); dollyEnd.set( 0, distance ); dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); dollyOut( dollyDelta.y ); dollyStart.copy( dollyEnd ); } function handleTouchMoveDollyPan( event ) { if ( scope.enableZoom ) handleTouchMoveDolly( event ); if ( scope.enablePan ) handleTouchMovePan( event ); } function handleTouchMoveDollyRotate( event ) { if ( scope.enableZoom ) handleTouchMoveDolly( event ); if ( scope.enableRotate ) handleTouchMoveRotate( event ); } // // event handlers - FSM: listen for events and reset state // function onPointerDown( event ) { if ( scope.enabled === false ) return; if ( pointers.length === 0 ) { scope.domElement.setPointerCapture( event.pointerId ); scope.domElement.addEventListener( 'pointermove', onPointerMove ); scope.domElement.addEventListener( 'pointerup', onPointerUp ); } // addPointer( event ); if ( event.pointerType === 'touch' ) { onTouchStart( event ); } else { onMouseDown( event ); } } function onPointerMove( event ) { if ( scope.enabled === false ) return; if ( event.pointerType === 'touch' ) { onTouchMove( event ); } else { onMouseMove( event ); } } function onPointerUp( event ) { removePointer( event ); if ( pointers.length === 0 ) { scope.domElement.releasePointerCapture( event.pointerId ); scope.domElement.removeEventListener( 'pointermove', onPointerMove ); scope.domElement.removeEventListener( 'pointerup', onPointerUp ); } scope.dispatchEvent( _endEvent ); state = STATE.NONE; } function onPointerCancel( event ) { removePointer( event ); } function onMouseDown( event ) { let mouseAction; switch ( event.button ) { case 0: mouseAction = scope.mouseButtons.LEFT; break; case 1: mouseAction = scope.mouseButtons.MIDDLE; break; case 2: mouseAction = scope.mouseButtons.RIGHT; break; default: mouseAction = - 1; } switch ( mouseAction ) { case THREE.MOUSE.DOLLY: if ( scope.enableZoom === false ) return; handleMouseDownDolly( event ); state = STATE.DOLLY; break; case THREE.MOUSE.ROTATE: if ( event.ctrlKey || event.metaKey || event.shiftKey ) { if ( scope.enablePan === false ) return; handleMouseDownPan( event ); state = STATE.PAN; } else { if ( scope.enableRotate === false ) return; handleMouseDownRotate( event ); state = STATE.ROTATE; } break; case THREE.MOUSE.PAN: if ( event.ctrlKey || event.metaKey || event.shiftKey ) { if ( scope.enableRotate === false ) return; handleMouseDownRotate( event ); state = STATE.ROTATE; } else { if ( scope.enablePan === false ) return; handleMouseDownPan( event ); state = STATE.PAN; } break; default: state = STATE.NONE; } if ( state !== STATE.NONE ) { scope.dispatchEvent( _startEvent ); } } function onMouseMove( event ) { switch ( state ) { case STATE.ROTATE: if ( scope.enableRotate === false ) return; handleMouseMoveRotate( event ); break; case STATE.DOLLY: if ( scope.enableZoom === false ) return; handleMouseMoveDolly( event ); break; case STATE.PAN: if ( scope.enablePan === false ) return; handleMouseMovePan( event ); break; } } function onMouseWheel( event ) { if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return; event.preventDefault(); scope.dispatchEvent( _startEvent ); handleMouseWheel( event ); scope.dispatchEvent( _endEvent ); } function onKeyDown( event ) { if ( scope.enabled === false || scope.enablePan === false ) return; handleKeyDown( event ); } function onTouchStart( event ) { trackPointer( event ); switch ( pointers.length ) { case 1: switch ( scope.touches.ONE ) { case THREE.TOUCH.ROTATE: if ( scope.enableRotate === false ) return; handleTouchStartRotate(); state = STATE.TOUCH_ROTATE; break; case THREE.TOUCH.PAN: if ( scope.enablePan === false ) return; handleTouchStartPan(); state = STATE.TOUCH_PAN; break; default: state = STATE.NONE; } break; case 2: switch ( scope.touches.TWO ) { case THREE.TOUCH.DOLLY_PAN: if ( scope.enableZoom === false && scope.enablePan === false ) return; handleTouchStartDollyPan(); state = STATE.TOUCH_DOLLY_PAN; break; case THREE.TOUCH.DOLLY_ROTATE: if ( scope.enableZoom === false && scope.enableRotate === false ) return; handleTouchStartDollyRotate(); state = STATE.TOUCH_DOLLY_ROTATE; break; default: state = STATE.NONE; } break; default: state = STATE.NONE; } if ( state !== STATE.NONE ) { scope.dispatchEvent( _startEvent ); } } function onTouchMove( event ) { trackPointer( event ); switch ( state ) { case STATE.TOUCH_ROTATE: if ( scope.enableRotate === false ) return; handleTouchMoveRotate( event ); scope.update(); break; case STATE.TOUCH_PAN: if ( scope.enablePan === false ) return; handleTouchMovePan( event ); scope.update(); break; case STATE.TOUCH_DOLLY_PAN: if ( scope.enableZoom === false && scope.enablePan === false ) return; handleTouchMoveDollyPan( event ); scope.update(); break; case STATE.TOUCH_DOLLY_ROTATE: if ( scope.enableZoom === false && scope.enableRotate === false ) return; handleTouchMoveDollyRotate( event ); scope.update(); break; default: state = STATE.NONE; } } function onContextMenu( event ) { if ( scope.enabled === false ) return; event.preventDefault(); } function addPointer( event ) { pointers.push( event ); } function removePointer( event ) { delete pointerPositions[ event.pointerId ]; for ( let i = 0; i < pointers.length; i ++ ) { if ( pointers[ i ].pointerId == event.pointerId ) { pointers.splice( i, 1 ); return; } } } function trackPointer( event ) { let position = pointerPositions[ event.pointerId ]; if ( position === undefined ) { position = new THREE.Vector2(); pointerPositions[ event.pointerId ] = position; } position.set( event.pageX, event.pageY ); } function getSecondPointerPosition( event ) { const pointer = event.pointerId === pointers[ 0 ].pointerId ? pointers[ 1 ] : pointers[ 0 ]; return pointerPositions[ pointer.pointerId ]; } // scope.domElement.addEventListener( 'contextmenu', onContextMenu ); scope.domElement.addEventListener( 'pointerdown', onPointerDown ); scope.domElement.addEventListener( 'pointercancel', onPointerCancel ); scope.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } ); // force an update at start this.update(); } } // This set of controls performs orbiting, dollying (zooming), and panning. // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). // This is very similar to OrbitControls, another set of touch behavior // // Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate // Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish // Pan - left mouse, or arrow keys / touch: one-finger move class MapControls extends OrbitControls { constructor( object, domElement ) { super( object, domElement ); this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up this.mouseButtons.LEFT = THREE.MOUSE.PAN; this.mouseButtons.RIGHT = THREE.MOUSE.ROTATE; this.touches.ONE = THREE.TOUCH.PAN; this.touches.TWO = THREE.TOUCH.DOLLY_ROTATE; } } THREE.MapControls = MapControls; THREE.OrbitControls = OrbitControls; } )(); </pre> </div> </div> </div> <script> $(function(){ $('a[rel*=facebox]').facebox({ 'loadingImage': 'https://www.yatex.org/gitbucket/assets/vendors/facebox/loading.gif?20240601154850', 'closeImage': 'https://www.yatex.org/gitbucket/assets/vendors/facebox/closelabel.png?20240601154850' }); $(document).on("click", ".js-fork-owner-select-target", function() { var account = $(this).text().replace("@", ""); $("#account").val(account); $("#fork").submit(); }); }); </script> </div> <script> $(function(){ $(".sidebar-toggle").on('click', function(e){ $.post('https://www.yatex.org/gitbucket/sidebar-collapse', { collapse: !$('body').hasClass('sidebar-collapse') }); }); }); </script> </body> </html> <script> $(window).on('load', function(){ window.onhashchange = function(){ updateHighlighting(); } const pre = $('pre.prettyprint'); function updateSourceLineNum() { $('.source-line-num').remove(); const pos = pre.find('ol.linenums').position(); if (pos) { $('<div class="source-line-num">').css({ height : pre.height(), width : '48px', cursor : 'pointer', position: 'absolute', top : pos.top + 'px', left : pos.left + 'px' }).click(function(e){ let pos = $(this).data("pos"); if (!pos) { pos = $('ol.linenums li').map(function(){ return { id: $(this).attr("id"), top: $(this).position().top} }).toArray(); $(this).data("pos",pos); } let i = 0; for(i = 0; i < pos.length - 1; i++){ if(pos[i + 1].top > e.pageY){ break; } } const line = pos[i].id.replace(/^L/,''); const hash = location.hash; const baseUrl = location.toString().split("#")[0]; if (e.shiftKey == true && hash.match(/#L\d+(-L\d+)?/)) { const fragments = hash.split('-'); window.history.pushState('', '', baseUrl + fragments[0] + '-L' + line); } else { const p = $("#L" + line).attr('id', ''); window.history.pushState('', '', baseUrl + '#L' + line); p.attr('id','L' + line); } $("#branchCtrlWrapper .btn .muted").text("tree:"); $("#branchCtrlWrapper .btn .strong").text("7a630f0bef"); getSelection().empty(); updateHighlighting(); }).appendTo(pre); updateHighlighting(); } else { // Maybe code view is not initialized yet. Retry until succeed. setTimeout(updateSourceLineNum, 300); } } const repository = $('.blame-action').data('repository'); $('.blame-action').click(function(e){ if(history.pushState && $('pre.prettyprint.no-renderable').length){ e.preventDefault(); history.pushState(null, null, this.href); updateBlame(); } }); function updateBlame(){ const m = /\/(blame|blob)(\/.*)$/.exec(location.href); const mode = m[1]; $('.blame-action').toggleClass("active", mode=='blame').attr('href', repository + (m[1] == 'blame' ? '/blob' : '/blame') + m[2]); if(pre.parents("div.box-content-bottom").find(".blame").length){ pre.parent().toggleClass("blame-container", mode == 'blame'); updateSourceLineNum(); return; } if(mode == 'blob'){ updateSourceLineNum(); return; } $(document.body).toggleClass('no-box-shadow', document.body.style.boxShadow === undefined); $('.blame-action').addClass("active"); const base = $('<div class="blame">').css({height: pre.height()}).prependTo(pre.parents("div.box-content-bottom")); base.parent().addClass("blame-container"); updateSourceLineNum(); $.get($('.blame-action').data('url')).done(function(data){ let blame = data.blame; let lastDiv; const now = new Date().getTime(); const index = []; for(let i = 0; i < blame.length; i++){ for(let j = 0; j < blame[i].lines.length; j++){ index[blame[i].lines[j]] = blame[i]; } } $('pre.prettyprint ol.linenums li').each(function(i, e){ const p = $(e).position(); const h = $(e).height(); if(blame == index[i]){ lastDiv.css("min-height",(p.top + h + 1) - lastDiv.position().top); } else { $(e).addClass('blame-sep') blame = index[i]; const sha = $('<div class="blame-sha">') .append($('<a>').attr("href", data.root + '/commit/' + blame.id).text(blame.id.substr(0, 7))); if (blame.prev) { sha.append($('<br />')) .append($('<a class="muted-link">').text('prev').attr("href", data.root + '/blame/' + blame.prev + '/' + (blame.prevPath || data.path))); } lastDiv = $('<div class="blame-info">') .addClass('heat' + Math.min(10, Math.max(1, Math.ceil((now - blame.commited) / (24 * 3600 * 1000 * 70))))) .toggleClass('blame-last', blame.id == data.last) .data('line', (i + 1)) .css({ "top" : p.top + 'px', "min-height" : h + 'px' }) .append(sha) .append($(blame.avatar).addClass('avatar').css({"float": "left"})) .append($('<div class="blame-commit-title">').text(blame.message)) .append($('<div class="muted">').html(blame.author + " authed " + blame.authed)) .appendTo(base); } }); }); return false; }; $(document).on('expanded.pushMenu collapsed.pushMenu', function(e){ setTimeout(updateBlame, 300); }); updateBlame(); }); let scrolling = false; /** * Highlight lines which are specified by URL hash. */ function updateHighlighting() { const hash = location.hash; const isDark = false; if (hash.match(/#L\d+(-L\d+)?/)) { if (isDark) { $('li.highlight-dark').removeClass('highlight-dark'); } else { $('li.highlight').removeClass('highlight'); } const fragments = hash.substr(1).split('-'); if (fragments.length == 1) { if (isDark) { $('#' + fragments[0]).addClass('highlight-dark'); } else { $('#' + fragments[0]).addClass('highlight'); } if(!scrolling){ $(window).scrollTop($('#' + fragments[0]).offset().top); } } else if(fragments.length > 1){ const start = parseInt(fragments[0].substr(1)); const end = parseInt(fragments[1].substr(1)); for (let i = start; i <= end; i++) { if (isDark) { $('#L' + i).addClass('highlight-dark'); } else { $('#L' + i).addClass('highlight'); } } if (!scrolling) { $(window).scrollTop($('#' + fragments[0]).offset().top); } } } scrolling = true; } </script>