Created
April 11, 2017 10:48
-
-
Save nicolasbeauvais/00dd531ad3dbea90184dbeb40c165166 to your computer and use it in GitHub Desktop.
Animated curves made for raisup.com, vuejs object structure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Point(x, y) { | |
this.x = x; | |
this.y = y; | |
} | |
export default { | |
data() { | |
return { | |
canvas: undefined, | |
context: undefined, | |
raf: undefined, | |
avHeight: 0, | |
width: 0, | |
height: 0, | |
colors: ['rgba(1, 169, 241, 0.7)', 'rgba(25, 216, 186, 0.7)'], | |
curves: [], | |
}; | |
}, | |
mounted() { | |
this.canvas = this.$refs.canvas; | |
this.ctx = this.canvas.getContext('2d'); | |
this.init(); | |
$(window).on('resize', this.resize); | |
}, | |
methods: { | |
init () { | |
this.resize(); | |
this.curves = this.generateCurves(); | |
this.render(); | |
}, | |
resize() { | |
this.width = this.ctx.canvas.width = this.canvas.offsetWidth; | |
this.height = this.ctx.canvas.height = this.canvas.offsetHeight; | |
this.avHeight = this.height - 220; | |
this.curves = this.generateCurves(); | |
}, | |
render() { | |
setTimeout(() => { | |
this.raf = window.requestAnimationFrame(this.render); | |
this.ctx.fillStyle = "#FFFFFF"; | |
this.ctx.fillRect(0, 0, this.width, this.height); | |
this.curves.forEach((curve) => { | |
this.renderCurve(curve, this.ctx, this.width, this.height); | |
}); | |
}, 1000 / 15); | |
}, | |
middlePoint() { | |
return new Point((this.width / 100) * 50, ((this.avHeight) / 100) * 50); | |
}, | |
generateCurves() { | |
return [ | |
this.generateCurve( | |
['rgba(25, 216, 186, 0.8)', 'rgba(1, 169, 241, 0.8)'], | |
(this.height / 100) * 10, | |
(this.height / 100) * 45, | |
this.middlePoint, | |
new Point((this.width / 100) * 25, ((this.avHeight) / 100) * 5), | |
new Point((this.width / 100) * 76, ((this.avHeight) / 100) * 86), | |
), | |
this.generateCurve( | |
['rgba(1, 169, 241, 0.8)', 'rgba(25, 216, 186, 0.8)'], | |
((this.avHeight) / 100) * 20, | |
((this.avHeight) / 100) * 40, | |
this.middlePoint, | |
new Point((this.width / 100) * 23, ((this.avHeight) / 100) * 82), | |
new Point((this.width / 100) * 81, ((this.avHeight) / 100) * 13), | |
), | |
]; | |
}, | |
generateCurve(colors, yStart, yEnd, middle, point1, point2) { | |
const Curve = function(instance, colors, yStart, yEnd, middle, point1, point2) { | |
this.colors = colors; | |
// Origin | |
this.yStart = yStart; | |
this.yEnd = yEnd; | |
this.point1 = point1; | |
this.point2 = point2; | |
// Animation | |
this.animation = { | |
start: { | |
point: new Point(0, this.yStart), | |
value: Math.floor(Math.random() * 30), | |
direction: Math.random() > 0.5 ? 1 : -1 | |
}, | |
end: { | |
point: new Point(instance.width, this.yEnd), | |
value: Math.floor(Math.random() * 30), | |
direction: Math.random() > 0.5 ? 1 : -1 | |
}, | |
middle: { | |
point: middle, | |
value: Math.floor(Math.random() * 30), | |
direction: Math.random() > 0.5 ? 1 : -1 | |
}, | |
}; | |
}; | |
Curve.prototype.animate = function (instance) { | |
// Limit Animation | |
for (let key in this.animation) { | |
const realPos = this.animation[key].point.y + this.animation[key].value; | |
const max = key === 'middle' ? (instance.avHeight / 4) * 3 : instance.avHeight; | |
const min = key === 'middle' ? (instance.avHeight / 4) : 0; | |
// If to far change direction | |
if (realPos >= max || realPos <= min) { | |
this.animation[key].direction = this.animation[key].direction * -1; | |
} else {// Else, change direction randomly (1/400 frames) | |
if (Math.floor(Math.random() * 400) === 50) { | |
this.animation[key].direction = this.animation[key].direction * -1; | |
} | |
} | |
this.animation[key].value += this.animation[key].direction; | |
} | |
// Apply | |
const middlePoint = instance.middlePoint(); | |
this.animation.start.point = new Point(0, this.yStart + this.animation.start.value); | |
this.animation.end.point = new Point(instance.width, this.yEnd + this.animation.end.value); | |
this.animation.middle.point = new Point(middlePoint.x + this.animation.middle.value, middlePoint.y + this.animation.middle.value); | |
}; | |
return new Curve(this, colors, yStart, yEnd, middle, point1, point2); | |
}, | |
renderCurve(curve, ctx, width, height) { | |
ctx.save(); | |
// Gradient | |
const gradient = ctx.createLinearGradient(0, 0, width, height); | |
gradient.addColorStop(0, curve.colors[0]); | |
gradient.addColorStop(1, curve.colors[1]); | |
ctx.fillStyle = gradient; | |
ctx.beginPath(); | |
ctx.moveTo(curve.animation.start.point.x, curve.animation.start.point.y); | |
const animationCoefficient = curve.animation.middle.value; | |
if (width < 778) {// Small screens (render 1 curve) | |
ctx.quadraticCurveTo( | |
curve.point1.x + animationCoefficient, | |
curve.point1.y + animationCoefficient, | |
curve.animation.end.point.x, | |
curve.animation.end.point.y | |
); | |
} else {// Big screens (render 2 curves) | |
ctx.quadraticCurveTo( | |
curve.point1.x + animationCoefficient, | |
curve.point1.y + animationCoefficient, | |
curve.animation.middle.point.x, | |
curve.animation.middle.point.y | |
); | |
ctx.quadraticCurveTo( | |
curve.point2.x + animationCoefficient, | |
curve.point2.y + animationCoefficient, | |
curve.animation.end.point.x, | |
curve.animation.end.point.y | |
); | |
} | |
ctx.lineTo(width, height); | |
ctx.lineTo(0, height); | |
ctx.fill(); | |
ctx.restore(); | |
// Animate next frame | |
curve.animate(this); | |
}, | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment