Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: tracing/tracing/ui/base/chart_base_2d.html

Issue 2162963002: [polymer] Merge of master into polymer10-migration (Closed) Base URL: git@github.com:catapult-project/catapult.git@polymer10-migration
Patch Set: Merge polymer10-migration int polymer10-merge Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tracing/tracing/ui/base/chart_base.html ('k') | tracing/tracing/ui/base/drag_handle.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <!-- 2 <!--
3 Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 Copyright (c) 2014 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be 4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file. 5 found in the LICENSE file.
6 --> 6 -->
7 7
8 <link rel="import" href="/tracing/base/iteration_helpers.html"> 8 <link rel="import" href="/tracing/base/iteration_helpers.html">
9 <link rel="import" href="/tracing/base/raf.html">
9 <link rel="import" href="/tracing/base/range.html"> 10 <link rel="import" href="/tracing/base/range.html">
10 <link rel="import" href="/tracing/ui/base/chart_base.html"> 11 <link rel="import" href="/tracing/ui/base/chart_base.html">
11 <link rel="import" href="/tracing/ui/base/mouse_tracker.html"> 12 <link rel="import" href="/tracing/ui/base/mouse_tracker.html">
12 13
13 <style> 14 <style>
14 * /deep/ .chart-base-2d.updating-brushing-state #brushes > * { 15 * /deep/ .chart-base-2d.updating-brushing-state #brushes > * {
15 fill: rgb(103, 199, 165) 16 fill: rgb(103, 199, 165)
16 } 17 }
17 18
18 * /deep/ .chart-base-2d #brushes { 19 * /deep/ .chart-base-2d #brushes {
(...skipping 12 matching lines...) Expand all
31 __proto__: ChartBase.prototype, 32 __proto__: ChartBase.prototype,
32 33
33 decorate: function() { 34 decorate: function() {
34 ChartBase.prototype.decorate.call(this); 35 ChartBase.prototype.decorate.call(this);
35 Polymer.dom(this).classList.add('chart-base-2d'); 36 Polymer.dom(this).classList.add('chart-base-2d');
36 this.xScale_ = d3.scale.linear(); 37 this.xScale_ = d3.scale.linear();
37 this.yScale_ = d3.scale.linear(); 38 this.yScale_ = d3.scale.linear();
38 this.isYLogScale_ = false; 39 this.isYLogScale_ = false;
39 this.yLogScaleMin_ = undefined; 40 this.yLogScaleMin_ = undefined;
40 this.dataRange_ = new tr.b.Range(); 41 this.dataRange_ = new tr.b.Range();
41 42 this.hideXAxis_ = false;
43 this.hideYAxis_ = false;
42 this.data_ = []; 44 this.data_ = [];
43 this.seriesKeys_ = [];
44 this.leftMargin_ = 50;
45 45
46 d3.select(this.chartAreaElement) 46 d3.select(this.chartAreaElement)
47 .append('g') 47 .append('g')
48 .attr('id', 'brushes'); 48 .attr('id', 'brushes');
49 d3.select(this.chartAreaElement) 49 d3.select(this.chartAreaElement)
50 .append('g') 50 .append('g')
51 .attr('id', 'series'); 51 .attr('id', 'series');
52 52
53 this.addEventListener('mousedown', this.onMouseDown_.bind(this)); 53 this.addEventListener('mousedown', this.onMouseDown_.bind(this));
54 }, 54 },
55 55
56 get hideXAxis() {
57 return this.hideXAxis_;
58 },
59
60 set hideXAxis(h) {
61 this.hideXAxis_ = h;
62 this.updateContents_();
63 },
64
65 get hideYAxis() {
66 return this.hideYAxis_;
67 },
68
69 set hideYAxis(h) {
70 this.hideYAxis_ = h;
71 this.updateContents_();
72 },
73
56 get data() { 74 get data() {
57 return this.data_; 75 return this.data_;
58 }, 76 },
59 77
60 /** 78 /**
61 * Sets the data array for the object 79 * Sets the data array for the object
62 * 80 *
63 * @param {Array} data The data. Each element must be an object, with at 81 * @param {Array} data The data. Each element must be an object, with at
64 * least an x property. All other properties become series names in the 82 * least an x property. All other properties become series names in the
65 * chart. The data can be sparse (i.e. every x value does not have to 83 * chart. The data can be sparse (i.e. every x value does not have to
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 leftIndex = index; 120 leftIndex = index;
103 rightIndex = Math.min(index + 1, data.length - 1); 121 rightIndex = Math.min(index + 1, data.length - 1);
104 } 122 }
105 var leftWidth = this.getXForDatum_(data[index], index) - 123 var leftWidth = this.getXForDatum_(data[index], index) -
106 this.getXForDatum_(data[leftIndex], leftIndex); 124 this.getXForDatum_(data[leftIndex], leftIndex);
107 var rightWidth = this.getXForDatum_(data[rightIndex], rightIndex) - 125 var rightWidth = this.getXForDatum_(data[rightIndex], rightIndex) -
108 this.getXForDatum_(data[index], index); 126 this.getXForDatum_(data[index], index);
109 return leftWidth * 0.5 + rightWidth * 0.5; 127 return leftWidth * 0.5 + rightWidth * 0.5;
110 }, 128 },
111 129
112 getLegendKeys_: function() {
113 if (this.seriesKeys_ &&
114 this.seriesKeys_.length > 1)
115 return this.seriesKeys_.slice();
116 return [];
117 },
118
119 updateSeriesKeys_: function() { 130 updateSeriesKeys_: function() {
120 // Accumulate the keys on each data point. 131 // Don't clear seriesByKey_; the caller might have put state in it using
121 var keySet = {}; 132 // customizeLegendTargets, customizeOptionalSeries, or
133 // customizeEnabledSeries before setting data.
122 this.data_.forEach(function(datum) { 134 this.data_.forEach(function(datum) {
123 Object.keys(datum).forEach(function(key) { 135 Object.keys(datum).forEach(function(key) {
124 if (this.isDatumFieldSeries_(key)) 136 if (this.isDatumFieldSeries_(key))
125 keySet[key] = true; 137 this.getDataSeries(key);
126 }, this); 138 }, this);
127 }, this); 139 }, this);
128 this.seriesKeys_ = Object.keys(keySet);
129 }, 140 },
130 141
131 isDatumFieldSeries_: function(fieldName) { 142 isDatumFieldSeries_: function(fieldName) {
132 throw new Error('Not implemented'); 143 throw new Error('Not implemented');
133 }, 144 },
134 145
135 getXForDatum_: function(datum, index) { 146 getXForDatum_: function(datum, index) {
136 throw new Error('Not implemented'); 147 throw new Error('Not implemented');
137 }, 148 },
138 149
139 updateScales_: function() { 150 updateScales_: function() {
140 if (this.data_.length === 0) 151 if (this.data_.length === 0)
141 return; 152 return;
142 153
143 var width = this.chartAreaSize.width; 154 var width = this.chartAreaSize.width;
144 var height = this.chartAreaSize.height; 155 var height = this.chartAreaSize.height;
145 156
146 // X. 157 // X.
147 this.xScale_.range([0, width]); 158 this.xScale_.range([0, width]);
148 this.xScale_.domain(d3.extent(this.data_, this.getXForDatum_.bind(this))); 159 this.xScale_.domain(d3.extent(this.data_, this.getXForDatum_.bind(this)));
149 160
150 // Y. 161 // Y.
151 var yRange = new tr.b.Range(); 162 var yRange = new tr.b.Range();
152 var keySet = new Set(this.seriesKeys_); 163 for (var i = 0; i < this.data_.length; i++) {
153 for (var i = 0; i < this.data_.length; i++) 164 for (var key in this.data_[i]) {
154 for (var key in this.data_[i]) 165 if (!isNaN(Math.max(this.data_[i][key])))
155 if (keySet.has(key))
156 yRange.addValue(this.data_[i][key]); 166 yRange.addValue(this.data_[i][key]);
167 }
168 }
157 169
158 this.yScale_.range([height, 0]); 170 this.yScale_.range([height, 0]);
159 this.yScale_.domain([yRange.min, yRange.max]); 171 this.yScale_.domain([yRange.min, yRange.max]);
160 }, 172 },
161 173
162 updateBrushContents_: function(brushSel) { 174 updateBrushContents_: function(brushSel) {
163 brushSel.selectAll('*').remove(); 175 brushSel.selectAll('*').remove();
164 }, 176 },
165 177
166 updateXAxis_: function(xAxis) { 178 updateXAxis_: function(xAxis) {
167 xAxis.selectAll('*').remove(); 179 xAxis.selectAll('*').remove();
168 xAxis[0][0].style.opacity = 0; 180 xAxis[0][0].style.opacity = 0;
181 if (this.hideXAxis)
182 return;
183
169 xAxis.attr('transform', 'translate(0,' + this.chartAreaSize.height + ')') 184 xAxis.attr('transform', 'translate(0,' + this.chartAreaSize.height + ')')
170 .call(d3.svg.axis() 185 .call(d3.svg.axis()
171 .scale(this.xScale_) 186 .scale(this.xScale_)
172 .orient('bottom')); 187 .orient('bottom'));
173 window.requestAnimationFrame(function() { 188 tr.b.requestAnimationFrame(function() {
174 var previousRight = undefined; 189 var previousRight = undefined;
175 xAxis.selectAll('.tick')[0].forEach(function(tick) { 190 xAxis.selectAll('.tick')[0].forEach(function(tick) {
176 var currentLeft = tick.transform.baseVal[0].matrix.e; 191 var currentLeft = tick.transform.baseVal[0].matrix.e;
177 if ((previousRight === undefined) || 192 if ((previousRight === undefined) ||
178 (currentLeft > (previousRight + 3))) { 193 (currentLeft > (previousRight + 3))) {
179 var currentWidth = tick.getBBox().width; 194 var currentWidth = tick.getBBox().width;
180 previousRight = currentLeft + currentWidth; 195 previousRight = currentLeft + currentWidth;
181 } else { 196 } else {
182 tick.style.opacity = 0; 197 tick.style.opacity = 0;
183 } 198 }
184 }); 199 });
185 xAxis[0][0].style.opacity = 1; 200 xAxis[0][0].style.opacity = 1;
186 }); 201 }, this);
187 },
188
189 getMargin_: function() {
190 var margin = ChartBase.prototype.getMargin_.call(this);
191 margin.left = this.leftMargin_;
192 return margin;
193 }, 202 },
194 203
195 updateDataRange_: function() { 204 updateDataRange_: function() {
196 var dataBySeriesKey = this.getDataBySeriesKey_(); 205 var dataBySeriesKey = this.getDataBySeriesKey_();
197 this.dataRange_.reset(); 206 this.dataRange_.reset();
198 tr.b.iterItems(dataBySeriesKey, function(series, values) { 207 tr.b.iterItems(dataBySeriesKey, function(series, values) {
199 for (var i = 0; i < values.length; i++) { 208 for (var i = 0; i < values.length; i++) {
200 this.dataRange_.addValue(values[i][series]); 209 this.dataRange_.addValue(values[i][series]);
201 } 210 }
202 }, this); 211 }, this);
203 212
204 // Choose the closest power of 10, rounded down, as the smallest tick 213 // Choose the closest power of 10, rounded down, as the smallest tick
205 // to display. 214 // to display.
206 this.yLogScaleMin_ = undefined; 215 this.yLogScaleMin_ = undefined;
207 if (this.dataRange_.min !== undefined) { 216 if (this.dataRange_.min !== undefined) {
208 var minValue = this.dataRange_.min; 217 var minValue = this.dataRange_.min;
209 if (minValue == 0) 218 if (minValue == 0)
210 minValue = 1; 219 minValue = 1;
211 220
212 var onePowerLess = Math.floor( 221 var onePowerLess = Math.floor(
213 Math.log(minValue) / Math.log(10)) - 1; 222 Math.log(minValue) / Math.log(10)) - 1;
214 this.yLogScaleMin_ = Math.pow(10, onePowerLess); 223 this.yLogScaleMin_ = Math.pow(10, onePowerLess);
215 } 224 }
216 }, 225 },
217 226
218 updateYAxis_: function(yAxis) { 227 updateYAxis_: function(yAxis) {
219 yAxis.selectAll('*').remove(); 228 yAxis.selectAll('*').remove();
220 yAxis[0][0].style.opacity = 0; 229 yAxis[0][0].style.opacity = 0;
230 if (this.hideYAxis)
231 return;
221 232
222 var axisModifier = d3.svg.axis() 233 var axisModifier = d3.svg.axis()
223 .scale(this.yScale_) 234 .scale(this.yScale_)
224 .orient('left'); 235 .orient('left');
225 236
226 if (this.isYLogScale_) { 237 if (this.isYLogScale_) {
227 if (this.yLogScaleMin_ === undefined) 238 if (this.yLogScaleMin_ === undefined)
228 return; 239 return;
229 var minValue = this.dataRange_.min; 240 var minValue = this.dataRange_.min;
230 if (minValue == 0) 241 if (minValue == 0)
(...skipping 10 matching lines...) Expand all
241 252
242 axisModifier = axisModifier 253 axisModifier = axisModifier
243 .tickValues(tickValues) 254 .tickValues(tickValues)
244 .tickFormat(function(d) { 255 .tickFormat(function(d) {
245 return d; 256 return d;
246 }); 257 });
247 } 258 }
248 259
249 yAxis.call(axisModifier); 260 yAxis.call(axisModifier);
250 261
251 window.requestAnimationFrame(function() { 262 tr.b.requestAnimationFrame(function() {
252 var previousTop = undefined; 263 var previousTop = undefined;
253 var leftMargin = 0; 264 var leftMargin = 0;
254 yAxis.selectAll('.tick')[0].forEach(function(tick) { 265 yAxis.selectAll('.tick')[0].forEach(function(tick) {
255 var bbox = tick.getBBox(); 266 var bbox = tick.getBBox();
256 leftMargin = Math.max(leftMargin, bbox.width); 267 leftMargin = Math.max(leftMargin, bbox.width);
257 var currentTop = tick.transform.baseVal[0].matrix.f; 268 var currentTop = tick.transform.baseVal[0].matrix.f;
258 var currentBottom = currentTop + bbox.height; 269 var currentBottom = currentTop + bbox.height;
259 if ((previousTop === undefined) || 270 if ((previousTop === undefined) ||
260 (previousTop > (currentBottom + 3))) { 271 (previousTop > (currentBottom + 3))) {
261 previousTop = currentTop; 272 previousTop = currentTop;
262 } else { 273 } else {
263 tick.style.opacity = 0; 274 tick.style.opacity = 0;
264 } 275 }
265 }); 276 });
266 if (leftMargin > this.leftMargin_) { 277
267 this.leftMargin_ = leftMargin; 278 leftMargin = parseInt(Math.ceil(leftMargin));
279 if (leftMargin > this.margin.left) {
280 this.margin.left = leftMargin;
268 this.updateContents_(); 281 this.updateContents_();
269 } else { 282 } else {
270 yAxis[0][0].style.opacity = 1; 283 yAxis[0][0].style.opacity = 1;
271 } 284 }
272 }.bind(this)); 285 }, this);
273 }, 286 },
274 287
275 updateContents_: function() { 288 updateContents_: function() {
276 ChartBase.prototype.updateContents_.call(this); 289 ChartBase.prototype.updateContents_.call(this);
277 var chartAreaSel = d3.select(this.chartAreaElement); 290 var chartAreaSel = d3.select(this.chartAreaElement);
278 this.updateXAxis_(chartAreaSel.select('.x.axis')); 291 this.updateXAxis_(chartAreaSel.select('.x.axis'));
279 this.updateYAxis_(chartAreaSel.select('.y.axis')); 292 this.updateYAxis_(chartAreaSel.select('.y.axis'));
280 this.updateBrushContents_(chartAreaSel.select('#brushes')); 293 this.updateBrushContents_(chartAreaSel.select('#brushes'));
281 this.updateDataContents_(chartAreaSel.select('#series')); 294 this.updateDataContents_(chartAreaSel.select('#series'));
282 }, 295 },
283 296
284 updateDataContents_: function(seriesSel) { 297 updateDataContents_: function(seriesSel) {
285 throw new Error('Not implemented'); 298 throw new Error('Not implemented');
286 }, 299 },
287 300
288 /** 301 /**
289 * Returns a map of series key to the data for that series. 302 * Returns a map of series key to the data for that series.
290 * 303 *
291 * Example: 304 * Example:
292 * // returns {y: [{x: 1, y: 1}, {x: 3, y: 3}], z: [{x: 2, z: 2}]} 305 * // returns {y: [{x: 1, y: 1}, {x: 3, y: 3}], z: [{x: 2, z: 2}]}
293 * this.data_ = [{x: 1, y: 1}, {x: 2, z: 2}, {x: 3, y: 3}]; 306 * this.data_ = [{x: 1, y: 1}, {x: 2, z: 2}, {x: 3, y: 3}];
294 * this.getDataBySeriesKey_(); 307 * this.getDataBySeriesKey_();
295 * @return {Object} A map of series data by series key. 308 * @return {Object} A map of series data by series key.
296 */ 309 */
297 getDataBySeriesKey_: function() { 310 getDataBySeriesKey_: function() {
298 var dataBySeriesKey = {}; 311 var dataBySeriesKey = {};
299 this.seriesKeys_.forEach(function(seriesKey) { 312 for (var [key, series] of this.seriesByKey_) {
300 dataBySeriesKey[seriesKey] = []; 313 dataBySeriesKey[key] = [];
301 }); 314 }
302 315
303 this.data_.forEach(function(multiSeriesDatum, index) { 316 this.data_.forEach(function(multiSeriesDatum, index) {
304 var x = this.getXForDatum_(multiSeriesDatum, index); 317 var x = this.getXForDatum_(multiSeriesDatum, index);
305 318
306 d3.keys(multiSeriesDatum).forEach(function(seriesKey) { 319 d3.keys(multiSeriesDatum).forEach(function(seriesKey) {
307 // Skip 'x' - it's not a series 320 // Skip 'x' - it's not a series
308 if (seriesKey === 'x') 321 if (seriesKey === 'x')
309 return; 322 return;
310 323
311 if (multiSeriesDatum[seriesKey] === undefined) 324 if (multiSeriesDatum[seriesKey] === undefined)
312 return; 325 return;
313 326
314 if (!this.isDatumFieldSeries_(seriesKey)) 327 if (!this.isDatumFieldSeries_(seriesKey))
315 return; 328 return;
316 329
317 var singleSeriesDatum = {x: x}; 330 var singleSeriesDatum = {x: x};
318 singleSeriesDatum[seriesKey] = multiSeriesDatum[seriesKey]; 331 singleSeriesDatum[seriesKey] = multiSeriesDatum[seriesKey];
319 dataBySeriesKey[seriesKey].push(singleSeriesDatum); 332 dataBySeriesKey[seriesKey].push(singleSeriesDatum);
320 }, this); 333 }, this);
321 }, this); 334 }, this);
322 335
323 return dataBySeriesKey; 336 return dataBySeriesKey;
324 }, 337 },
325 338
326 getDataPointAtClientPoint_: function(clientX, clientY) { 339 getDataPointAtClientPoint_: function(clientX, clientY) {
327 var rect = this.getBoundingClientRect(); 340 var rect = this.getBoundingClientRect();
328 var margin = this.margin; 341 var x = clientX - rect.left - this.margin.left;
329 var x = clientX - rect.left - margin.left; 342 var y = clientY - rect.top - this.margin.top;
330 var y = clientY - rect.top - margin.top;
331 x = this.xScale_.invert(x); 343 x = this.xScale_.invert(x);
332 y = this.yScale_.invert(y); 344 y = this.yScale_.invert(y);
333 x = tr.b.clamp(x, this.xScale_.domain()[0], this.xScale_.domain()[1]); 345 x = tr.b.clamp(x, this.xScale_.domain()[0], this.xScale_.domain()[1]);
334 y = tr.b.clamp(y, this.yScale_.domain()[0], this.yScale_.domain()[1]); 346 y = tr.b.clamp(y, this.yScale_.domain()[0], this.yScale_.domain()[1]);
335 return {x: x, y: y}; 347 return {x: x, y: y};
336 }, 348 },
337 349
338 prepareDataEvent_: function(mouseEvent, dataEvent) { 350 prepareDataEvent_: function(mouseEvent, dataEvent) {
339 var dataPoint = this.getDataPointAtClientPoint_( 351 var dataPoint = this.getDataPointAtClientPoint_(
340 mouseEvent.clientX, mouseEvent.clientY); 352 mouseEvent.clientX, mouseEvent.clientY);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 this.dispatchEvent(dataEvent); 387 this.dispatchEvent(dataEvent);
376 Polymer.dom(this).classList.remove('updating-brushing-state'); 388 Polymer.dom(this).classList.remove('updating-brushing-state');
377 } 389 }
378 }; 390 };
379 391
380 return { 392 return {
381 ChartBase2D: ChartBase2D 393 ChartBase2D: ChartBase2D
382 }; 394 };
383 }); 395 });
384 </script> 396 </script>
OLDNEW
« no previous file with comments | « tracing/tracing/ui/base/chart_base.html ('k') | tracing/tracing/ui/base/drag_handle.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698