function HBox(x, y, width, height, fillStyle, id) { this.x = x; this.y = y; this.width = width; this.height = height; this.fillStyle = fillStyle; //[51,51,51,1]; this.id = id; this.wide = (id ? WSDOM.Element.hasClass(id + '_target', 'wide') : false); this.openLeft = false; this.alwaysOpenLeft = false; this.xOffset = 0; } HBox.prototype.draw = function(ctx) { //var tmp = ctx.fillStyle //ctx.clearRect(this.x, this.y, this.width, this.height); ctx.fillStyle = "rgba(" + this.fillStyle.join(',') + ")"; ctx.beginPath(); ctx.rect(this.x + this.xOffset, this.y, this.width, this.height); ctx.fill(); //ctx.fillStyle = tmp; }; HBox.prototype.addToPath = function(ctx) { ctx.rect(this.x + this.xOffset, this.y, this.width, this.height); }; HBox.prototype.hitTest = function(x, y) { x -= this.xOffset; return (x >= this.x && x <= (this.x + this.width) && y >= this.y && y <= (this.y + this.height)); }; function HSystem() { var self = this; var repaintSystem = this.repaintSystem = function(){ self.repaint(); }; this.el = WSDOM.Element.get('canvas'); this.container = WSDOM.Element.get('servicesAnim'); this.context = this.el.getContext("2d"); this.interval = null; // handle for the animation interval this.offset = null; // used to calculate mouse position this.getOffset(); this.boxes = [ new HBox(-55, 0, 55, 55, [ 51,51,51,1], 'trimtabs'), // 0 new HBox(180, 60, 55, 55, [ 51,51,51,0], 'qsg'), // 1 new HBox(180, 120, 55, 55, [ 51,51,51,0], 'pacificepoch'), // 2 new HBox(240, 60, 55, 55, [ 51,51,51,0], 'isuppli'), // 3 new HBox(300, 0, 55, 55, [ 51,51,51,0], 'lusight'), // 4 new HBox(300, 60, 55, 55, [ 51,51,51,0], 'wsod'), // 5 new HBox(300, 120, 55, 55, [ 51,51,51,0], 'epocrates') // 6 - doesn't have to fades out anymore! ]; this.boxes[6].alwaysOpenLeft = true; // epocrates always opens to the left //this.boxes[10].alwaysOpenDown = true; // vantage always opens down this.activeBox = Math.round(Math.random() * (this.boxes.length - 2)); // last hovered box this.expandedBox = -1; // box that is expanded to show company data or -1 if none this.positions = [ // trimtabs, qsg,pacificepoch,isuppli,lusight, wsod, epocrates <- Positions for this box [ null, {y:180}, {x:480}, {y:180}, null, null, null ], // trimtabs expanded [ null, null, {y:240}, {y: 0}, null, null, null ], // qsg expanded [ null, null, null, null, null, null, {y:0} ], // investars expanded [ null, null,{l:true}, null, {x:420}, {y: 0}, {y:240} ], // isuppli expanded [ null,{l:true}, {y:180}, {x:660}, null, {y:180}, null ], // lusight expanded [ null, null,{l:true},{l:true}, null, null, {y:240} ], // wsod expanded [ null, null,{l:true}, null, null, null, null ] // epocrates expanded ]; for(var i = 0; i < this.boxes.length; i++) { if(this.boxes[i].id) { WSDOM.Events.add(WSDOM.Element.get(this.boxes[i].id + '_target'), 'click', this.expandHandler, this, i); WSDOM.Events.add(WSDOM.Element.get(this.boxes[i].id + '_close'), 'click', this.collapseHandler, this, i); } } WSDOM.Events.add(window, 'resize', this.getOffset, this); WSDOM.Events.add(window, 'scroll', this.getOffset, this); // set up mousemove event for the canvas this.mouseMoveEvent = WSDOM.Events.add(null, 'mousemove', this.mouseMoveHandler, this); this.enableMouseMove = function() { //self.mouseMoveEvent.addElement(self.el); self.mouseMoveEvent.addElement(document); }; this.disableMouseMove = function() { self.mouseMoveEvent.removeAllElements(); }; /* Phase 1: Single box slides in */ Animator.addAnimations([{ obj: this.boxes[0], property: 'x', to: 180, transition: 'easeOutCubic', duration: 1000 } ], repaintSystem, function() { /* Phase 2: The rest of the "H" fades in */ Animator.addAnimations([{ obj: self.boxes[1], property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 1000 }, { obj: self.boxes[2], property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 1000 }, { obj: self.boxes[3], property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 1000 }, { obj: self.boxes[4], property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 1000 }, { obj: self.boxes[5], property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 1000 }, { obj: self.boxes[6], property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 1000 } ], repaintSystem, function () { /* Phase 3: "H" breaks up, boxes go to final positions */ Animator.addAnimations([{ obj: self.boxes[0], property: 'x', to: 0, transition: 'easeOutCubic', duration: 1000 }, { obj: self.boxes[1], property: 'x', to: 120, transition: 'easeOutCubic', duration: 1000 }, { obj: self.boxes[2], property: 'x', to: 240, transition: 'easeOutCubic', duration: 1000 }, { obj: self.boxes[3], property: 'x', to: 300, transition: 'easeOutCubic', duration: 1000 }, { obj: self.boxes[4], property: 'x', to: 480, transition: 'easeOutCubic', duration: 1000 }, { obj: self.boxes[5], property: 'x', to: 600, transition: 'easeOutCubic', duration: 1000 }, { obj: self.boxes[6], property: 'x', to: 780, transition: 'easeOutCubic', duration: 1000 } ], repaintSystem, function() { /* Phase 4: Boxes go red, one opens up */ var box = self.boxes[self.activeBox]; var animations = [{ obj: box, property: 'width', to: (box.wide ? 235 : 175), transition: 'easeInSine', duration: 750 } ]; if(self.activeBox > 5) { // These boxes need to fade in if active animations.push({ obj: box, property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 750 }); } for(var i = 0, len = self.boxes.length; i < len; i++) { if(i != self.activeBox) { animations.push({ obj: self.boxes[i], property: 'fillStyle', to: [153,0,0,1], transition: 'easeInCirc', duration: 750 }); } } Animator.addAnimations(animations, repaintSystem, function() { WSDOM.Element.setXY(box.id + '_target', Math.round(box.x + box.xOffset), Math.round(box.y)); self.enableMouseMove(); }); }); }); }); } HSystem.prototype.getOffset = function() { this.offset = WSDOM.Element.getXY(this.el); var scroll = WSDOM.Viewport.getWindowScrollOffset(); this.offset.x -= scroll.x; this.offset.y -= scroll.y; }; HSystem.prototype.clear = function() { this.context.clearRect(0, 0, 840, 360); }; HSystem.prototype.repaint = function() { this.clear(); //this.context.fillStyle = "#900"; //this.context.beginPath(); for(var i = 0, len = this.boxes.length; i < len; i++) { if(i != this.expandedBox) this.boxes[i].draw(this.context); //this.boxes[i].addToPath(this.context); } if(this.expandedBox >= 0) this.boxes[this.expandedBox].draw(this.context); //this.context.fill(); }; HSystem.prototype.mouseMoveHandler = function(e) { var x = e.nativeEvent.clientX - this.offset.x; var y = e.nativeEvent.clientY - this.offset.y; for(var i = 0, len = this.boxes.length; i < len; i++) { if(this.boxes[i].hitTest(x, y)) { if(i != this.activeBox) this.activateBox(i); return; } } if(this.expandedBox >= 0 && this.expandedBox != this.activeBox) { this.deactivateBox(); this.activeBox = this.expandedBox; } }; HSystem.prototype.expandHandler = function(e, el, data){ e.cancel(); el.blur(); if(this.expandedBox >= 0) this.collapseCompany(this.expandedBox, data); else this.expandCompany(data); }; HSystem.prototype.collapseHandler = function(e, el, data){ e.cancel(); el.blur(); this.collapseCompany(this.expandedBox); }; HSystem.prototype.activateBox = function(idx) { if(idx == this.expandedBox) return; var box = this.boxes[idx]; Animator.cancelByHandle(box.id); var animations = [{ obj: box, properties: ['width'], to: [(box.wide ? 235 : 175)], transition: 'easeInSine', duration: 500, handle: box.id }, { obj: box, property: 'fillStyle', to: [51,51,51,1], transition: 'easeInCirc', duration: 500, handle: box.id } ]; if(box.openLeft || box.alwaysOpenLeft) { animations[0].properties.push('xOffset'); animations[0].to.push(box.wide ? -180 : -120); } this.deactivateBox(); var target = WSDOM.Element.get(this.boxes[idx].id + "_target"); var self = this; Animator.addAnimations(animations, this.repaintSystem, function() { WSDOM.Element.setXY(target, Math.round(box.x + box.xOffset), Math.round(box.y)); }); this.activeBox = idx; }; HSystem.prototype.deactivateBox = function() { if(this.activeBox == this.expandedBox) return; var activeBox = this.boxes[this.activeBox]; if(!Animator.isRunning()) { WSDOM.Element.setXY(activeBox.id + "_target", -9999, 0); } var animations = [{ obj: activeBox, properties: ['width'], to: [55], transition: 'easeInSine', duration: 500, handle: activeBox.id }, { obj: activeBox, property: 'fillStyle', to: [153,0,0,1], transition: 'easeInCirc', duration: 500, handle: activeBox.id }]; if(activeBox.openLeft || activeBox.alwaysOpenLeft) { animations[0].properties.push('xOffset'); animations[0].to.push(0); } Animator.addAnimations(animations, this.repaintSystem); }; HSystem.prototype.expandCompany = function(idx) { this.disableMouseMove(); var self = this; var box = this.boxes[idx]; // hide the link WSDOM.Element.setXY(box.id + '_target', -9999, 0); // set the expanding box's movements var animations = [{ obj: box, properties: ['width','height'], to: [475,175], transition: 'easeInSine', duration: 500 } ]; if(box.x > 300.1) { //.1 because of floating point errors box._origX = box.x; animations[0].properties.push('x'); animations[0].to.push(box.x - (box.wide ? 240 : 300)); } if(box.y > 120.1 && !box.alwaysOpenDown) { //.1 because of floating point errors box._origY = box.y; animations[0].properties.push('y'); animations[0].to.push(box.y - 120); } // position other boxes var positions = this.positions[idx]; var position = null; for(var i = 1; i < this.positions.length; i++) { // start at 1 because first box never moves if(position = positions[i]) { this.boxes[i].openLeft = !!position.l; if(position.x !== undefined) { this.boxes[i]._origX = this.boxes[i].x; animations.push({ obj: this.boxes[i], property: 'x', to: position.x, transition: 'easeInSine', duration: 500 }); } else if (position.y !== undefined) { this.boxes[i]._origY = this.boxes[i].y; animations.push({ obj: this.boxes[i], property: 'y', to: position.y, transition: 'easeInSine', duration: 500 }); } } } Animator.addAnimations(animations, this.repaintSystem, function() { // show the company info card after movement WSDOM.Element.setXY(box.id + '_card', Math.round(box.x + box.xOffset), Math.round(box.y)); self.enableMouseMove(); }); this.expandedBox = idx; }; HSystem.prototype.collapseCompany = function(idx, showIdx) { this.disableMouseMove(); var self = this; var box = this.boxes[idx]; // Find out if the expanded company is not active one and if the active one is moving var active = (idx == this.activeBox); var activeBox = null; if(!active) { activeBox = this.boxes[this.activeBox]; if(!activeBox._origX && !activeBox._origY && !activeBox.openLeft) activeBox = null; } // hide the company info card WSDOM.Element.setXY(box.id + '_card', -9999, 0); // hide the active link if(activeBox) WSDOM.Element.setXY(activeBox.id + '_target', -9999, 0); // set the collapsing box's movements var animations = [{ obj: box, properties: ['width','height'], to: [(active ? (box.wide ? 235 : 175) : 55),55], transition: 'easeInSine', duration: 500 } ]; if(!active) { animations.push({ obj: box, property: 'fillStyle', to: [153,0,0,1], transition: 'easeInCirc', duration: 500 }); } if(box._origX) { animations[0].properties.push('x'); animations[0].to.push(box._origX); delete box._origX; } if(box._origY) { animations[0].properties.push('y'); animations[0].to.push(box._origY); delete box._origY; } // return other boxes to original position for(var i = 1; i < this.boxes.length; i++) { // start at 1 because first box never moves if(this.boxes[i].openLeft || (this.boxes[i].alwaysOpenLeft && showIdx != i && this.activeBox != i)) { animations.push({ obj: this.boxes[i], property: 'xOffset', to: 0, transition: 'easeInSine', duration: 500 }); this.boxes[i].openLeft = false; } if(undefined !== this.boxes[i]._origX) { animations.push({ obj: this.boxes[i], property: 'x', to: this.boxes[i]._origX, transition: 'easeInSine', duration: 500 }); delete this.boxes[i]._origX; } else if(undefined !== this.boxes[i]._origY) { animations.push({ obj: this.boxes[i], property: 'y', to: this.boxes[i]._origY, transition: 'easeInSine', duration: 500 }); delete this.boxes[i]._origY; } } Animator.addAnimations(animations, this.repaintSystem, function() { // show the link after movement if (active) { WSDOM.Element.setXY(box.id + '_target', Math.round(box.x + box.xOffset), Math.round(box.y)); } else if(activeBox) { WSDOM.Element.setXY(activeBox.id + '_target', Math.round(activeBox.x + activeBox.xOffset), Math.round(activeBox.y)); } if(showIdx !== undefined) { self.expandCompany(showIdx); self.expandedBox = showIdx; } else { self.enableMouseMove(); self.expandedBox = -1; } }); }; var system = null; function startAnimation() { system = new HSystem(); } WSDOM.Events.add(window, 'load', startAnimation);