# How I built the SiriWaveJS library: a look at the math and the code

Oct 26, 2018 · 10 min read

# The classic wave style

## Basic code concepts

`const ctx = canvas.getContext('2d');ctx.beginPath();ctx.strokeStyle = 'white';for (let i = -2; i <= 2; i += 0.01) {   const x = _xpos(i);   const y = _ypos(i);   ctx.lineTo(x, y);}ctx.stroke();`

## Implement _xpos(i)

_xpos(i) = w * [ (i + B) / 2B ]

## Implement _ypos

`const K = 4;const FREQ = 6;function _attFn(x) {   return Math.pow(K / (K + Math.pow(x, K)), K);}function _ypos(i) {   return Math.sin(FREQ * i - phase) *       _attFn(i) *       canvasHeight *      globalAmplitude *       (1 / attenuation);}`

## Phase

`phase = (phase + (Math.PI / 2) * speed) % (2 * Math.PI);`

## Finalizing

`return [   { attenuation: -2, lineWidth: 1.0, opacity: 0.1 },   { attenuation: -6, lineWidth: 1.0, opacity: 0.2 },   { attenuation: 4, lineWidth: 1.0, opacity: 0.4 },   { attenuation: 2, lineWidth: 1.0, opacity: 0.6},   // basic line   { attenuation: 1, lineWidth: 1.5, opacity: 1.0},];`

# The iOS 9+ style

`const K = 4;const NO_OF_CURVES = 3;// This parameters should be generated randomlyconst widths = [ 0.4, 0.6, 0.3 ];const offsets = [ 1, 4, -3 ];const amplitudes = [ 0.5, 0.7, 0.2 ];const phases = [ 0, 0, 0 ];function _globalAttFn(x) {   return Math.pow(K / (K + Math.pow(x, 2)), K);}function _ypos(i) {   let y = 0;   for (let ci = 0; ci < NO_OF_CURVES; ci++) {      const t = offsets[ci];      const k = 1 / widths[ci];      const x = (i * k) - t;            y += Math.abs(         amplitudes[ci] *          Math.sin(x - phases[ci]) *          _globalAttFn(x)      );   }   y = y / NO_OF_CURVES;   return canvasHeightMax * globalAmplitude * y;}`

# Build with RollupJS

`{   input: 'src/siriwave.js',   output: {      file: pkg.unpkg,      name: pkg.amdName,      format: 'umd'    },    plugins: [       resolve(),       commonjs(),       babel({ exclude: 'node_modules/**' }),    ]}`
`{   input: 'src/siriwave.js',   output: {      file: pkg.unpkg.replace('.js', '.min.js'),      name: pkg.amdName,      format: 'umd'    },    plugins: [       resolve(),       commonjs(),       babel({ exclude: 'node_modules/**' }),       uglify()]}`
`{    input: ‘src/siriwave.js’,   output: {       file: pkg.module,       format: ‘esm’   },    plugins: [       babel({ exclude: ‘node_modules/**’ })   ]}`

## Watch and Hot code reload

`import livereload from 'rollup-plugin-livereload';import serve from 'rollup-plugin-serve';if (process.env.NODE_ENV !== 'production') { additional_plugins.push(  serve({   open: true,   contentBase: '.'  }) ); additional_plugins.push(  livereload({   watch: 'dist'  }) );}`
`"module": "dist/siriwave.m.js","jsnext:main": "dist/siriwave.m.js","unpkg": "dist/siriwave.js","amdName": "SiriWave","scripts": {   "build": "NODE_ENV=production rollup -c",   "dev": "rollup -c -w"},`

Written by

## Flavio De Stefano

#### Software Engineer for @Spotify in @Stockholm; with passion

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just \$5/month. Upgrade