Guest User

First stab at confetti script - gunr2171

a guest
Oct 17th, 2014
26
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Confetti
  3. // @namespace    http://your.homepage/
  4. // @version      0.1
  5. // @description  enter something useful
  6. // @author       You
  7. // @match        http://chat.stackoverflow.com/rooms/41570/so-close-vote-reviewers
  8. // @grant        none
  9. // ==/UserScript==
  10.  
  11.  
  12. (function() {
  13.    
  14.     $('body').append("<div id='confetti'></div>");
  15.     //$('body').append('<styles>#confetti{  background: #000;   height: 100%;   left: 0;    position: fixed;    top: 0; width: 100%;    z-index: 10;}</styles>');
  16.    
  17.     //$('body div#confetti').css('background', '#000');
  18.     $('body div#confetti').css('height', '100%');
  19.     $('body div#confetti').css('left', '0');
  20.     $('body div#confetti').css('position', 'fixed');
  21.     $('body div#confetti').css('top', '0');
  22.     $('body div#confetti').css('width', '100%');
  23.     $('body div#confetti').css('z-index', '10');
  24.     $('body div#confetti').css('display', 'none');
  25.            
  26.     $(document).on('click', 'div#chat div.content', function() {
  27.         //$(this).attr('style', 'background-color: red');
  28.        
  29.         //alert('click!');
  30.         //$('body div#confetti').css('display', 'block');
  31.        
  32.        
  33.        
  34.        
  35.         //===============================
  36.         /* Confetti by Patrik Svensson (http://metervara.net) */
  37.         var frameRate = 30;
  38.         var dt = 1.0 / frameRate;
  39.         var DEG_TO_RAD = Math.PI / 180;
  40.         var RAD_TO_DEG = 180 / Math.PI;
  41.         var colors = [
  42.             ["#df0049", "#660671"],
  43.             ["#00e857", "#005291"],
  44.             ["#2bebbc", "#05798a"],
  45.             ["#ffd200", "#b06c00"]
  46.         ];
  47.    
  48.         function Vector2(_x, _y) {
  49.             this.x = _x, this.y = _y;
  50.             this.Length = function() {
  51.                 return Math.sqrt(this.SqrLength());
  52.             }
  53.             this.SqrLength = function() {
  54.                 return this.x * this.x + this.y * this.y;
  55.             }
  56.             this.Equals = function(_vec0, _vec1) {
  57.                 return _vec0.x == _vec1.x && _vec0.y == _vec1.y;
  58.             }
  59.             this.Add = function(_vec) {
  60.                 this.x += _vec.x;
  61.                 this.y += _vec.y;
  62.             }
  63.             this.Sub = function(_vec) {
  64.                 this.x -= _vec.x;
  65.                 this.y -= _vec.y;
  66.             }
  67.             this.Div = function(_f) {
  68.                 this.x /= _f;
  69.                 this.y /= _f;
  70.             }
  71.             this.Mul = function(_f) {
  72.                 this.x *= _f;
  73.                 this.y *= _f;
  74.             }
  75.             this.Normalize = function() {
  76.                 var sqrLen = this.SqrLength();
  77.                 if (sqrLen != 0) {
  78.                     var factor = 1.0 / Math.sqrt(sqrLen);
  79.                     this.x *= factor;
  80.                     this.y *= factor;
  81.                 }
  82.             }
  83.             this.Normalized = function() {
  84.                 var sqrLen = this.SqrLength();
  85.                 if (sqrLen != 0) {
  86.                     var factor = 1.0 / Math.sqrt(sqrLen);
  87.                     return new Vector2(this.x * factor, this.y * factor);
  88.                 }
  89.                 return new Vector2(0, 0);
  90.             }
  91.         }
  92.         Vector2.Lerp = function(_vec0, _vec1, _t) {
  93.             return new Vector2((_vec1.x - _vec0.x) * _t + _vec0.x, (_vec1.y - _vec0.y) * _t + _vec0.y);
  94.         }
  95.         Vector2.Distance = function(_vec0, _vec1) {
  96.             return Math.sqrt(Vector2.SqrDistance(_vec0, _vec1));
  97.         }
  98.         Vector2.SqrDistance = function(_vec0, _vec1) {
  99.             var x = _vec0.x - _vec1.x;
  100.             var y = _vec0.y - _vec1.y;
  101.             return (x * x + y * y + z * z);
  102.         }
  103.         Vector2.Scale = function(_vec0, _vec1) {
  104.             return new Vector2(_vec0.x * _vec1.x, _vec0.y * _vec1.y);
  105.         }
  106.         Vector2.Min = function(_vec0, _vec1) {
  107.             return new Vector2(Math.min(_vec0.x, _vec1.x), Math.min(_vec0.y, _vec1.y));
  108.         }
  109.         Vector2.Max = function(_vec0, _vec1) {
  110.             return new Vector2(Math.max(_vec0.x, _vec1.x), Math.max(_vec0.y, _vec1.y));
  111.         }
  112.         Vector2.ClampMagnitude = function(_vec0, _len) {
  113.             var vecNorm = _vec0.Normalized;
  114.             return new Vector2(vecNorm.x * _len, vecNorm.y * _len);
  115.         }
  116.         Vector2.Sub = function(_vec0, _vec1) {
  117.             return new Vector2(_vec0.x - _vec1.x, _vec0.y - _vec1.y, _vec0.z - _vec1.z);
  118.         }
  119.    
  120.         function EulerMass(_x, _y, _mass, _drag) {
  121.             this.position = new Vector2(_x, _y);
  122.             this.mass = _mass;
  123.             this.drag = _drag;
  124.             this.force = new Vector2(0, 0);
  125.             this.velocity = new Vector2(0, 0);
  126.             this.AddForce = function(_f) {
  127.                 this.force.Add(_f);
  128.             }
  129.             this.Integrate = function(_dt) {
  130.                 var acc = this.CurrentForce(this.position);
  131.                 acc.Div(this.mass);
  132.                 var posDelta = new Vector2(this.velocity.x, this.velocity.y);
  133.                 posDelta.Mul(_dt);
  134.                 this.position.Add(posDelta);
  135.                 acc.Mul(_dt);
  136.                 this.velocity.Add(acc);
  137.                 this.force = new Vector2(0, 0);
  138.             }
  139.             this.CurrentForce = function(_pos, _vel) {
  140.                 var totalForce = new Vector2(this.force.x, this.force.y);
  141.                 var speed = this.velocity.Length();
  142.                 var dragVel = new Vector2(this.velocity.x, this.velocity.y);
  143.                 dragVel.Mul(this.drag * this.mass * speed);
  144.                 totalForce.Sub(dragVel);
  145.                 return totalForce;
  146.             }
  147.         }
  148.    
  149.         function ConfettiPaper(_x, _y) {
  150.             this.pos = new Vector2(_x, _y);
  151.             this.rotationSpeed = Math.random() * 600 + 800;
  152.             this.angle = DEG_TO_RAD * Math.random() * 360;
  153.             this.rotation = DEG_TO_RAD * Math.random() * 360;
  154.             this.cosA = 1.0;
  155.             this.size = 5.0;
  156.             this.oscillationSpeed = Math.random() * 1.5 + 0.5;
  157.             this.xSpeed = 40.0;
  158.             this.ySpeed = Math.random() * 60 + 50.0;
  159.             this.corners = new Array();
  160.             this.time = Math.random();
  161.             var ci = Math.round(Math.random() * (colors.length - 1));
  162.             this.frontColor = colors[ci][0];
  163.             this.backColor = colors[ci][1];
  164.             for (var i = 0; i < 4; i++) {
  165.                 var dx = Math.cos(this.angle + DEG_TO_RAD * (i * 90 + 45));
  166.                 var dy = Math.sin(this.angle + DEG_TO_RAD * (i * 90 + 45));
  167.                 this.corners[i] = new Vector2(dx, dy);
  168.             }
  169.             this.Update = function(_dt) {
  170.                 this.time += _dt;
  171.                 this.rotation += this.rotationSpeed * _dt;
  172.                 this.cosA = Math.cos(DEG_TO_RAD * this.rotation);
  173.                 this.pos.x += Math.cos(this.time * this.oscillationSpeed) * this.xSpeed * _dt
  174.                 this.pos.y += this.ySpeed * _dt;
  175.                 if (this.pos.y > ConfettiPaper.bounds.y) {
  176.                     this.pos.x = Math.random() * ConfettiPaper.bounds.x;
  177.                     this.pos.y = 0;
  178.                 }
  179.             }
  180.             this.Draw = function(_g) {
  181.                 if (this.cosA > 0) {
  182.                     _g.fillStyle = this.frontColor;
  183.                 } else {
  184.                     _g.fillStyle = this.backColor;
  185.                 }
  186.                 _g.beginPath();
  187.                 _g.moveTo(this.pos.x + this.corners[0].x * this.size, this.pos.y + this.corners[0].y * this.size * this.cosA);
  188.                 for (var i = 1; i < 4; i++) {
  189.                     _g.lineTo(this.pos.x + this.corners[i].x * this.size, this.pos.y + this.corners[i].y * this.size * this.cosA);
  190.                 }
  191.                 _g.closePath();
  192.                 _g.fill();
  193.             }
  194.         }
  195.         ConfettiPaper.bounds = new Vector2(0, 0);
  196.    
  197.         function ConfettiRibbon(_x, _y, _count, _dist, _thickness, _angle, _mass, _drag) {
  198.             this.particleDist = _dist;
  199.             this.particleCount = _count;
  200.             this.particleMass = _mass;
  201.             this.particleDrag = _drag;
  202.             this.particles = new Array();
  203.             var ci = Math.round(Math.random() * (colors.length - 1));
  204.             this.frontColor = colors[ci][0];
  205.             this.backColor = colors[ci][1];
  206.             this.xOff = Math.cos(DEG_TO_RAD * _angle) * _thickness;
  207.             this.yOff = Math.sin(DEG_TO_RAD * _angle) * _thickness;
  208.             this.position = new Vector2(_x, _y);
  209.             this.prevPosition = new Vector2(_x, _y);
  210.             this.velocityInherit = Math.random() * 2 + 4;
  211.             this.time = Math.random() * 100;
  212.             this.oscillationSpeed = Math.random() * 2 + 2;
  213.             this.oscillationDistance = Math.random() * 40 + 40;
  214.             this.ySpeed = Math.random() * 40 + 80;
  215.             for (var i = 0; i < this.particleCount; i++) {
  216.                 this.particles[i] = new EulerMass(_x, _y - i * this.particleDist, this.particleMass, this.particleDrag);
  217.             }
  218.             this.Update = function(_dt) {
  219.                 var i = 0;
  220.                 this.time += _dt * this.oscillationSpeed;
  221.                 this.position.y += this.ySpeed * _dt;
  222.                 this.position.x += Math.cos(this.time) * this.oscillationDistance * _dt;
  223.                 this.particles[0].position = this.position;
  224.                 var dX = this.prevPosition.x - this.position.x;
  225.                 var dY = this.prevPosition.y - this.position.y;
  226.                 var delta = Math.sqrt(dX * dX + dY * dY);
  227.                 this.prevPosition = new Vector2(this.position.x, this.position.y);
  228.                 for (i = 1; i < this.particleCount; i++) {
  229.                     var dirP = Vector2.Sub(this.particles[i - 1].position, this.particles[i].position);
  230.                     dirP.Normalize();
  231.                     dirP.Mul((delta / _dt) * this.velocityInherit);
  232.                     this.particles[i].AddForce(dirP);
  233.                 }
  234.                 for (i = 1; i < this.particleCount; i++) {
  235.                     this.particles[i].Integrate(_dt);
  236.                 }
  237.                 for (i = 1; i < this.particleCount; i++) {
  238.                     var rp2 = new Vector2(this.particles[i].position.x, this.particles[i].position.y);
  239.                     rp2.Sub(this.particles[i - 1].position);
  240.                     rp2.Normalize();
  241.                     rp2.Mul(this.particleDist);
  242.                     rp2.Add(this.particles[i - 1].position);
  243.                     this.particles[i].position = rp2;
  244.                 }
  245.                 if (this.position.y > ConfettiRibbon.bounds.y + this.particleDist * this.particleCount) {
  246.                     this.Reset();
  247.                 }
  248.             }
  249.             this.Reset = function() {
  250.                 this.position.y = -Math.random() * ConfettiRibbon.bounds.y;
  251.                 this.position.x = Math.random() * ConfettiRibbon.bounds.x;
  252.                 this.prevPosition = new Vector2(this.position.x, this.position.y);
  253.                 this.velocityInherit = Math.random() * 2 + 4;
  254.                 this.time = Math.random() * 100;
  255.                 this.oscillationSpeed = Math.random() * 2.0 + 1.5;
  256.                 this.oscillationDistance = Math.random() * 40 + 40;
  257.                 this.ySpeed = Math.random() * 40 + 80;
  258.                 var ci = Math.round(Math.random() * (colors.length - 1));
  259.                 this.frontColor = colors[ci][0];
  260.                 this.backColor = colors[ci][1];
  261.                 this.particles = new Array();
  262.                 for (var i = 0; i < this.particleCount; i++) {
  263.                     this.particles[i] = new EulerMass(this.position.x, this.position.y - i * this.particleDist, this.particleMass, this.particleDrag);
  264.                 }
  265.             }
  266.             this.Draw = function(_g) {
  267.                 for (var i = 0; i < this.particleCount - 1; i++) {
  268.                     var p0 = new Vector2(this.particles[i].position.x + this.xOff, this.particles[i].position.y + this.yOff);
  269.                     var p1 = new Vector2(this.particles[i + 1].position.x + this.xOff, this.particles[i + 1].position.y + this.yOff);
  270.                     if (this.Side(this.particles[i].position.x, this.particles[i].position.y, this.particles[i + 1].position.x, this.particles[i + 1].position.y, p1.x, p1.y) < 0) {
  271.                         _g.fillStyle = this.frontColor;
  272.                         _g.strokeStyle = this.frontColor;
  273.                     } else {
  274.                         _g.fillStyle = this.backColor;
  275.                         _g.strokeStyle = this.backColor;
  276.                     }
  277.                     if (i == 0) {
  278.                         _g.beginPath();
  279.                         _g.moveTo(this.particles[i].position.x, this.particles[i].position.y);
  280.                         _g.lineTo(this.particles[i + 1].position.x, this.particles[i + 1].position.y);
  281.                         _g.lineTo((this.particles[i + 1].position.x + p1.x) * 0.5, (this.particles[i + 1].position.y + p1.y) * 0.5);
  282.                         _g.closePath();
  283.                         _g.stroke();
  284.                         _g.fill();
  285.                         _g.beginPath();
  286.                         _g.moveTo(p1.x, p1.y);
  287.                         _g.lineTo(p0.x, p0.y);
  288.                         _g.lineTo((this.particles[i + 1].position.x + p1.x) * 0.5, (this.particles[i + 1].position.y + p1.y) * 0.5);
  289.                         _g.closePath();
  290.                         _g.stroke();
  291.                         _g.fill();
  292.                     } else if (i == this.particleCount - 2) {
  293.                         _g.beginPath();
  294.                         _g.moveTo(this.particles[i].position.x, this.particles[i].position.y);
  295.                         _g.lineTo(this.particles[i + 1].position.x, this.particles[i + 1].position.y);
  296.                         _g.lineTo((this.particles[i].position.x + p0.x) * 0.5, (this.particles[i].position.y + p0.y) * 0.5);
  297.                         _g.closePath();
  298.                         _g.stroke();
  299.                         _g.fill();
  300.                         _g.beginPath();
  301.                         _g.moveTo(p1.x, p1.y);
  302.                         _g.lineTo(p0.x, p0.y);
  303.                         _g.lineTo((this.particles[i].position.x + p0.x) * 0.5, (this.particles[i].position.y + p0.y) * 0.5);
  304.                         _g.closePath();
  305.                         _g.stroke();
  306.                         _g.fill();
  307.                     } else {
  308.                         _g.beginPath();
  309.                         _g.moveTo(this.particles[i].position.x, this.particles[i].position.y);
  310.                         _g.lineTo(this.particles[i + 1].position.x, this.particles[i + 1].position.y);
  311.                         _g.lineTo(p1.x, p1.y);
  312.                         _g.lineTo(p0.x, p0.y);
  313.                         _g.closePath();
  314.                         _g.stroke();
  315.                         _g.fill();
  316.                     }
  317.                 }
  318.             }
  319.             this.Side = function(x1, y1, x2, y2, x3, y3) {
  320.                 return ((x1 - x2) * (y3 - y2) - (y1 - y2) * (x3 - x2));
  321.             }
  322.         }
  323.         ConfettiRibbon.bounds = new Vector2(0, 0);
  324.         confetti = {};
  325.         confetti.Context = function(parent) {
  326.             var i = 0;
  327.             var canvasParent = document.getElementById(parent);
  328.             var canvas = document.createElement('canvas');
  329.             canvas.width = canvasParent.offsetWidth;
  330.             canvas.height = canvasParent.offsetHeight;
  331.             canvasParent.appendChild(canvas);
  332.             var context = canvas.getContext('2d');
  333.             var interval = null;
  334.             var confettiRibbonCount = 7;
  335.             var rpCount = 30;
  336.             var rpDist = 8.0;
  337.             var rpThick = 8.0;
  338.             var confettiRibbons = new Array();
  339.             ConfettiRibbon.bounds = new Vector2(canvas.width, canvas.height);
  340.             for (i = 0; i < confettiRibbonCount; i++) {
  341.                 confettiRibbons[i] = new ConfettiRibbon(Math.random() * canvas.width, -Math.random() * canvas.height * 2, rpCount, rpDist, rpThick, 45, 1, 0.05);
  342.             }
  343.             var confettiPaperCount = 25;
  344.             var confettiPapers = new Array();
  345.             ConfettiPaper.bounds = new Vector2(canvas.width, canvas.height);
  346.             for (i = 0; i < confettiPaperCount; i++) {
  347.                 confettiPapers[i] = new ConfettiPaper(Math.random() * canvas.width, Math.random() * canvas.height);
  348.             }
  349.             this.resize = function() {
  350.                 canvas.width = canvasParent.offsetWidth;
  351.                 canvas.height = canvasParent.offsetHeight;
  352.                 ConfettiPaper.bounds = new Vector2(canvas.width, canvas.height);
  353.                 ConfettiRibbon.bounds = new Vector2(canvas.width, canvas.height);
  354.             }
  355.             this.start = function() {
  356.                 this.stop()
  357.                 var context = this
  358.                 this.interval = setInterval(function() {
  359.                     confetti.update();
  360.                 }, 1000.0 / frameRate)
  361.             }
  362.             this.stop = function() {
  363.                 clearInterval(this.interval);
  364.             }
  365.             this.update = function() {
  366.                 var i = 0;
  367.                 context.clearRect(0, 0, canvas.width, canvas.height);
  368.                 for (i = 0; i < confettiPaperCount; i++) {
  369.                     confettiPapers[i].Update(dt);
  370.                     confettiPapers[i].Draw(context);
  371.                 }
  372.                 for (i = 0; i < confettiRibbonCount; i++) {
  373.                     confettiRibbons[i].Update(dt);
  374.                     confettiRibbons[i].Draw(context);
  375.                 }
  376.             }
  377.         }
  378.        
  379.         $('body div#confetti').fadeIn('fast');
  380.        
  381.         var confetti = new confetti.Context('confetti');
  382.         confetti.start();
  383.        
  384.        
  385.        
  386.         $(window).resize(function() {
  387.             confetti.resize();
  388.         });
  389.        
  390.        setTimeout(function()
  391.           {
  392.             $('body div#confetti').fadeOut('fast');
  393.           }, 1000);
  394.        
  395.         //===============================
  396.        
  397.          
  398.        
  399.     });
  400.    
  401.    
  402.    
  403. })();
RAW Paste Data