123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659 |
- topSuite("Ext.draw.sprite.Sprite", ['Ext.draw.*'], function() {
- beforeEach(function() {
- // Silence warnings regarding Sencha download server
- spyOn(Ext.log, 'warn');
- });
- describe('setAttributes', function () {
- var draw;
- afterEach(function () {
- Ext.destroy(draw);
- });
- it('should filter out attributes properly', function () {
- // This actually tests many things: the setAttributes method of the sprite,
- // the abstract and Animation modifiers and the Animator class.
- var animationend;
- draw = new Ext.draw.Container({
- renderTo: document.body,
- width: 200,
- height: 200
- });
- var surface = draw.getSurface();
- var circle = new Ext.draw.sprite.Circle({
- r: 10,
- cx: 100,
- cy: 100,
- fillStyle: 'red',
- strokeStyle: 'none'
- });
- var animation = circle.getAnimation();
- animation.setDuration(250);
- animation.on('animationend', function () {
- animationend = true;
- });
- surface.add(circle);
- circle.setAttributes({
- r: 90
- });
- surface.renderFrame();
- waitsFor(function () {
- return animationend;
- });
- runs(function () {
- expect(circle.attr.r).toBe(90);
- animationend = false;
- circle.setAttributes({
- r: 50
- });
- // The call below should compare the value being set with the target value
- // at the end of animation, not the current value, which is still 90.
- // If this is buggy, the attribute won't be set and the animation to 50
- // will be performed instead.
- circle.setAttributes({
- r: 90
- });
- surface.renderFrame();
- });
- waitsFor(function () {
- return animationend;
- });
- runs(function () {
- expect(circle.attr.r).toBe(90);
- });
- });
- });
- describe('surface', function () {
- var surface;
- it('should remove itself from the old surface', function () {
- surface = new Ext.draw.Surface({
- items: {
- type: 'rect',
- id: 'rect',
- x: 50,
- y: 50,
- width: 100,
- height: 100,
- fillStyle: 'orange'
- }
- });
- var sprite = surface.get('rect');
- expect(surface.getItems().length).toBe(1);
- sprite.setSurface(null);
- expect(surface.getItems().length).toBe(0);
- });
- afterEach(function () {
- Ext.destroy(surface);
- });
- });
- describe('transformation matrix calculation', function () {
- describe('default centers of scaling and rotation', function () {
- it('should apply transformation in the following order: scale, rotate, translate', function () {
- var theta = Math.PI / 2,
- sin = Math.sin(theta),
- cos = Math.cos(theta),
- left = 100,
- top = 100,
- width = 100,
- height = 100,
- sx = 2,
- sy = 0.5,
- tx = 100,
- ty = 50,
- centerX = left + width / 2,
- centerY = top + height / 2;
- var rect = new Ext.draw.sprite.Rect({
- x: left,
- y: top,
- width: width,
- height: height,
- rotationRads: theta,
- scalingX: sx,
- scalingY: sy,
- translationX: tx,
- translationY: ty
- });
- var referenceMatrix = [
- cos * sx, sin * sx,
- -sin * sy, cos * sy,
- cos * (centerX * (1 - sx) - centerX) - sin * (centerY * (1 - sy) - centerY) + centerX + tx,
- sin * (centerX * (1 - sx) - centerX) + cos * (centerY * (1 - sy) - centerY) + centerY + ty
- ];
- rect.applyTransformations(true);
- expect(rect.attr.matrix.elements).toEqual(referenceMatrix);
- });
- });
- describe('custom centers of scaling and rotation', function () {
- it('should apply transformation in the following order: scale, rotate, translate', function () {
- var theta = Math.PI / 2,
- sin = Math.sin(theta),
- cos = Math.cos(theta),
- left = 100,
- top = 100,
- width = 100,
- height = 100,
- sx = 2,
- sy = 0.5,
- tx = 100,
- ty = 50,
- scalingCenterX = 50,
- scalingCenterY = 50,
- rotationCenterX = 150,
- rotationCenterY = 150;
- var rect = new Ext.draw.sprite.Rect({
- x: left,
- y: top,
- width: width,
- height: height,
- rotationRads: theta,
- scalingX: sx,
- scalingY: sy,
- translationX: tx,
- translationY: ty,
- rotationCenterX: rotationCenterX,
- rotationCenterY: rotationCenterY,
- scalingCenterX: scalingCenterX,
- scalingCenterY: scalingCenterY
- });
- var referenceMatrix = [
- cos * sx, sin * sx,
- -sin * sy, cos * sy,
- cos * (scalingCenterX * (1 - sx) - rotationCenterX) - sin * (scalingCenterY * (1 - sy) - rotationCenterY) + rotationCenterX + tx,
- sin * (scalingCenterX * (1 - sx) - rotationCenterX) + cos * (scalingCenterY * (1 - sy) - rotationCenterY) + rotationCenterY + ty
- ];
- rect.applyTransformations(true);
- expect(rect.attr.matrix.elements).toEqual(referenceMatrix);
- });
- });
- });
- describe('setTransform', function () {
- // This is a result of scaling by (2.5, 7.5), rotating by Math.PI/4 and translating by (3,4).
- var elements = [1.76776695, 1.76776695, -5.30330086, 5.30330086, 3, 4],
- sprite;
- beforeEach(function () {
- sprite = new Ext.draw.sprite.Rect();
- });
- afterEach(function () {
- Ext.destroy(sprite);
- });
- it("should use the given elements for the transformation matrix of the sprite", function () {
- sprite.setTransform(elements);
- var matrixElements = sprite.attr.matrix.elements;
- expect(matrixElements).toEqual(elements);
- });
- it("should mark the sprite and its parent as dirty", function () {
- var drawContainer = new Ext.draw.Container({
- renderTo: Ext.getBody(),
- width: 200,
- height: 200
- });
- var surface = drawContainer.getSurface();
- expect(surface.getDirty()).toBe(false);
- surface.add(sprite);
- expect(surface.getDirty()).toBe(true);
- surface.renderFrame();
- expect(surface.getDirty()).toBe(false);
- sprite.setTransform(elements);
- expect(sprite.attr.dirty).toBe(true);
- expect(sprite.getParent().getDirty()).toBe(true);
- drawContainer.destroy();
- });
- it("should properly calculate the inverse matrix from the given matrix", function () {
- sprite.setTransform(elements);
- var inverseMatrixElements = sprite.attr.inverseMatrix.elements,
- precision = 8;
- expect(inverseMatrixElements[0]).toBeCloseTo(0.28284271, precision);
- expect(inverseMatrixElements[1]).toBeCloseTo(-0.0942809, precision);
- expect(inverseMatrixElements[2]).toBeCloseTo(0.28284271, precision);
- expect(inverseMatrixElements[3]).toBeCloseTo(0.0942809, precision);
- expect(inverseMatrixElements[4]).toBeCloseTo(-1.97989899, precision);
- expect(inverseMatrixElements[5]).toBeCloseTo(-0.0942809, precision);
- });
- it("should mark bbox transform as dirty", function () {
- sprite.setTransform(elements);
- expect(sprite.attr.bbox.transform.dirty).toBe(true);
- });
- it("should not update the transformation attributes by default", function () {
- var attr = sprite.attr,
- rotationRads = attr.rotationRads,
- rotationCenterX = attr.rotationCenterX,
- rotationCenterY = attr.rotationCenterY,
- scalingX = attr.scalingX,
- scalingY = attr.scalingY,
- scalingCenterX = attr.scalingCenterX,
- scalingCenterY = attr.scalingCenterY,
- translationX = attr.translationX,
- translationY = attr.translationY;
- sprite.setTransform(elements);
- expect(attr.rotationRads).toEqual(rotationRads);
- expect(attr.rotationCenterX).toEqual(rotationCenterX);
- expect(attr.rotationCenterY).toEqual(rotationCenterY);
- expect(attr.scalingX).toEqual(scalingX);
- expect(attr.scalingY).toEqual(scalingY);
- expect(attr.scalingCenterX).toEqual(scalingCenterX);
- expect(attr.scalingCenterY).toEqual(scalingCenterY);
- expect(attr.translationX).toEqual(translationX);
- expect(attr.translationY).toEqual(translationY);
- });
- it("should update the transformation attributes, if explicitly asked", function () {
- var attr = sprite.attr,
- precision = 8;
- sprite.setTransform(elements, true);
- expect(attr.rotationRads).toBeCloseTo(Math.PI / 4, precision);
- expect(attr.rotationCenterX).toEqual(0);
- expect(attr.rotationCenterY).toEqual(0);
- expect(attr.scalingX).toBeCloseTo(2.5, precision);
- expect(attr.scalingY).toBeCloseTo(7.5, precision);
- expect(attr.scalingCenterX).toEqual(0);
- expect(attr.scalingCenterY).toEqual(0);
- expect(attr.translationX).toEqual(3);
- expect(attr.translationY).toEqual(4);
- });
- it("should not modify the given array", function () {
- sprite.setTransform(elements);
- sprite.attr.matrix.rotate(Math.PI / 4);
- expect(elements).toEqual([1.76776695, 1.76776695, -5.30330086, 5.30330086, 3, 4]);
- });
- it("should return the sprite itself", function () {
- var result = sprite.transform([1, 0, 0, 1, 100, 100]);
- expect(result).toEqual(sprite);
- });
- });
- describe('resetTransform', function () {
- var spriteConfig = {
- type: 'rect',
- x: 0,
- y: 0,
- width: 100,
- height: 100,
- rotationCenterX: 0,
- rotationCenterY: 0,
- rotationRads: Math.PI / 3,
- scalingCenterX: 0,
- scalingCenterY: 0,
- scalingX: 2,
- scalingY: 3,
- translationX: 50,
- translationY: 50
- };
- it("should mark the sprite and its parent as dirty", function () {
- var drawContainer = new Ext.draw.Container({
- renderTo: Ext.getBody(),
- width: 200,
- height: 200
- });
- var surface = drawContainer.getSurface();
- expect(surface.getDirty()).toBe(false);
- var sprite = surface.add(spriteConfig);
- expect(surface.getDirty()).toBe(true);
- surface.renderFrame();
- expect(surface.getDirty()).toBe(false);
- sprite.resetTransform();
- expect(sprite.attr.dirty).toBe(true);
- expect(sprite.getParent().getDirty()).toBe(true);
- drawContainer.destroy();
- });
- it("should reset the transformation matrix and its reverse to the identity matrix", function () {
- var sprite = new Ext.draw.sprite.Rect(spriteConfig),
- identityMatrixElements = [1, 0, 0, 1, 0, 0];
- sprite.applyTransformations(true);
- expect(sprite.attr.matrix.elements).not.toEqual(identityMatrixElements);
- sprite.resetTransform();
- expect(sprite.attr.matrix.elements).toEqual(identityMatrixElements);
- expect(sprite.attr.inverseMatrix.elements).toEqual(identityMatrixElements);
- sprite.destroy();
- });
- it("should return the sprite itself", function () {
- var sprite = new Ext.draw.sprite.Rect(),
- result = sprite.transform([1, 0, 0, 1, 100, 100]);
- expect(result).toEqual(sprite);
- sprite.destroy();
- });
- });
- describe('transform', function () {
- it("should multiply the given matrix with the current transformation matrix", function () {
- var sprite = new Ext.draw.sprite.Rect(),
- precision = 12;
- sprite.attr.matrix.elements = [1, 2, 3, 4, 5, 6];
- sprite.transform([1, 2, 3, 4, 5, 6]);
- expect(sprite.attr.matrix.elements).toEqual([7, 10, 15, 22, 28, 40]);
- var inverseMatrixElements = sprite.attr.inverseMatrix.elements;
- expect(inverseMatrixElements[0]).toBeCloseTo(5.5, precision);
- expect(inverseMatrixElements[1]).toBeCloseTo(-2.5, precision);
- expect(inverseMatrixElements[2]).toBeCloseTo(-3.75, precision);
- expect(inverseMatrixElements[3]).toBeCloseTo(1.75, precision);
- expect(inverseMatrixElements[4]).toBeCloseTo(-4, precision);
- expect(inverseMatrixElements[5]).toBeCloseTo(0, precision);
- });
- it("should pre-multiply the current matrix with the given matrix", function () {
- var sprite = new Ext.draw.sprite.Rect(),
- scale = [2, 0, 0, 3, 0, 0],
- translate = [1, 0, 0, 1, 100, 100],
- p = [2, 4],
- tp;
- // Initially, sprite's matrix is identity matrix.
- // First scale the grid, then translate.
- // S * T * I = identity.prepend(translate).prepend(scale)
- sprite.transform(translate).transform(scale);
- expect(sprite.attr.matrix.elements).toEqual([2, 0, 0, 3, 200, 300]);
- tp = sprite.attr.matrix.transformPoint(p);
- // Transformed point in original grid coordinates.
- expect(tp).toEqual([204, 312]);
- sprite.resetTransform();
- // First translate the grid, then scale.
- // T * S * I = identity.prepend(scale).prepend(translate)
- sprite.transform(scale).transform(translate);
- expect(sprite.attr.matrix.elements).toEqual([2, 0, 0, 3, 100, 100]);
- tp = sprite.attr.matrix.transformPoint(p);
- expect(tp).toEqual([104, 112]);
- sprite.destroy();
- });
- it("should return the sprite itself", function () {
- var sprite = new Ext.draw.sprite.Rect(),
- result = sprite.transform([1, 0, 0, 1, 100, 100]);
- expect(result).toEqual(sprite);
- sprite.destroy();
- });
- });
- describe('remove', function () {
- it("should remove itself from the surface, returning itself or null (if already removed)", function () {
- var surface = new Ext.draw.Surface({}),
- sprite = new Ext.draw.sprite.Rect({}),
- id = sprite.getId(),
- result;
- surface.add(sprite);
- result = sprite.remove();
- expect(surface.getItems().length).toBe(0);
- expect(surface.get(id)).toBe(undefined);
- expect(result).toEqual(sprite);
- result = sprite.remove(); // sprite with no surface, expect not to throw
- expect(result).toBe(null);
- sprite.destroy();
- surface.destroy();
- });
- });
- describe('destroy', function () {
- it("should remove itself from the surface", function () {
- var surface = new Ext.draw.Surface({}),
- sprite = new Ext.draw.sprite.Rect({}),
- id = sprite.getId();
- surface.add(sprite);
- sprite.destroy();
- expect(surface.getItems().length).toBe(0);
- expect(surface.get(id)).toBe(undefined);
- surface.destroy();
- });
- });
- describe("isVisible", function () {
- var none = 'none',
- rgba_none = 'rgba(0,0,0,0)',
- sprite, surface, container;
- beforeEach(function () {
- container = new Ext.draw.Container({
- renderTo: Ext.getBody()
- });
- surface = new Ext.draw.Surface();
- sprite = new Ext.draw.sprite.Rect({
- hidden: false,
- globalAlpha: 1,
- fillOpacity: 1,
- strokeOpacity: 1,
- fillStyle: 'red',
- strokeStyle: 'red'
- });
- surface.add(sprite);
- container.add(surface);
- });
- afterEach(function () {
- Ext.destroy(sprite, surface, container);
- });
- it("should return true if the sprite belongs to a visible parent, false otherwise", function () {
- expect(sprite.isVisible()).toBe(true);
- surface.remove(sprite);
- expect(sprite.isVisible()).toBe(false);
- var instancing = new Ext.draw.sprite.Instancing({
- template: sprite
- });
- surface.add(instancing);
- expect(sprite.isVisible()).toBe(true);
- instancing.destroy();
- });
- it("should return false if the sprite belongs to a parent that doesn't belong to a surface", function () {
- var instancing = new Ext.draw.sprite.Instancing({
- template: sprite
- });
- expect(sprite.isVisible()).toBe(false);
- });
- it("should return false in case the sprite is hidden", function () {
- sprite.hide();
- expect(sprite.isVisible()).toBe(false);
- });
- it("should return false in case the sprite has no fillStyle and strokeStyle, true otherwise", function () {
- sprite.setAttributes({
- fillStyle: none
- });
- expect(sprite.isVisible()).toBe(true);
- sprite.setAttributes({
- fillStyle: rgba_none
- });
- expect(sprite.isVisible()).toBe(true);
- sprite.setAttributes({
- fillStyle: 'red',
- strokeStyle: none
- });
- expect(sprite.isVisible()).toBe(true);
- sprite.setAttributes({
- strokeStyle: rgba_none
- });
- expect(sprite.isVisible()).toBe(true);
- sprite.setAttributes({
- fillStyle: none,
- strokeStyle: none
- });
- expect(sprite.isVisible()).toBe(false);
- sprite.setAttributes({
- fillStyle: none,
- strokeStyle: rgba_none
- });
- expect(sprite.isVisible()).toBe(false);
- sprite.setAttributes({
- fillStyle: rgba_none,
- strokeStyle: none
- });
- expect(sprite.isVisible()).toBe(false);
- sprite.setAttributes({
- fillStyle: rgba_none,
- strokeStyle: rgba_none
- });
- expect(sprite.isVisible()).toBe(false);
- });
- it("should return false if the globalAlpha attribute is zero", function () {
- sprite.setAttributes({
- globalAlpha: 0
- });
- expect(sprite.isVisible()).toBe(false);
- });
- it("should return false if both fill and stroke are completely transparent, true otherwise", function () {
- sprite.setAttributes({
- fillOpacity: 0,
- strokeOpacity: 0
- });
- expect(sprite.isVisible()).toBe(false);
- sprite.setAttributes({
- fillOpacity: 0,
- strokeOpacity: 0.01
- });
- expect(sprite.isVisible()).toBe(true);
- sprite.setAttributes({
- fillOpacity: 0.01,
- strokeOpacity: 0
- });
- expect(sprite.isVisible()).toBe(true);
- });
- });
- describe("hitTest", function () {
- var sprite, surface, container;
- beforeEach(function () {
- container = new Ext.draw.Container({
- renderTo: Ext.getBody()
- });
- surface = new Ext.draw.Surface();
- sprite = new Ext.draw.sprite.Circle({
- hidden: false,
- globalAlpha: 1,
- fillOpacity: 1,
- strokeOpacity: 1,
- fillStyle: 'red',
- strokeStyle: 'red',
- r: 100,
- cx: 100,
- cy: 100
- });
- surface.add(sprite);
- container.add(surface);
- });
- afterEach(function () {
- Ext.destroy(sprite, surface, container);
- });
- it("should return an object with the 'sprite' property set to the sprite itself, " +
- "if the sprite is visible and its bounding box is hit", function () {
- // Testing hitTest method of the abstract Sprite class.
- // Even though, (10,10) is not inside the circle, it's inside it's bounding box.
- var result = Ext.draw.sprite.Sprite.prototype.hitTest.call(sprite, [10, 10]);
- expect(result && result.sprite).toBe(sprite);
- });
- it("should return null, if the sprite's bounding box is hit, but the sprite is not visible", function () {
- var originalMethod = sprite.isVisible;
- sprite.isVisible = function () { return false; };
- var result = Ext.draw.sprite.Sprite.prototype.hitTest.call(sprite, [10, 10]);
- expect(result).toBe(null);
- sprite.isVisible = originalMethod;
- });
- it("should return null, if the sprite is visible, but it's bounding box is not hit", function () {
- var result = Ext.draw.sprite.Sprite.prototype.hitTest.call(sprite, [210, 210]);
- expect(result).toBe(null);
- });
- });
- describe("getAnimation", function () {
- it("should return the stored reference to the sprite's animation modifier", function () {
- var sprite = new Ext.draw.sprite.Rect();
- expect(sprite.getAnimation()).toEqual(sprite.modifiers.animation);
- });
- });
- describe("setAnimation", function () {
- it("should set the config of the Animation modifier of a sprite", function () {
- var sprite = new Ext.draw.sprite.Rect();
- var config = {
- duration: 2000,
- easing: 'bounceOut',
- customEasings: {
- x: 'linear'
- },
- customDurations: {
- y: 1000
- }
- };
- sprite.setAnimation(config);
- var actualConfig = sprite.modifiers.animation.getInitialConfig();
- expect(actualConfig.duration).toEqual(config.duration);
- expect(actualConfig.easing).toEqual(config.easing);
- expect(actualConfig.customEasings).toEqual(config.customEasings);
- expect(actualConfig.customDurations).toEqual(config.customDurations);
- });
- });
- });
|