├── src
├── context.js
├── font-face
│ ├── monoton
│ │ └── Monoton-Regular.ttf
│ └── signika
│ │ └── Signika-Regular.otf
├── index.js
├── shaders
│ ├── hoc.js
│ ├── CurveOne.js
│ ├── Parabola.js
│ ├── Impulse.js
│ ├── CurveTwo.js
│ ├── Gain.js
│ ├── SineCurve.js
│ ├── CurveFive.js
│ ├── CurveFour.js
│ ├── CurveThree.js
│ ├── ExpoStep.js
│ ├── PowerCurve.js
│ └── CubicPulse.js
├── App.js
└── App.css
├── public
├── manifest.json
└── index.html
├── .gitignore
├── package.json
└── README.md
/src/context.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const { Consumer, Provider } = React.createContext()
--------------------------------------------------------------------------------
/src/font-face/monoton/Monoton-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitin42/shaping-functions/HEAD/src/font-face/monoton/Monoton-Regular.ttf
--------------------------------------------------------------------------------
/src/font-face/signika/Signika-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitin42/shaping-functions/HEAD/src/font-face/signika/Signika-Regular.otf
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Shaping Functions
9 |
10 |
11 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/shaders/hoc.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Consumer } from '../context'
3 |
4 | export const ShaderCanvas = (Shader, heading) => class extends React.Component {
5 | render() {
6 | return (
7 |
8 | {timesync => (
9 |
10 |
11 |
12 |
{heading}
13 |
14 |
15 | )}
16 |
17 | )
18 | }
19 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shaping-functions",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "glslCanvas": "^0.1.7",
7 | "react": "^16.5.2",
8 | "react-dom": "^16.5.2",
9 | "react-scripts": "2.0.4",
10 | "react-shader-canvas": "^1.0.0",
11 | "react-tooltip": "^3.8.4"
12 | },
13 | "scripts": {
14 | "start": "SKIP_PREFLIGHT_CHECK=true react-scripts start",
15 | "build": "SKIP_PREFLIGHT_CHECK=true react-scripts build",
16 | "eject": "react-scripts eject"
17 | },
18 | "eslintConfig": {
19 | "extends": "react-app"
20 | },
21 | "browserslist": [
22 | ">0.2%",
23 | "not dead",
24 | "not ie <= 11",
25 | "not op_mini all"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/src/shaders/CurveOne.js:
--------------------------------------------------------------------------------
1 | import {createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({ timeSync = false }) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float plotCurve( float x, float k ) {
14 | return 1.0 - pow(abs(x), k);
15 | }
16 |
17 | void main() {
18 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
19 | float px = 1.0 / u_resolution.y;
20 |
21 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
22 | float l = plotCurve(point.x, ${timeSync ? 'u_time * cp.y' : 'cp.y'});
23 | vec3 color = vec3(smoothstep(l, l+px, point.y), sin(cp.y), cos(cp.x));
24 |
25 | gl_FragColor = vec4(color, 1.0);
26 | }
27 | `
28 |
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Kynd Curve One');
--------------------------------------------------------------------------------
/src/shaders/Parabola.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc';
3 |
4 | const shader = ({timeSync = false}) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float parabola( float x, float k ) {
14 | return pow(4.0 * x * (1.0-x), k);
15 | }
16 |
17 | void main() {
18 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
19 | float px = 1.0 / u_resolution.y;
20 |
21 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
22 | float l = parabola(point.x, ${timeSync ? 'cp.y * u_time' : 'cp.y'});
23 | vec3 color = vec3(smoothstep(l, l+px, point.y), sin(u_time), cos(u_time));
24 |
25 | gl_FragColor = vec4(color, 1.0);
26 | }
27 | `
28 |
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Parabola')
--------------------------------------------------------------------------------
/src/shaders/Impulse.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({timeSync = false}) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float impulse( float k, float x ) {
14 | float h = k*x;
15 | return h*exp(1.0-h);
16 | }
17 |
18 | void main() {
19 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
20 | float px = 1.0 / u_resolution.y;
21 |
22 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
23 | float l = impulse(${timeSync ? 'cp.x * u_time' : 'cp.x'}, point.x);
24 | vec3 color = vec3(smoothstep(l, l+px, point.y), tan(u_time), sin(cp.y));
25 |
26 | gl_FragColor = vec4(color, 1.0);
27 | }
28 | `
29 |
30 | export default ShaderCanvas(createShaderCanvas(shader), 'Impulse Curve')
--------------------------------------------------------------------------------
/src/shaders/CurveTwo.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({ timeSync = false }) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float plotCurve( float x, float k ) {
14 | return pow(cos(3.142 * x / 2.0), k);
15 | }
16 |
17 | void main() {
18 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
19 | float px = 1.0 / u_resolution.y;
20 |
21 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
22 | float l = plotCurve(point.x, ${timeSync ? 'u_time * cp.y' : 'cp.y'});
23 | vec3 color = vec3(smoothstep(l, l+px, point.y), tan(cp.y), fract(cp.x));
24 |
25 | gl_FragColor = vec4(color, 1.0);
26 | }
27 | `
28 |
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Kynd Curve Two');
--------------------------------------------------------------------------------
/src/shaders/Gain.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc';
3 |
4 | const shader = ({timeSync = false}) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float gain(float x, float k) {
14 | float a = 0.5*pow(2.0*((x<0.5)?x:1.0-x), k);
15 | return (x<0.5)?a:1.0-a;
16 | }
17 |
18 | void main() {
19 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
20 | float px = 1.0 / u_resolution.y;
21 |
22 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
23 | float l = gain(point.x, ${timeSync ? 'cp.x * u_time' : 'cp.x'});
24 | vec3 color = vec3(smoothstep(l, l+px, point.y), tan(u_time), sin(cp.y));
25 |
26 | gl_FragColor = vec4(color, 1.0);
27 | }
28 | `
29 |
30 | export default ShaderCanvas(createShaderCanvas(shader), 'Gain Curve')
--------------------------------------------------------------------------------
/src/shaders/SineCurve.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({timeSync = false}) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float sinc( float x, float k ){
14 | float a = 3.1459265359 * k * x - 1.0;
15 |
16 | return sin(a)/a;
17 | }
18 |
19 | void main() {
20 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
21 | float px = 1.0 / u_resolution.y;
22 |
23 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
24 | float l = sinc(point.x, ${timeSync ? 'cp.x * u_time' : 'cp.x'});
25 | vec3 color = vec3(smoothstep(l, l+px, point.y), tan(u_time), sin(cp.y));
26 |
27 | gl_FragColor = vec4(color, 1.0);
28 | }
29 | `
30 |
31 | export default ShaderCanvas(createShaderCanvas(shader), 'Sine Curve')
--------------------------------------------------------------------------------
/src/shaders/CurveFive.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({ timeSync = false }) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float plotCurve( float x, float k ) {
14 | return 1.0 - pow(max(0.0, abs(x) * 2.0 - 1.0), k);
15 | }
16 |
17 | void main() {
18 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
19 | float px = 1.0 / u_resolution.y;
20 |
21 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
22 | float l = plotCurve(point.x, ${timeSync ? 'u_time * cp.y' : 'cp.y'});
23 | vec3 color = vec3(smoothstep(l, l+px, point.y), sin(cp.y * 0.2), tan(cp.x));
24 |
25 | gl_FragColor = vec4(color, 1.0);
26 | }
27 | `
28 |
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Kynd Curve Five');
--------------------------------------------------------------------------------
/src/shaders/CurveFour.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({ timeSync = false }) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float plotCurve( float x, float k ) {
14 | return pow(min(cos(3.142 * x / 2.0), 1.0 - abs(x)), k);
15 | }
16 |
17 | void main() {
18 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
19 | float px = 1.0 / u_resolution.y;
20 |
21 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
22 | float l = plotCurve(point.x, ${timeSync ? 'u_time * cp.y' : 'cp.y'});
23 | vec3 color = vec3(smoothstep(l, l+px, point.y), tan(cp.y), cos(cp.x));
24 |
25 | gl_FragColor = vec4(color, 1.0);
26 | }
27 | `
28 |
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Kynd Curve Four');
--------------------------------------------------------------------------------
/src/shaders/CurveThree.js:
--------------------------------------------------------------------------------
1 | import {createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({ timeSync = false }) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float plotCurve( float x, float k ) {
14 | return 1.0 - pow(abs(sin(3.142 * x / 2.0)), k);
15 | }
16 |
17 | void main() {
18 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
19 | float px = 1.0 / u_resolution.y;
20 |
21 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
22 | float l = plotCurve(point.x, ${timeSync ? 'u_time * cp.y' : 'cp.y'});
23 | vec3 color = vec3(smoothstep(l, l+px, point.y), sin(cp.y * 0.5), cos(cp.x * 0.8));
24 |
25 | gl_FragColor = vec4(color, 1.0);
26 | }
27 | `
28 |
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Kynd Curve Three');
--------------------------------------------------------------------------------
/src/shaders/ExpoStep.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc';
3 |
4 | const shader = ({timeSync = false}) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float expStep( float x, float k, float n ){
14 | return exp( -k*pow(x,n) );
15 | }
16 |
17 | void main() {
18 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
19 | float px = 1.0 / u_resolution.y;
20 |
21 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
22 | float l = expStep(point.x, ${timeSync ? 'cp.x * u_time' : 'cp.x'}, ${timeSync ? 'cp.y * u_time' : 'cp.y'});
23 | vec3 color = vec3(smoothstep(l, l+px, point.y), sin(u_time), cos(cp.y) * 0.5);
24 |
25 | gl_FragColor = vec4(color, 1.0);
26 | }
27 | `
28 |
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Exponential Step')
--------------------------------------------------------------------------------
/src/shaders/PowerCurve.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc';
3 |
4 | const shader = ({timeSync = false}) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float pcurve( float x, float a, float b ){
14 | float k = pow(a+b,a+b) / (pow(a,a)*pow(b,b));
15 | return k * pow( x, a ) * pow( 1.0-x, b );
16 | }
17 |
18 | void main() {
19 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
20 | float px = 1.0 / u_resolution.y;
21 |
22 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
23 | float l = pcurve(point.x, ${timeSync ? 'cp.x * u_time' : 'cp.x'}, ${timeSync ? 'cp.y * u_time': 'cp.y'});
24 | vec3 color = vec3(smoothstep(l, l+px, point.y), tan(u_time), sin(cp.y));
25 |
26 | gl_FragColor = vec4(color, 1.0);
27 | }
28 | `
29 | export default ShaderCanvas(createShaderCanvas(shader), 'Power Curve')
--------------------------------------------------------------------------------
/src/shaders/CubicPulse.js:
--------------------------------------------------------------------------------
1 | import { createShaderCanvas } from 'react-shader-canvas'
2 | import { ShaderCanvas } from './hoc'
3 |
4 | const shader = ({timeSync = false}) => `
5 | #ifdef GL_ES
6 | precision mediump float;
7 | #endif
8 |
9 | uniform float u_time;
10 | uniform vec2 u_mouse;
11 | uniform vec2 u_resolution;
12 |
13 | float cubicPulse( float c, float w, float x ){
14 | x = abs(x - c);
15 | if( x>w ) return 0.0;
16 | x /= w;
17 | return 1.0 - x*x*(3.0-2.0*x);
18 | }
19 |
20 | void main() {
21 | vec2 point = gl_FragCoord.xy / u_resolution.xy;
22 | float px = 1.0 / u_resolution.y;
23 |
24 | vec2 cp = vec2(cos(u_time),sin(u_time)) * 0.618 + 0.620;
25 | float l = cubicPulse(${timeSync ? 'cp.x * u_time / 10.0' : 'cp.x'}, ${timeSync ? 'cp.y * u_time / 10.0' : 'cp.y'}, point.x);
26 | vec3 color = vec3(smoothstep(l, l+px, point.y), tan(u_time), sin(cp.y));
27 |
28 | gl_FragColor = vec4(color, 1.0);
29 | }
30 | `
31 |
32 | export default ShaderCanvas(createShaderCanvas(shader), 'Cubic Pulse')
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # shaping-functions
2 |
3 | > Visualisation of shaping functions
4 |
5 | ## Introduction
6 |
7 | This is visualisation of shaping functions used in algorithmic drawing. I am learning shaders and mathematics required for computer graphics. As a part of my learning process and to practice writing my own functions, I decided to port [these](http://www.iquilezles.org/www/articles/functions/functions.html) shaping functions written by [Inigo Quilez](http://www.iquilezles.org/index.html) and also [Kynd's curves](http://www.flickr.com/photos/kynd/9546075099). Inigo Quilez's [blog](http://www.iquilezles.org/www/index.htm) explains the use cases for shaping functions such as - animations, or making envelopes for music.
8 |
9 | ## Future
10 |
11 | I'll keep updating the collection (of shaping functions) as I write my own functions for algorithmic drawing.
12 |
13 | ## Resources
14 |
15 | I am learning about shaders and glsl from [thebookofshaders](https://thebookofshaders.com/).
16 |
17 | Many many thanks to [Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com) and [Jen Lowe](http://jenlowe.net) for **The Book of Shaders** which is such an amazing resource to learn glsl and algorithmic drawing, and made this project possible.
18 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import ReactTooltip from 'react-tooltip'
3 |
4 | import Parabola from './shaders/Parabola'
5 | import Impulse from './shaders/Impulse'
6 | import ExpoStep from './shaders/ExpoStep'
7 | import Gain from './shaders/Gain'
8 | import PowerCurve from './shaders/PowerCurve'
9 | import CubicPulse from './shaders/CubicPulse'
10 | import SineCurve from './shaders/SineCurve'
11 | import CurveOne from './shaders/CurveOne'
12 | import CurveTwo from './shaders/CurveTwo'
13 | import CurveThree from './shaders/CurveThree'
14 | import CurveFour from './shaders/CurveFour'
15 | import CurveFive from './shaders/CurveFive'
16 |
17 | import { Provider } from './context'
18 |
19 | import './App.css'
20 |
21 | class App extends Component {
22 | state = {
23 | timesync: false
24 | }
25 |
26 | handleTimeSync = e => this.setState(state => ({ timesync: !state.timesync }))
27 |
28 | render() {
29 | return (
30 |
31 |
32 |
Shaping Functions
33 |
34 |
37 |
38 | Playback Time - {' '}
39 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
73 |
74 | );
75 | }
76 | }
77 |
78 | export default App;
79 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: Monoton;
3 | src: url(./font-face/monoton/Monoton-Regular.ttf)
4 | }
5 |
6 | @font-face {
7 | font-family: Signika;
8 | src: url(./font-face/signika/Signika-Regular.otf);
9 | }
10 |
11 | html {
12 | font-family: Signika, sans-serif;
13 | color: #2f2f2f;
14 | }
15 |
16 | h1 {
17 | font-weight: 500;
18 | font-size: 1.8em;
19 | }
20 |
21 | canvas {
22 | box-shadow: 3px 6px 9px 0 #c7c5c7;
23 | -webkit-box-shadow: 3px 6px 9px 0 #c7c5c7;
24 | -moz-box-shadow: 3px 6px 9px 0 #c7c5c7;
25 | border-radius: 5px;
26 | }
27 |
28 | .canvas-grid {
29 | display: grid;
30 | grid-template-columns: repeat(3, 1fr);
31 | justify-items: center;
32 | grid-gap: 10px;
33 | }
34 |
35 | .heading {
36 | font-size: 4em;
37 | font-family: Monoton;
38 | }
39 |
40 | .small-heading {
41 | font-size: 1.2em;
42 | }
43 |
44 | .content-center {
45 | display: flex;
46 | justify-content: center;
47 | }
48 |
49 | .link {
50 | font-size: 1.5em;
51 | }
52 |
53 | a {
54 | text-decoration: none;
55 | color: #2f2f2f;
56 | border-bottom: 2px solid #2f2f2f;
57 | }
58 |
59 | .footer {
60 | margin-top: 5px;
61 | }
62 |
63 | .switch {
64 | position: relative;
65 | display: inline-block;
66 | width: 60px;
67 | height: 34px;
68 | }
69 |
70 | .switch input {
71 | display: none;
72 | }
73 |
74 | .toggle {
75 | position: absolute;
76 | cursor: pointer;
77 | top: 0;
78 | left: 0;
79 | right: 0;
80 | bottom: 0;
81 | background-color: #dedede;
82 | -webkit-transition: 0.4s;
83 | transition: 0.4s;
84 | border-radius: 50px;
85 | }
86 |
87 | .toggle:before {
88 | position: absolute;
89 | content: '';
90 | height: 26px;
91 | width: 26px;
92 | left: 4px;
93 | bottom: 4px;
94 | background-color: white;
95 | -webkit-transition: 0.4s;
96 | transition: 0.4s;
97 | border-radius: 50px;
98 | }
99 |
100 | input:checked + .toggle {
101 | background-color: #424242;
102 | }
103 |
104 | input:focus + .toggle {
105 | box-shadow: 0 0 1px #4f4f4f;
106 | }
107 |
108 | input:checked + .toggle:before {
109 | -webkit-transform: translateX(26px);
110 | -ms-transform: translateX(26px);
111 | transform: translateX(26px);
112 | }
113 |
114 | .toggle:after {
115 | content: 'OFF';
116 | color: white;
117 | display: block;
118 | position: absolute;
119 | transform: translate(-50%, -50%);
120 | top: 50%;
121 | left: 72%;
122 | font-size: 12px;
123 | }
124 |
125 | input:checked + .toggle:after {
126 | content: 'ON';
127 | display: block;
128 | position: absolute;
129 | transform: translate(-50%, -50%);
130 | left: 25%;
131 | font-size: 12px;
132 | }
133 |
134 | input:checked + .toggle .on {
135 | display: block;
136 | }
137 |
138 | input:checked + .toggle .off {
139 | display: none;
140 | }
141 |
142 | @media only screen and (max-width: 480px) {
143 | canvas {
144 | width: 250px;
145 | height: 250px;
146 | }
147 |
148 | .canvas-grid {
149 | display: grid;
150 | grid-template-columns: 1fr;
151 | justify-items: center;
152 | grid-gap: 5px;
153 | }
154 |
155 | .switch {
156 | width: 50px;
157 | height: 25px;
158 | }
159 |
160 | .toggle:before {
161 | height: 20px;
162 | width: 20px;
163 | left: 3px;
164 | bottom: 3px;
165 | border-radius: 25px;
166 | }
167 |
168 | /* .toggle:after {
169 | top: 50%;
170 | left: 42%;
171 | font-size: 10px;
172 | } */
173 |
174 | .heading {
175 | font-size: 1.5em;
176 | word-spacing: 5px;
177 | }
178 |
179 | h1 {
180 | font-size: 1.5em;
181 | }
182 |
183 | .link {
184 | font-size: 14px;
185 | }
186 |
187 | .small-heading {
188 | font-size: 12px;
189 | }
190 | }
--------------------------------------------------------------------------------