From 454bcdca0ba186f065c00dbda85b77414558e290 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Mon, 19 Sep 2016 16:11:15 -0400 Subject: [PATCH] Add confetti effect for when you finish the wizard --- .../wizard/components/wizard-canvas.js.es6 | 166 ++++++++++++++++++ .../wizard/controllers/application.js.es6 | 10 ++ .../javascripts/wizard/routes/step.js.es6 | 2 + .../wizard/templates/application.hbs | 4 + app/assets/stylesheets/wizard.scss | 9 + 5 files changed, 191 insertions(+) create mode 100644 app/assets/javascripts/wizard/components/wizard-canvas.js.es6 create mode 100644 app/assets/javascripts/wizard/controllers/application.js.es6 diff --git a/app/assets/javascripts/wizard/components/wizard-canvas.js.es6 b/app/assets/javascripts/wizard/components/wizard-canvas.js.es6 new file mode 100644 index 00000000000..269bf7b9e9c --- /dev/null +++ b/app/assets/javascripts/wizard/components/wizard-canvas.js.es6 @@ -0,0 +1,166 @@ +const MAX_PARTICLES = 100; + +const SIZE = 144; + +let width, height; + +const COLORS = ['red', 'black', 'blue', 'purple', 'brown', 'green']; + +class Particle { + constructor() { + this.reset(); + this.y = (Math.random() * (height + SIZE)) - SIZE; + } + + reset() { + this.y = -SIZE; + this.origX = Math.random() * width; + this.speed = 1 + Math.random(); + this.ang = Math.random() * 2 * Math.PI; + this.scale = (Math.random() * 0.5); + this.radius = (Math.random() * 25) + 25; + this.color = COLORS[Math.floor(Math.random() * COLORS.length)]; + } + + move() { + this.y += this.speed; + + if (this.y > height + SIZE) { + this.reset(); + } + + this.ang += this.speed / 30.0; + if (this.ang > 2 * Math.PI) { + this.ang = 0; + } + + this.x = this.origX + (this.radius * Math.sin(this.ang)); + } +} + +export default Ember.Component.extend({ + classNames: ['wizard-canvas'], + tagName: 'canvas', + ctx: null, + ready: false, + particles: null, + + didInsertElement() { + this._super(); + + const canvas = this.$()[0]; + this.ctx = canvas.getContext('2d'); + this.resized(); + + this.particles = []; + for (let i=0; i this.resized()); + }, + + willDestroyElement() { + this._super(); + $(window).off('resize.wizard'); + }, + + resized() { + width = $(window).width(); + height = $(window).height(); + + const canvas = this.$()[0]; + canvas.width = width; + canvas.height = height; + }, + + paint() { + if (this.isDestroying || this.isDestroyed || !this.ready) { return; } + + const { ctx } = this; + ctx.clearRect(0, 0, width, height); + + this.particles.forEach(particle => { + particle.move(); + this.drawParticle(particle); + }); + + window.requestAnimationFrame(() => this.paint()); + }, + + + drawParticle(p) { + const c = this.ctx; + + c.save(); + c.translate(p.x - SIZE, p.y - SIZE); + c.scale(p.scale, p.scale); + c.fillStyle = p.color; + c.strokeStyle = p.color; + c.globalAlpha = "1.0"; + c.lineWidth = "1"; + c.lineCap = "butt"; + c.lineJoin = "round"; + c.mitterLimit = "1"; + c.beginPath(); + c.moveTo(97.90, 194.90); + c.lineTo(103.50, 162.90); + c.bezierCurveTo(88.70, 152, 84.20, 139.70, 90.20, 126.30); + c.bezierCurveTo(99.50, 105.60, 124.60, 89.60, 159.70, 100.40); + c.lineTo(159.70, 100.40); + c.bezierCurveTo(175.90, 105.40, 186.40, 111.20, 192.60, 118.50); + c.bezierCurveTo(200, 127.20, 201.60, 138.40, 197.50, 152.70); + c.bezierCurveTo(194, 165, 187.40, 173.60, 177.90, 178.30); + c.bezierCurveTo(165.60, 184.40, 148.40, 183.70, 129.40, 176.30); + c.bezierCurveTo(127.70, 175.60, 126, 174.90, 124.40, 174.20); + c.lineTo(97.90, 194.90); + c.closePath(); + c.moveTo(138, 99.30); + c.bezierCurveTo(115.40, 99.30, 99.30, 111.90, 92.40, 127.30); + c.bezierCurveTo(86.80, 139.70, 91.20, 151.20, 105.50, 161.50); + c.lineTo(106.10, 161.90); + c.lineTo(101.20, 189.40); + c.lineTo(124, 171.70); + c.lineTo(124.60, 172); + c.bezierCurveTo(126.40, 172.80, 128.30, 173.60, 130.20, 174.30); + c.bezierCurveTo(148.60, 181.40, 165.10, 182.20, 176.80, 176.40); + c.bezierCurveTo(185.70, 172, 191.90, 163.90, 195.20, 152.20); + c.bezierCurveTo(202.40, 127.20, 191.90, 112.80, 159, 102.70); + c.lineTo(159, 102.70); + c.bezierCurveTo(151.60, 100.30, 144.50, 99.30, 138, 99.30); + c.closePath(); + c.fill(); + c.stroke(); + c.beginPath(); + c.moveTo(115.70, 136.20); + c.bezierCurveTo(115.70, 137.90, 115, 139.30, 113.30, 139.30); + c.bezierCurveTo(111.60, 139.30, 110.20, 137.90, 110.20, 136.20); + c.bezierCurveTo(110.20, 134.50, 111.60, 133.10, 113.30, 133.10); + c.bezierCurveTo(115, 133, 115.70, 134.40, 115.70, 136.20); + c.closePath(); + c.fill(); + c.stroke(); + c.beginPath(); + c.moveTo(145.80, 141.60); + c.bezierCurveTo(145.80, 143.30, 144.40, 144.10, 142.70, 144.10); + c.bezierCurveTo(141, 144.10, 139.60, 143.40, 139.60, 141.60); + c.bezierCurveTo(139.60, 141.60, 141, 138.50, 142.70, 138.50); + c.bezierCurveTo(144.40, 138.50, 145.80, 139.90, 145.80, 141.60); + c.closePath(); + c.fill(); + c.stroke(); + c.beginPath(); + c.moveTo(171.60, 146.80); + c.bezierCurveTo(171.60, 148.50, 171, 149.90, 169.20, 149.90); + c.bezierCurveTo(167.50, 149.90, 166.10, 148.50, 166.10, 146.80); + c.bezierCurveTo(166.10, 145.10, 167.50, 143.70, 169.20, 143.70); + c.bezierCurveTo(171, 143.60, 171.60, 145, 171.60, 146.80); + c.closePath(); + c.fill(); + c.stroke(); + c.restore(); + } +}); diff --git a/app/assets/javascripts/wizard/controllers/application.js.es6 b/app/assets/javascripts/wizard/controllers/application.js.es6 new file mode 100644 index 00000000000..6592eb9e5f4 --- /dev/null +++ b/app/assets/javascripts/wizard/controllers/application.js.es6 @@ -0,0 +1,10 @@ +import computed from 'ember-addons/ember-computed-decorators'; + +export default Ember.Controller.extend({ + currentStepId: null, + + @computed('currentStepId') + showCanvas(currentStepId) { + return currentStepId === 'finished'; + } +}); diff --git a/app/assets/javascripts/wizard/routes/step.js.es6 b/app/assets/javascripts/wizard/routes/step.js.es6 index 3487d61612a..152bf7a497b 100644 --- a/app/assets/javascripts/wizard/routes/step.js.es6 +++ b/app/assets/javascripts/wizard/routes/step.js.es6 @@ -6,6 +6,8 @@ export default Ember.Route.extend({ }, setupController(controller, step) { + this.controllerFor('application').set('currentStepId', step.get('id')); + controller.setProperties({ step, wizard: this.modelFor('application') }); diff --git a/app/assets/javascripts/wizard/templates/application.hbs b/app/assets/javascripts/wizard/templates/application.hbs index 1c069d5ba24..bef41d850c5 100644 --- a/app/assets/javascripts/wizard/templates/application.hbs +++ b/app/assets/javascripts/wizard/templates/application.hbs @@ -1,3 +1,7 @@ +{{#if showCanvas}} + {{wizard-canvas}} +{{/if}} +
{{outlet}} diff --git a/app/assets/stylesheets/wizard.scss b/app/assets/stylesheets/wizard.scss index 6354b9186c0..5f920c8918d 100644 --- a/app/assets/stylesheets/wizard.scss +++ b/app/assets/stylesheets/wizard.scss @@ -20,7 +20,16 @@ body.wizard { background: #ff9; } +.wizard-canvas { + position: absolute; + top: 0; + left: 0; + z-index: 10; +} + .wizard-column { + position: relative; + z-index: 11; background-color: white; box-shadow: 0 5px 10px rgba(0,0,0,0.2); box-sizing: border-box;