1<!DOCTYPE html> 2<!-- 3Copyright (c) 2013 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7<link rel="import" href="/tracing/base/utils.html"> 8<link rel="import" href="/tracing/ui/base/animation.html"> 9 10<script> 11'use strict'; 12 13tr.exportTo('tr.ui', function() { 14 var kDefaultPanAnimationDurationMs = 100.0; 15 16 /** 17 * Pans a TimelineDisplayTransform by a given amount. 18 * @constructor 19 * @extends {tr.ui.b.Animation} 20 * @param {Number} deltaX The total amount of change to the transform's panX. 21 * @param {Number} deltaY The total amount of change to the transform's panY. 22 * @param {Number=} opt_durationMs How long the pan animation should run. 23 * Defaults to kDefaultPanAnimationDurationMs. 24 */ 25 function TimelineDisplayTransformPanAnimation( 26 deltaX, deltaY, opt_durationMs) { 27 this.deltaX = deltaX; 28 this.deltaY = deltaY; 29 if (opt_durationMs === undefined) 30 this.durationMs = kDefaultPanAnimationDurationMs; 31 else 32 this.durationMs = opt_durationMs; 33 34 this.startPanX = undefined; 35 this.startPanY = undefined; 36 this.startTimeMs = undefined; 37 } 38 39 TimelineDisplayTransformPanAnimation.prototype = { 40 __proto__: tr.ui.b.Animation.prototype, 41 42 get affectsPanY() { 43 return this.deltaY !== 0; 44 }, 45 46 canTakeOverFor: function(existingAnimation) { 47 return existingAnimation instanceof TimelineDisplayTransformPanAnimation; 48 }, 49 50 takeOverFor: function(existing, timestamp, target) { 51 var remainingDeltaXOnExisting = existing.goalPanX - target.panX; 52 var remainingDeltaYOnExisting = existing.goalPanY - target.panY; 53 var remainingTimeOnExisting = timestamp - ( 54 existing.startTimeMs + existing.durationMs); 55 remainingTimeOnExisting = Math.max(remainingTimeOnExisting, 0); 56 57 this.deltaX += remainingDeltaXOnExisting; 58 this.deltaY += remainingDeltaYOnExisting; 59 this.durationMs += remainingTimeOnExisting; 60 }, 61 62 start: function(timestamp, target) { 63 this.startTimeMs = timestamp; 64 this.startPanX = target.panX; 65 this.startPanY = target.panY; 66 }, 67 68 tick: function(timestamp, target) { 69 var percentDone = (timestamp - this.startTimeMs) / this.durationMs; 70 percentDone = tr.b.clamp(percentDone, 0, 1); 71 72 target.panX = tr.b.lerp(percentDone, this.startPanX, this.goalPanX); 73 if (this.affectsPanY) 74 target.panY = tr.b.lerp(percentDone, this.startPanY, this.goalPanY); 75 return timestamp >= this.startTimeMs + this.durationMs; 76 }, 77 78 get goalPanX() { 79 return this.startPanX + this.deltaX; 80 }, 81 82 get goalPanY() { 83 return this.startPanY + this.deltaY; 84 } 85 }; 86 87 /** 88 * Zooms in/out on a specified location in the world. 89 * 90 * Zooming in and out is all about keeping the area under the mouse cursor, 91 * here called the "focal point" in the same place under the zoom. If one 92 * simply changes the scale, the area under the mouse cursor will change. To 93 * keep the focal point from moving during the zoom, the pan needs to change 94 * in order to compensate. Thus, a ZoomTo animation is given both a focal 95 * point in addition to the amount by which to zoom. 96 * 97 * @constructor 98 * @extends {tr.ui.b.Animation} 99 * @param {Number} goalFocalPointXWorld The X coordinate in the world which is 100 * of interest. 101 * @param {Number} goalFocalPointXView Where on the screen the 102 * goalFocalPointXWorld should stay centered during the zoom. 103 * @param {Number} goalFocalPointY Where the panY should be when the zoom 104 * completes. 105 * @param {Number} zoomInRatioX The ratio of the current scaleX to the goal 106 * scaleX. 107 */ 108 function TimelineDisplayTransformZoomToAnimation( 109 goalFocalPointXWorld, 110 goalFocalPointXView, 111 goalFocalPointY, 112 zoomInRatioX, 113 opt_durationMs) { 114 this.goalFocalPointXWorld = goalFocalPointXWorld; 115 this.goalFocalPointXView = goalFocalPointXView; 116 this.goalFocalPointY = goalFocalPointY; 117 this.zoomInRatioX = zoomInRatioX; 118 if (opt_durationMs === undefined) 119 this.durationMs = kDefaultPanAnimationDurationMs; 120 else 121 this.durationMs = opt_durationMs; 122 123 this.startTimeMs = undefined; 124 this.startScaleX = undefined; 125 this.goalScaleX = undefined; 126 this.startPanY = undefined; 127 } 128 129 TimelineDisplayTransformZoomToAnimation.prototype = { 130 __proto__: tr.ui.b.Animation.prototype, 131 132 get affectsPanY() { 133 return this.startPanY != this.goalFocalPointY; 134 }, 135 136 canTakeOverFor: function(existingAnimation) { 137 return false; 138 }, 139 140 takeOverFor: function(existingAnimation, timestamp, target) { 141 this.goalScaleX = target.scaleX * this.zoomInRatioX; 142 }, 143 144 start: function(timestamp, target) { 145 this.startTimeMs = timestamp; 146 this.startScaleX = target.scaleX; 147 this.goalScaleX = this.zoomInRatioX * target.scaleX; 148 this.startPanY = target.panY; 149 }, 150 151 tick: function(timestamp, target) { 152 var percentDone = (timestamp - this.startTimeMs) / this.durationMs; 153 percentDone = tr.b.clamp(percentDone, 0, 1); 154 155 target.scaleX = tr.b.lerp(percentDone, this.startScaleX, this.goalScaleX); 156 if (this.affectsPanY) { 157 target.panY = tr.b.lerp( 158 percentDone, this.startPanY, this.goalFocalPointY); 159 } 160 161 target.xPanWorldPosToViewPos( 162 this.goalFocalPointXWorld, this.goalFocalPointXView); 163 return timestamp >= this.startTimeMs + this.durationMs; 164 } 165 }; 166 167 return { 168 TimelineDisplayTransformPanAnimation: 169 TimelineDisplayTransformPanAnimation, 170 TimelineDisplayTransformZoomToAnimation: 171 TimelineDisplayTransformZoomToAnimation 172 }; 173}); 174</script> 175