1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @constructor
* @param {number} width
* @param {number} height
* @param {number} marginTop
* @param {number} controlPointRadius
* @param {boolean} linearLine
*/
WebInspector.BezierUI = function(width, height, marginTop, controlPointRadius, linearLine)
{
this.width = width;
this.height = height;
this.marginTop = marginTop;
this.radius = controlPointRadius;
this.linearLine = linearLine;
}
WebInspector.BezierUI.prototype = {
/**
* @return {number}
*/
curveWidth: function()
{
return this.width - this.radius * 2;
},
/**
* @return {number}
*/
curveHeight: function()
{
return this.height - this.radius * 2 - this.marginTop * 2;
},
/**
* @param {!Element} parentElement
* @param {string} className
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
*/
_drawLine: function(parentElement, className, x1, y1, x2, y2)
{
var line = parentElement.createSVGChild("line", className);
line.setAttribute("x1", x1 + this.radius);
line.setAttribute("y1", y1 + this.radius + this.marginTop);
line.setAttribute("x2", x2 + this.radius);
line.setAttribute("y2", y2 + this.radius + this.marginTop);
},
/**
* @param {!Element} parentElement
* @param {number} startX
* @param {number} startY
* @param {number} controlX
* @param {number} controlY
*/
_drawControlPoints: function(parentElement, startX, startY, controlX, controlY)
{
this._drawLine(parentElement, "bezier-control-line", startX, startY, controlX, controlY);
var circle = parentElement.createSVGChild("circle", "bezier-control-circle");
circle.setAttribute("cx", controlX + this.radius);
circle.setAttribute("cy", controlY + this.radius + this.marginTop);
circle.setAttribute("r", this.radius);
},
/**
* @param {?WebInspector.Geometry.CubicBezier} bezier
* @param {!Element} svg
*/
drawCurve: function(bezier, svg)
{
if (!bezier)
return;
var width = this.curveWidth();
var height = this.curveHeight();
svg.setAttribute("width", this.width);
svg.setAttribute("height", this.height);
svg.removeChildren();
var group = svg.createSVGChild("g");
if (this.linearLine)
this._drawLine(group, "linear-line", 0, height, width, 0);
var curve = group.createSVGChild("path", "bezier-path");
var curvePoints = [
new WebInspector.Geometry.Point(bezier.controlPoints[0].x * width + this.radius, (1 - bezier.controlPoints[0].y) * height + this.radius + this.marginTop),
new WebInspector.Geometry.Point(bezier.controlPoints[1].x * width + this.radius, (1 - bezier.controlPoints[1].y) * height + this.radius + this.marginTop),
new WebInspector.Geometry.Point(width + this.radius, this.marginTop + this.radius)
];
curve.setAttribute("d", "M" + this.radius + "," + (height + this.radius + this.marginTop) + " C" + curvePoints.join(" "));
this._drawControlPoints(group, 0, height, bezier.controlPoints[0].x * width, (1 - bezier.controlPoints[0].y) * height);
this._drawControlPoints(group, width, 0, bezier.controlPoints[1].x * width, (1 - bezier.controlPoints[1].y) * height);
}
}
WebInspector.BezierUI.Height = 26;
/**
* @param {!WebInspector.Geometry.CubicBezier} bezier
* @param {!Element} path
* @param {number} width
*/
WebInspector.BezierUI.drawVelocityChart = function(bezier, path, width)
{
var height = WebInspector.BezierUI.Height;
var pathBuilder = ["M", 0, height];
/** @const */ var sampleSize = 1 / 40;
var prev = bezier.evaluateAt(0);
for (var t = sampleSize; t < 1 + sampleSize; t += sampleSize) {
var current = bezier.evaluateAt(t);
var slope = (current.y - prev.y) / (current.x - prev.x);
var weightedX = prev.x * (1 - t) + current.x * t;
slope = Math.tanh(slope / 1.5); // Normalise slope
pathBuilder = pathBuilder.concat(["L", (weightedX * width).toFixed(2), (height - slope * height).toFixed(2) ]);
prev = current;
}
pathBuilder = pathBuilder.concat(["L", width.toFixed(2), height, "Z"]);
path.setAttribute("d", pathBuilder.join(" "));
}
|