234 lines
7.1 KiB
JavaScript
234 lines
7.1 KiB
JavaScript
//
|
|
// To use this script, the HTML has to have only one element and this element's className
|
|
// should be equal to "Benchmark".
|
|
//
|
|
// This script forces rendering the HTML element many times by changing its position and its
|
|
// size. The size can be very big to test the case of displaying only a small portion of the
|
|
// element and measure how fast the display will be in this case.
|
|
//
|
|
|
|
function Point(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
|
|
Point.prototype = {
|
|
scale : function(other) {
|
|
return new Point(this.x * other.x, this.y * other.y);
|
|
},
|
|
add : function(other) {
|
|
return new Point(this.x + other.x, this.y + other.y);
|
|
},
|
|
subtract : function(other) {
|
|
return new Point(this.x - other.x, this.y - other.y);
|
|
},
|
|
isAlmostEqual : function(other, threshold) {
|
|
return Math.abs(this.x - other.x) < threshold && Math.abs(this.y - other.y) < threshold;
|
|
}
|
|
}
|
|
|
|
function Rectangle(position, size) {
|
|
this.position = position;
|
|
this.size = size;
|
|
}
|
|
|
|
Rectangle.prototype = {
|
|
left : function() {
|
|
return this.position.x;
|
|
},
|
|
top : function() {
|
|
return this.position.y;
|
|
},
|
|
width : function() {
|
|
return this.size.x;
|
|
},
|
|
height : function() {
|
|
return this.size.y;
|
|
},
|
|
isAlmostEqual : function(other, threshold) {
|
|
return this.position.isAlmostEqual(other.position, threshold) && this.size.isAlmostEqual(other.size, threshold);
|
|
}
|
|
}
|
|
|
|
function ElapsedTime() {
|
|
this._startTime = PerfTestRunner.now();
|
|
this._stopTime = this._startTime;
|
|
}
|
|
|
|
ElapsedTime.prototype = {
|
|
|
|
start : function() {
|
|
this._startTime = this._stopTime = PerfTestRunner.now();
|
|
},
|
|
|
|
stop : function() {
|
|
this._stopTime = PerfTestRunner.now();
|
|
},
|
|
|
|
isActive : function() {
|
|
return this._startTime == this._stopTime;
|
|
},
|
|
|
|
elapsed : function() {
|
|
return (this.isActive() ? PerfTestRunner.now() : this._stopTime) - this._startTime;
|
|
},
|
|
|
|
elapsedString : function() {
|
|
var tenths = this.elapsed() / 1000;
|
|
return tenths.toFixed(2) + " Seconds";
|
|
}
|
|
}
|
|
|
|
function AnimateMove(offset, zoomFactor, animateFactor) {
|
|
this.offset = offset;
|
|
this.zoomFactor = zoomFactor;
|
|
this.animateFactor = animateFactor;
|
|
}
|
|
|
|
AnimateMove.centerFactor = new Point(0.5, 0.5);
|
|
|
|
AnimateMove.prototype = {
|
|
|
|
targetRect : function(windowSize, sourceSize) {
|
|
var offset = this.offset.scale(this.zoomFactor);
|
|
var size = sourceSize.scale(this.zoomFactor);
|
|
var position = windowSize.subtract(size).scale(AnimateMove.centerFactor).subtract(offset);
|
|
return new Rectangle(position, size);
|
|
},
|
|
|
|
nextAnimateRect : function(targetRect, animateRect) {
|
|
var deltaPosition = targetRect.position.subtract(animateRect.position).scale(this.animateFactor);
|
|
var deltaSize = targetRect.size.subtract(animateRect.size).scale(this.animateFactor);
|
|
return new Rectangle(animateRect.position.add(deltaPosition), animateRect.size.add(deltaSize));
|
|
}
|
|
}
|
|
|
|
function ElementAnimator(element, windowSize, sourceSize) {
|
|
this._element = element;
|
|
this._windowSize = windowSize;
|
|
this._sourceSize = sourceSize;
|
|
|
|
this._animateMoves = [
|
|
new AnimateMove(new Point( 0, 0), new Point( 0.7, 0.7), new Point(1.00, 1.00)),
|
|
new AnimateMove(new Point(-500, -300), new Point(12.0, 12.0), new Point(0.50, 0.50)),
|
|
new AnimateMove(new Point( 100, -200), new Point( 0.1, 0.1), new Point(0.50, 0.50)),
|
|
new AnimateMove(new Point(-100, -300), new Point( 5.0, 5.0), new Point(0.20, 0.20)),
|
|
new AnimateMove(new Point( 0, 0), new Point( 0.7, 0.7), new Point(0.50, 0.50))
|
|
];
|
|
|
|
this._animateMoveIndex = 0;
|
|
this.nextTargetRect();
|
|
this._animateRect = this._targetRect;
|
|
this.moveToAnimateRect();
|
|
}
|
|
|
|
ElementAnimator.prototype = {
|
|
|
|
nextTargetRect : function() {
|
|
if (this._animateMoveIndex >= this._animateMoves.length)
|
|
return false;
|
|
|
|
this._targetRect = this._animateMoves[this._animateMoveIndex++].targetRect(this._windowSize, this._sourceSize);
|
|
return true;
|
|
},
|
|
|
|
nextAnimateRect : function() {
|
|
if (this._animateRect.isAlmostEqual(this._targetRect, 0.1))
|
|
return false;
|
|
|
|
this._animateRect = this._animateMoves[this._animateMoveIndex - 1].nextAnimateRect(this._targetRect, this._animateRect);
|
|
return true;
|
|
},
|
|
|
|
moveToAnimateRect : function() {
|
|
this._element.style.width = this._animateRect.width() + "px";
|
|
this._element.style.left = this._animateRect.left() + "px";
|
|
this._element.style.top = this._animateRect.top() + "px";
|
|
}
|
|
}
|
|
|
|
function RenderAnimator() {
|
|
this.element = document.getElementsByClassName("Benchmark")[0];
|
|
this.sourceSize = new Point(this.element.width, this.element.height);
|
|
|
|
// Tiling causes the rendering to slow down when the window width > 2000
|
|
this.windowSize = new Point(3000, 1500);
|
|
|
|
this.timer = document.createElement("span");
|
|
this.timer.className = "Timer";
|
|
document.body.appendChild(this.timer);
|
|
|
|
this.timeoutDelay = window.testRunner ? 0 : 500;
|
|
this.elapsedTime = new ElapsedTime();
|
|
this.elementAnimator = null;
|
|
}
|
|
|
|
RenderAnimator.prototype = {
|
|
|
|
nextRun : function() {
|
|
this.showElements(true);
|
|
this.elementAnimator = new ElementAnimator(this.element, this.windowSize, this.sourceSize);
|
|
|
|
var self = this;
|
|
setTimeout(function () {
|
|
self.elapsedTime.start();
|
|
self.moveToNextTargetRect();
|
|
}, this.timeoutDelay);
|
|
},
|
|
|
|
moveToNextTargetRect : function() {
|
|
if (this.elementAnimator.nextTargetRect())
|
|
setTimeout(this.moveToNextAnimateRect.bind(this), 0);
|
|
else {
|
|
this.elapsedTime.stop();
|
|
setTimeout(this.finishRun.bind(this), this.timeoutDelay);
|
|
}
|
|
},
|
|
|
|
moveToNextAnimateRect : function() {
|
|
this.timer.innerHTML = this.elapsedTime.elapsedString();
|
|
|
|
if (this.elementAnimator.nextAnimateRect())
|
|
window.requestAnimationFrame(this.moveToNextAnimateRect.bind(this));
|
|
else
|
|
this.moveToNextTargetRect();
|
|
|
|
this.elementAnimator.moveToAnimateRect();
|
|
},
|
|
|
|
finishRun : function() {
|
|
this.showElements(false);
|
|
|
|
var finishedTest = !PerfTestRunner.measureValueAsync(this.elapsedTime.elapsed());
|
|
PerfTestRunner.gc();
|
|
|
|
if (!finishedTest)
|
|
setTimeout(this.nextRun.bind(this), this.timeoutDelay * 2);
|
|
},
|
|
|
|
showElements : function(show) {
|
|
this.element.style.visibility = "visible";
|
|
this.element.style.opacity = show ? 1 : 0;
|
|
this.timer.style.opacity = show ? 1 : 0;
|
|
},
|
|
|
|
removeElements : function() {
|
|
this.element.parentNode.removeChild(this.element);
|
|
this.timer.parentNode.removeChild(this.timer);
|
|
this.element = null;
|
|
this.timer = null;
|
|
}
|
|
}
|
|
|
|
window.addEventListener("load", function() {
|
|
window.renderAnimator = new RenderAnimator();
|
|
window.renderAnimator.nextRun();
|
|
});
|
|
|
|
PerfTestRunner.prepareToMeasureValuesAsync({
|
|
unit: 'ms',
|
|
done: function () {
|
|
window.renderAnimator.removeElements();
|
|
}
|
|
});
|