├── .gitignore
├── nytm.pdf
├── favicon.png
├── audio
├── harp_00.mp3
├── harp_01.mp3
├── harp_02.mp3
├── harp_03.mp3
├── harp_04.mp3
├── harp_05.mp3
├── harp_06.mp3
├── harp_07.mp3
├── harp_08.mp3
├── harp_09.mp3
├── harp_10.mp3
├── harp_11.mp3
├── harp_12.mp3
├── harp_13.mp3
├── harp_14.mp3
├── harp_15.mp3
├── harp_16.mp3
├── harp_17.mp3
├── harp_18.mp3
├── harp_19.mp3
├── harp_20.mp3
├── harp_21.mp3
├── harp_22.mp3
├── harp_23.mp3
├── harp_24.mp3
├── harp_25.mp3
├── harp_26.mp3
├── harp_27.mp3
├── harp_28.mp3
├── harp_29.mp3
├── harp_30.mp3
├── harp_31.mp3
├── harp_32.mp3
├── harp_33.mp3
├── harp_34.mp3
├── harp_35.mp3
├── harp_36.mp3
├── harp_37.mp3
├── harp_38.mp3
├── harp_39.mp3
├── harp_40.mp3
├── harp_41.mp3
├── harp_42.mp3
├── harp_43.mp3
├── harp_44.mp3
├── harp_45.mp3
├── harp_46.mp3
├── harp_47.mp3
├── harp_48.mp3
├── harp_49.mp3
├── harp_50.mp3
├── harp_51.mp3
├── harp_52.mp3
├── harp_53.mp3
├── harp_54.mp3
├── harp_55.mp3
├── harp_56.mp3
├── harp_57.mp3
├── harp_58.mp3
├── harp_59.mp3
├── cello_00.mp3
├── cello_01.mp3
├── cello_02.mp3
├── cello_03.mp3
├── cello_04.mp3
├── cello_05.mp3
├── cello_06.mp3
├── cello_07.mp3
├── cello_08.mp3
├── cello_09.mp3
├── cello_10.mp3
├── cello_11.mp3
├── cello_12.mp3
├── cello_13.mp3
├── cello_14.mp3
├── cello_15.mp3
├── cello_16.mp3
├── cello_17.mp3
├── cello_18.mp3
└── cello_19.mp3
├── fonts
├── ebgaramond12-sc.eot
├── ebgaramond12-sc.ttf
├── ebgaramond12-sc.woff
├── ebgaramond12-sc.woff2
├── hack-the-hackpad-icon.eot
├── hack-the-hackpad-icon.ttf
├── hack-the-hackpad-icon.woff
└── hack-the-hackpad-icon.svg
├── stringAnimation
├── css
│ └── style.css
├── index.html
└── js
│ ├── main.js
│ ├── main-alone.js
│ ├── main-old.js
│ └── class.js
├── css
├── mobile.css.map
├── underline.css
├── tablet.css.map
├── reset.css.map
├── tablet.css
├── tablet.scss
├── reset.scss
├── reset.css
├── animation.css.map
├── animation.css
├── animation.scss
├── mobile.scss
├── mobile.css
├── style.css.map
├── style.scss
└── style.css
├── js
├── baseline-ratio.js
├── classie.js
├── underline.js
├── single-underline.js
├── multiple.js
├── multiple-underline.js
└── guitar-string.js
├── i
├── logo.svg
└── logo-long.svg
├── README.md
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | **/.sass-cache
3 | **/.sass-cache/*
--------------------------------------------------------------------------------
/nytm.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/nytm.pdf
--------------------------------------------------------------------------------
/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/favicon.png
--------------------------------------------------------------------------------
/audio/harp_00.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_00.mp3
--------------------------------------------------------------------------------
/audio/harp_01.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_01.mp3
--------------------------------------------------------------------------------
/audio/harp_02.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_02.mp3
--------------------------------------------------------------------------------
/audio/harp_03.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_03.mp3
--------------------------------------------------------------------------------
/audio/harp_04.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_04.mp3
--------------------------------------------------------------------------------
/audio/harp_05.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_05.mp3
--------------------------------------------------------------------------------
/audio/harp_06.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_06.mp3
--------------------------------------------------------------------------------
/audio/harp_07.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_07.mp3
--------------------------------------------------------------------------------
/audio/harp_08.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_08.mp3
--------------------------------------------------------------------------------
/audio/harp_09.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_09.mp3
--------------------------------------------------------------------------------
/audio/harp_10.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_10.mp3
--------------------------------------------------------------------------------
/audio/harp_11.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_11.mp3
--------------------------------------------------------------------------------
/audio/harp_12.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_12.mp3
--------------------------------------------------------------------------------
/audio/harp_13.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_13.mp3
--------------------------------------------------------------------------------
/audio/harp_14.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_14.mp3
--------------------------------------------------------------------------------
/audio/harp_15.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_15.mp3
--------------------------------------------------------------------------------
/audio/harp_16.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_16.mp3
--------------------------------------------------------------------------------
/audio/harp_17.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_17.mp3
--------------------------------------------------------------------------------
/audio/harp_18.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_18.mp3
--------------------------------------------------------------------------------
/audio/harp_19.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_19.mp3
--------------------------------------------------------------------------------
/audio/harp_20.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_20.mp3
--------------------------------------------------------------------------------
/audio/harp_21.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_21.mp3
--------------------------------------------------------------------------------
/audio/harp_22.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_22.mp3
--------------------------------------------------------------------------------
/audio/harp_23.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_23.mp3
--------------------------------------------------------------------------------
/audio/harp_24.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_24.mp3
--------------------------------------------------------------------------------
/audio/harp_25.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_25.mp3
--------------------------------------------------------------------------------
/audio/harp_26.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_26.mp3
--------------------------------------------------------------------------------
/audio/harp_27.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_27.mp3
--------------------------------------------------------------------------------
/audio/harp_28.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_28.mp3
--------------------------------------------------------------------------------
/audio/harp_29.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_29.mp3
--------------------------------------------------------------------------------
/audio/harp_30.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_30.mp3
--------------------------------------------------------------------------------
/audio/harp_31.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_31.mp3
--------------------------------------------------------------------------------
/audio/harp_32.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_32.mp3
--------------------------------------------------------------------------------
/audio/harp_33.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_33.mp3
--------------------------------------------------------------------------------
/audio/harp_34.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_34.mp3
--------------------------------------------------------------------------------
/audio/harp_35.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_35.mp3
--------------------------------------------------------------------------------
/audio/harp_36.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_36.mp3
--------------------------------------------------------------------------------
/audio/harp_37.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_37.mp3
--------------------------------------------------------------------------------
/audio/harp_38.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_38.mp3
--------------------------------------------------------------------------------
/audio/harp_39.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_39.mp3
--------------------------------------------------------------------------------
/audio/harp_40.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_40.mp3
--------------------------------------------------------------------------------
/audio/harp_41.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_41.mp3
--------------------------------------------------------------------------------
/audio/harp_42.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_42.mp3
--------------------------------------------------------------------------------
/audio/harp_43.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_43.mp3
--------------------------------------------------------------------------------
/audio/harp_44.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_44.mp3
--------------------------------------------------------------------------------
/audio/harp_45.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_45.mp3
--------------------------------------------------------------------------------
/audio/harp_46.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_46.mp3
--------------------------------------------------------------------------------
/audio/harp_47.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_47.mp3
--------------------------------------------------------------------------------
/audio/harp_48.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_48.mp3
--------------------------------------------------------------------------------
/audio/harp_49.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_49.mp3
--------------------------------------------------------------------------------
/audio/harp_50.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_50.mp3
--------------------------------------------------------------------------------
/audio/harp_51.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_51.mp3
--------------------------------------------------------------------------------
/audio/harp_52.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_52.mp3
--------------------------------------------------------------------------------
/audio/harp_53.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_53.mp3
--------------------------------------------------------------------------------
/audio/harp_54.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_54.mp3
--------------------------------------------------------------------------------
/audio/harp_55.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_55.mp3
--------------------------------------------------------------------------------
/audio/harp_56.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_56.mp3
--------------------------------------------------------------------------------
/audio/harp_57.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_57.mp3
--------------------------------------------------------------------------------
/audio/harp_58.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_58.mp3
--------------------------------------------------------------------------------
/audio/harp_59.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/harp_59.mp3
--------------------------------------------------------------------------------
/audio/cello_00.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_00.mp3
--------------------------------------------------------------------------------
/audio/cello_01.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_01.mp3
--------------------------------------------------------------------------------
/audio/cello_02.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_02.mp3
--------------------------------------------------------------------------------
/audio/cello_03.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_03.mp3
--------------------------------------------------------------------------------
/audio/cello_04.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_04.mp3
--------------------------------------------------------------------------------
/audio/cello_05.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_05.mp3
--------------------------------------------------------------------------------
/audio/cello_06.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_06.mp3
--------------------------------------------------------------------------------
/audio/cello_07.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_07.mp3
--------------------------------------------------------------------------------
/audio/cello_08.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_08.mp3
--------------------------------------------------------------------------------
/audio/cello_09.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_09.mp3
--------------------------------------------------------------------------------
/audio/cello_10.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_10.mp3
--------------------------------------------------------------------------------
/audio/cello_11.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_11.mp3
--------------------------------------------------------------------------------
/audio/cello_12.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_12.mp3
--------------------------------------------------------------------------------
/audio/cello_13.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_13.mp3
--------------------------------------------------------------------------------
/audio/cello_14.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_14.mp3
--------------------------------------------------------------------------------
/audio/cello_15.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_15.mp3
--------------------------------------------------------------------------------
/audio/cello_16.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_16.mp3
--------------------------------------------------------------------------------
/audio/cello_17.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_17.mp3
--------------------------------------------------------------------------------
/audio/cello_18.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_18.mp3
--------------------------------------------------------------------------------
/audio/cello_19.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/audio/cello_19.mp3
--------------------------------------------------------------------------------
/fonts/ebgaramond12-sc.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/fonts/ebgaramond12-sc.eot
--------------------------------------------------------------------------------
/fonts/ebgaramond12-sc.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/fonts/ebgaramond12-sc.ttf
--------------------------------------------------------------------------------
/fonts/ebgaramond12-sc.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/fonts/ebgaramond12-sc.woff
--------------------------------------------------------------------------------
/fonts/ebgaramond12-sc.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/fonts/ebgaramond12-sc.woff2
--------------------------------------------------------------------------------
/fonts/hack-the-hackpad-icon.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/fonts/hack-the-hackpad-icon.eot
--------------------------------------------------------------------------------
/fonts/hack-the-hackpad-icon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/fonts/hack-the-hackpad-icon.ttf
--------------------------------------------------------------------------------
/fonts/hack-the-hackpad-icon.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wentin/underlineJS/HEAD/fonts/hack-the-hackpad-icon.woff
--------------------------------------------------------------------------------
/stringAnimation/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 20px;
3 | padding: 0px;
4 | }
5 | canvas {
6 | background-color: #fff;
7 | margin: auto;
8 | display: block;
9 | width: 100%;
10 | height: 100%;
11 | }
--------------------------------------------------------------------------------
/css/mobile.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": ";AAEA,2DAEuB;EAEtB,iBAAM;IACL,KAAK,EAAE,IAAI;IACX,iBAAiB,EAAE,iBAAiB;IACpC,SAAS,EAAE,iBAAiB;IAMtB,qBAAI;MACA,iBAAiB,EAAE,oBAAoB;MACvC,SAAS,EAAE,oBAAoB;IAEnC,yBAAQ;MACJ,OAAO,EAAE,CAAC;IAEd,yBAAQ;MACJ,OAAO,EAAE,CAAC;EAWlB,iBAAM;IACR,OAAO,EAAE,IAAI",
4 | "sources": ["mobile.scss"],
5 | "names": [],
6 | "file": "mobile.css"
7 | }
--------------------------------------------------------------------------------
/css/underline.css:
--------------------------------------------------------------------------------
1 | .underline {
2 | position: relative;
3 | }
4 | .underline span {
5 | pointer-events: none;
6 |
7 | }
8 | .underline canvas {
9 | pointer-events: auto;
10 | position: absolute;
11 | top: 0;
12 | left: 0;
13 | /*background-color: rgba(222, 222, 222, 0.1);*/
14 | /*z-index: -1;*/
15 | -moz-user-select: none;
16 | -khtml-user-select: none;
17 | -webkit-user-select: none;
18 | -o-user-select: none;
19 | cursor: pointer;
20 | }
--------------------------------------------------------------------------------
/css/tablet.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": ";AACA,gEAEwB;EAGvB,iBAAM;IACL,KAAK,EAAE,IAAI;EAEZ,iBAAM;IACL,IAAI,EAAE,IAAI;EAGZ,eAAW;IACP,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,QAAQ;IACjB,uBAAU;MACN,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,IAAI;IAEhB,sBAAS;MACL,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,IAAI;AAOpB,4GAG8B;EAIlB,8BAAQ;IACJ,iBAAiB,EAAE,eAAe;IAClC,SAAS,EAAE,eAAe;IAC1B,OAAO,EAAE,CAAC",
4 | "sources": ["tablet.scss"],
5 | "names": [],
6 | "file": "tablet.css"
7 | }
--------------------------------------------------------------------------------
/css/reset.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": ";;;;AAKA;;;;;;;;;;;;wBAYyB;EACxB,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,IAAI,EAAE,OAAO;EACb,cAAc,EAAE,QAAQ;;;AAGzB;0CAC2C;EAC1C,OAAO,EAAE,KAAK;;AAEf,IAAK;EACJ,WAAW,EAAE,CAAC;;AAEf,MAAO;EACN,UAAU,EAAE,IAAI;;AAEjB,aAAc;EACb,MAAM,EAAE,IAAI;;AAEb;iBACkB;EACjB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,IAAI;;AAEd,KAAM;EACL,eAAe,EAAE,QAAQ;EACzB,cAAc,EAAE,CAAC",
4 | "sources": ["reset.scss"],
5 | "names": [],
6 | "file": "reset.css"
7 | }
--------------------------------------------------------------------------------
/stringAnimation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Experiment
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/css/tablet.css:
--------------------------------------------------------------------------------
1 | /* iPads (portrait) ----------- */
2 | @media only screen and (min-width: 801px) and (max-width: 960px) {
3 | body header .menu {
4 | right: 20px; }
5 | body header .logo {
6 | left: 20px; }
7 | body ul.comment {
8 | width: 100%;
9 | margin: 40px 0 40px 0;
10 | padding: 40px 0px; }
11 | body ul.comment::before {
12 | width: 120px;
13 | height: 24px; }
14 | body ul.comment::after {
15 | width: 120px;
16 | height: 24px; } }
17 | @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: landscape) {
18 | .collapse header .logo #ackpad {
19 | -webkit-transform: translate(0, 0);
20 | transform: translate(0, 0);
21 | opacity: 0; } }
22 |
23 | /*# sourceMappingURL=tablet.css.map */
24 |
--------------------------------------------------------------------------------
/css/tablet.scss:
--------------------------------------------------------------------------------
1 | /* iPads (portrait) ----------- */
2 | @media only screen
3 | and (min-width : 801px)
4 | and (max-width : 960px) {
5 | body {
6 | header {
7 | .menu {
8 | right: 20px;
9 | }
10 | .logo {
11 | left: 20px;
12 | }
13 | }
14 | ul.comment {
15 | width: 100%;
16 | margin: 40px 0 40px 0;
17 | padding: 40px 0px;
18 | &::before {
19 | width: 120px;
20 | height: 24px;
21 | }
22 | &::after {
23 | width: 120px;
24 | height: 24px;
25 | }
26 | }
27 |
28 |
29 | }}
30 |
31 | @media only screen
32 | and (min-device-width : 768px)
33 | and (max-device-width : 1024px)
34 | and (orientation : landscape) {
35 | header {
36 | .logo {
37 | .collapse & {
38 | #ackpad {
39 | -webkit-transform: translate(0, 0);
40 | transform: translate(0, 0);
41 | opacity: 0;
42 | }
43 | }
44 | }
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/css/reset.scss:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 |
6 | html, body, div, span, applet, object, iframe,
7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8 | a, abbr, acronym, address, big, cite, code,
9 | del, dfn, em, img, ins, kbd, q, s, samp,
10 | small, strike, strong, sub, sup, tt, var,
11 | b, u, i, center,
12 | dl, dt, dd, ol, ul, li,
13 | fieldset, form, label, legend,
14 | table, caption, tbody, tfoot, thead, tr, th, td,
15 | article, aside, canvas, details, embed,
16 | figure, figcaption, footer, header, hgroup,
17 | menu, nav, output, ruby, section, summary,
18 | time, mark, audio, video {
19 | margin: 0;
20 | padding: 0;
21 | border: 0;
22 | font-size: 100%;
23 | font: inherit;
24 | vertical-align: baseline;
25 | }
26 | /* HTML5 display-role reset for older browsers */
27 | article, aside, details, figcaption, figure,
28 | footer, header, hgroup, menu, nav, section {
29 | display: block;
30 | }
31 | body {
32 | line-height: 1;
33 | }
34 | ol, ul {
35 | list-style: none;
36 | }
37 | blockquote, q {
38 | quotes: none;
39 | }
40 | blockquote:before, blockquote:after,
41 | q:before, q:after {
42 | content: '';
43 | content: none;
44 | }
45 | table {
46 | border-collapse: collapse;
47 | border-spacing: 0;
48 | }
--------------------------------------------------------------------------------
/css/reset.css:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 | html, body, div, span, applet, object, iframe,
6 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
7 | a, abbr, acronym, address, big, cite, code,
8 | del, dfn, em, img, ins, kbd, q, s, samp,
9 | small, strike, strong, sub, sup, tt, var,
10 | b, u, i, center,
11 | dl, dt, dd, ol, ul, li,
12 | fieldset, form, label, legend,
13 | table, caption, tbody, tfoot, thead, tr, th, td,
14 | article, aside, canvas, details, embed,
15 | figure, figcaption, footer, header, hgroup,
16 | menu, nav, output, ruby, section, summary,
17 | time, mark, audio, video {
18 | margin: 0;
19 | padding: 0;
20 | border: 0;
21 | font-size: 100%;
22 | font: inherit;
23 | vertical-align: baseline; }
24 |
25 | /* HTML5 display-role reset for older browsers */
26 | article, aside, details, figcaption, figure,
27 | footer, header, hgroup, menu, nav, section {
28 | display: block; }
29 |
30 | body {
31 | line-height: 1; }
32 |
33 | ol, ul {
34 | list-style: none; }
35 |
36 | blockquote, q {
37 | quotes: none; }
38 |
39 | blockquote:before, blockquote:after,
40 | q:before, q:after {
41 | content: '';
42 | content: none; }
43 |
44 | table {
45 | border-collapse: collapse;
46 | border-spacing: 0; }
47 |
48 | /*# sourceMappingURL=reset.css.map */
49 |
--------------------------------------------------------------------------------
/css/animation.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": ";;;AAIA,2BAOC;EANG,IAAI;IACA,iBAAiB,EAAE,YAAY;EAEnC,EAAE;IACE,iBAAiB,EAAE,cAAc;AAIzC,oCACwB;EAGtB,gBAAO;IACN,2BAA2B,EAAE,0BAA0B;IACvD,mBAAmB,EAAE,kBAAkB;IACvC,2BAA2B,EAAE,EAAE;IAC/B,mBAAmB,EAAE,EAAE;EAGxB,wBAAc;IACb,iBAAiB,EAAE,iBAAiB;IACpC,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;EAGX,eAAG;IACF,kCAAkC,EAAE,4BAAyB;IAC7D,0BAA0B,EAAE,4BAAyB;IACrD,2BAA2B,EAAE,IAAI;IACjC,mBAAmB,EAAE,IAAI;EAG1B,mBAAO;IACN,WAAW,EAAE,gBAAgB;IACvB,UAAU,EAAE,GAAG;EAGvB,WAAO;IACN,2BAA2B,EAAE,0BAA0B;IACvD,mBAAmB,EAAE,kBAAkB;IACvC,2BAA2B,EAAE,EAAE;IAC/B,mBAAmB,EAAE,EAAE;IACvB,iBAAiB,EAAE,iBAAiB;IACpC,SAAS,EAAE,iBAAiB;IAC5B,OAAO,EAAE,CAAC;;EAKX,sBAAS;IACL,wBAAwB,EAAE,EAAE;IAC5B,gBAAgB,EAAE,EAAE;IACpB,iBAAiB,EAAE,2BAA2B;IAC9C,SAAS,EAAE,2BAA2B;IACzC,OAAO,EAAE,CAAC;IACP,OAAO,EAAE,EAAE;EAGd,iCAAc;IACb,iBAAiB,EAAE,aAAa;IAChC,SAAS,EAAE,aAAa;IACxB,OAAO,EAAE,CAAC;EAEX,wBAAG;IACF,OAAO,EAAE,CAAC;IACV,iBAAiB,EAAE,4BAA4B;IAC/C,SAAS,EAAE,4BAA4B;EAExC,+BAAU;IACT,wBAAwB,EAAE,KAAK;IAC/B,gBAAgB,EAAE,KAAK;EAGxB,8CAA2B;IAC1B,wBAAwB,EAAE,IAAI;IAC9B,gBAAgB,EAAE,IAAI;EAEvB,sCAAmB;IAClB,wBAAwB,EAAE,KAAK;IAC/B,gBAAgB,EAAE,KAAK;EAExB,uCAAoB;IACnB,wBAAwB,EAAE,KAAK;IAC/B,gBAAgB,EAAE,KAAK;EAExB,uCAAoB;IACnB,wBAAwB,EAAE,KAAK;IAC/B,gBAAgB,EAAE,KAAK;EAKzB,oBAAO;IACN,iBAAiB,EAAE,aAAa;IAChC,SAAS,EAAE,aAAa;IACxB,OAAO,EAAE,CAAC;IACV,wBAAwB,EAAE,IAAI;IAC9B,gBAAgB,EAAE,IAAI",
4 | "sources": ["animation.scss"],
5 | "names": [],
6 | "file": "animation.css"
7 | }
--------------------------------------------------------------------------------
/js/baseline-ratio.js:
--------------------------------------------------------------------------------
1 | /* Universal Module Definition */
2 | (function (root, factory) {
3 | if (typeof define === 'function' && define.amd) {
4 | // AMD. Register as a named AMD module.
5 | define('baselineRatio', [], function () {
6 | return (root.baselineRatio = factory());
7 | });
8 | } else if (typeof exports === 'object') {
9 | // Node. Does not work with strict CommonJS, but
10 | // only CommonJS-like enviroments that support module.exports,
11 | // like Node.
12 | module.exports = factory();
13 | } else {
14 | // Browser globals
15 | root.baselineRatio = factory();
16 | }
17 | }(this, function () {
18 | var baselineRatio = function(elem) {
19 | // Get the baseline in the context of whatever element is passed in.
20 | elem = elem || document.body;
21 |
22 | // The container is a little defenseive.
23 | var container = document.createElement('div');
24 | container.style.display = "block";
25 | container.style.position = "absolute";
26 | container.style.bottom = "0";
27 | container.style.right = "0";
28 | container.style.width = "0px";
29 | container.style.height = "0px";
30 | container.style.margin = "0";
31 | container.style.padding = "0";
32 | container.style.visibility = "hidden";
33 | container.style.overflow = "hidden";
34 |
35 | // Intentionally unprotected style definition.
36 | var small = document.createElement('span');
37 | var large = document.createElement('span');
38 |
39 | // Large numbers help improve accuracy.
40 | small.style.fontSize = "0px";
41 | large.style.fontSize = "2000px";
42 |
43 | small.innerHTML = "X";
44 | large.innerHTML = "X";
45 |
46 | container.appendChild(small);
47 | container.appendChild(large);
48 |
49 | // Put the element in the DOM for a split second.
50 | elem.appendChild(container);
51 | var smalldims = small.getBoundingClientRect();
52 | var largedims = large.getBoundingClientRect();
53 | elem.removeChild(container);
54 |
55 | // Calculate where the baseline was, percentage-wise.
56 | var baselineposition = smalldims.top - largedims.top;
57 | var height = largedims.height;
58 |
59 | return 1 - (baselineposition / height);
60 | }
61 |
62 | return baselineRatio;
63 | }));
64 |
--------------------------------------------------------------------------------
/js/classie.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * classie v1.0.1
3 | * class helper functions
4 | * from bonzo https://github.com/ded/bonzo
5 | * MIT license
6 | *
7 | * classie.has( elem, 'my-class' ) -> true/false
8 | * classie.add( elem, 'my-new-class' )
9 | * classie.remove( elem, 'my-unwanted-class' )
10 | * classie.toggle( elem, 'my-class' )
11 | */
12 |
13 | /*jshint browser: true, strict: true, undef: true, unused: true */
14 | /*global define: false, module: false */
15 |
16 | ( function( window ) {
17 |
18 | 'use strict';
19 |
20 | // class helper functions from bonzo https://github.com/ded/bonzo
21 |
22 | function classReg( className ) {
23 | return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
24 | }
25 |
26 | // classList support for class management
27 | // altho to be fair, the api sucks because it won't accept multiple classes at once
28 | var hasClass, addClass, removeClass;
29 |
30 | if ( 'classList' in document.documentElement ) {
31 | hasClass = function( elem, c ) {
32 | return elem.classList.contains( c );
33 | };
34 | addClass = function( elem, c ) {
35 | elem.classList.add( c );
36 | };
37 | removeClass = function( elem, c ) {
38 | elem.classList.remove( c );
39 | };
40 | }
41 | else {
42 | hasClass = function( elem, c ) {
43 | return classReg( c ).test( elem.className );
44 | };
45 | addClass = function( elem, c ) {
46 | if ( !hasClass( elem, c ) ) {
47 | elem.className = elem.className + ' ' + c;
48 | }
49 | };
50 | removeClass = function( elem, c ) {
51 | elem.className = elem.className.replace( classReg( c ), ' ' );
52 | };
53 | }
54 |
55 | function toggleClass( elem, c ) {
56 | var fn = hasClass( elem, c ) ? removeClass : addClass;
57 | fn( elem, c );
58 | }
59 |
60 | var classie = {
61 | // full names
62 | hasClass: hasClass,
63 | addClass: addClass,
64 | removeClass: removeClass,
65 | toggleClass: toggleClass,
66 | // short names
67 | has: hasClass,
68 | add: addClass,
69 | remove: removeClass,
70 | toggle: toggleClass
71 | };
72 |
73 | // transport
74 | if ( typeof define === 'function' && define.amd ) {
75 | // AMD
76 | define( classie );
77 | } else if ( typeof exports === 'object' ) {
78 | // CommonJS
79 | module.exports = classie;
80 | } else {
81 | // browser global
82 | window.classie = classie;
83 | }
84 |
85 | })( window );
--------------------------------------------------------------------------------
/stringAnimation/js/main.js:
--------------------------------------------------------------------------------
1 | /*Created By Wenting Zhang
2 | */
3 |
4 | var dist = function(x, y, x0, y0){
5 | return Math.sqrt((x -= x0) * x + (y -= y0) * y);
6 | };
7 |
8 | var circleCenter = function(startPoint, thirdPoint, endPoint){
9 | var dy1 = thirdPoint.y - startPoint.y;
10 | var dx1 = thirdPoint.x - startPoint.x;
11 | var dy2 = endPoint.y - thirdPoint.y;
12 | var dx2 = endPoint.x - thirdPoint.x;
13 |
14 | var aSlope = dy1/dx1;
15 | var bSlope = dy2/dx2;
16 |
17 |
18 | var centerX = (aSlope*bSlope*(startPoint.y - endPoint.y) + bSlope*(startPoint.x + thirdPoint.x)
19 | - aSlope*(thirdPoint.x+endPoint.x) )/( 2* (bSlope-aSlope) );
20 | var centerY = -1*(centerX - (startPoint.x+thirdPoint.x)/2)/aSlope + (startPoint.y+thirdPoint.y)/2;
21 | var r = dist(centerX, centerY, startPoint.x, startPoint.y)
22 |
23 | return {
24 | x: centerX,
25 | y: centerY,
26 | r: r
27 | };
28 | }
29 |
30 | var Point = function (x,y){
31 | this.x=x;
32 | this.y=y;
33 | }
34 |
35 | var intersects = function(a, b, c, d, p, q, r, s) {
36 | // returns true if the line from (a,b)->(c,d) intersects with (p,q)->(r,s)
37 | var det, gamma, lambda;
38 | det = (c - a) * (s - q) - (r - p) * (d - b);
39 | if (det === 0) {
40 | return false;
41 | } else {
42 | lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / det;
43 | gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / det;
44 | return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1);
45 | }
46 | };
47 |
48 |
49 |
50 | window.requestAnimFrame = (function(callback) {
51 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
52 | function(callback) {
53 | window.setTimeout(callback, 1000 / 60);
54 | };
55 | })();
56 |
57 | window.addEventListener('resize', function(){
58 | //brower resize
59 | myString.resize();
60 | }, false)
61 |
62 | var myString = new String('myCanvas', new Point(300, 100.5), new Point(600, 100.5),
63 | 1, "#bad424");
64 | (function animate() {
65 | // update
66 | myString.update();
67 |
68 | // clear
69 | myString.clear();
70 |
71 | // draw stuff
72 | // console.log("run every frame");
73 | myString.draw();
74 |
75 |
76 | // request new frame
77 | requestAnimFrame(function() {
78 | animate();
79 | });
80 | })()
81 |
82 |
--------------------------------------------------------------------------------
/css/animation.css:
--------------------------------------------------------------------------------
1 | /* -------------------------- */
2 | /* Push */
3 | /* -------------------------- */
4 | @-webkit-keyframes rotating {
5 | from {
6 | -webkit-transform: rotate(0deg); }
7 | to {
8 | -webkit-transform: rotate(360deg); } }
9 | @media screen and (min-width: 801px) {
10 | body article > * {
11 | -webkit-transition-property: opacity, -webkit-transform;
12 | transition-property: opacity, transform;
13 | -webkit-transition-duration: 1s;
14 | transition-duration: 1s; }
15 | body article > *:not(h1) {
16 | -webkit-transform: translateY(400px);
17 | transform: translateY(400px);
18 | opacity: 0; }
19 | body article h1 {
20 | -webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
21 | transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
22 | -webkit-transition-duration: 1.2s;
23 | transition-duration: 1.2s; }
24 | body article h1 + * {
25 | padding-top: 105px !important;
26 | margin-top: 0px; }
27 | body footer {
28 | -webkit-transition-property: opacity, -webkit-transform;
29 | transition-property: opacity, transform;
30 | -webkit-transition-duration: 1s;
31 | transition-duration: 1s;
32 | -webkit-transform: translateY(400px);
33 | transform: translateY(400px);
34 | opacity: 0; }
35 |
36 | body.collapse .trigger {
37 | -webkit-transition-delay: 0s;
38 | transition-delay: 0s;
39 | -webkit-transform: translateY(150%) scale(0.9);
40 | transform: translateY(150%) scale(0.9);
41 | opacity: 0;
42 | z-index: -1; }
43 | body.collapse article > *:not(h1) {
44 | -webkit-transform: translateY(0);
45 | transform: translateY(0);
46 | opacity: 1; }
47 | body.collapse article h1 {
48 | opacity: 0;
49 | -webkit-transform: translateY(-100%) scale(0.9);
50 | transform: translateY(-100%) scale(0.9); }
51 | body.collapse article *:not(h1) {
52 | -webkit-transition-delay: 0.98s;
53 | transition-delay: 0.98s; }
54 | body.collapse article > *:not(h1):nth-child(8) {
55 | -webkit-transition-delay: 0.5s;
56 | transition-delay: 0.5s; }
57 | body.collapse article > *:nth-child(9) {
58 | -webkit-transition-delay: 0.62s;
59 | transition-delay: 0.62s; }
60 | body.collapse article > *:nth-child(10) {
61 | -webkit-transition-delay: 0.74s;
62 | transition-delay: 0.74s; }
63 | body.collapse article > *:nth-child(11) {
64 | -webkit-transition-delay: 0.86s;
65 | transition-delay: 0.86s; }
66 | body.collapse footer {
67 | -webkit-transform: translateY(0);
68 | transform: translateY(0);
69 | opacity: 1;
70 | -webkit-transition-delay: 0.8s;
71 | transition-delay: 0.8s; } }
72 |
73 | /*# sourceMappingURL=animation.css.map */
74 |
--------------------------------------------------------------------------------
/i/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/css/animation.scss:
--------------------------------------------------------------------------------
1 | /* -------------------------- */
2 | /* Push */
3 | /* -------------------------- */
4 |
5 | @-webkit-keyframes rotating {
6 | from{
7 | -webkit-transform: rotate(0deg);
8 | }
9 | to{
10 | -webkit-transform: rotate(360deg);
11 | }
12 | }
13 |
14 | @media screen
15 | and (min-width : 801px) {
16 | body {
17 | article{
18 | & > * {
19 | -webkit-transition-property: opacity, -webkit-transform;
20 | transition-property: opacity, transform;
21 | -webkit-transition-duration: 1s;
22 | transition-duration: 1s;
23 | }
24 |
25 | & > *:not(h1) {
26 | -webkit-transform: translateY(400px);
27 | transform: translateY(400px);
28 | opacity: 0;
29 | }
30 |
31 | h1 {
32 | -webkit-transition-timing-function: cubic-bezier(0.7,0,0.3,1);
33 | transition-timing-function: cubic-bezier(0.7,0,0.3,1);
34 | -webkit-transition-duration: 1.2s;
35 | transition-duration: 1.2s;
36 | }
37 |
38 | h1 + * {
39 | padding-top: 105px !important;
40 | margin-top: 0px;
41 | }
42 | }
43 | footer {
44 | -webkit-transition-property: opacity, -webkit-transform;
45 | transition-property: opacity, transform;
46 | -webkit-transition-duration: 1s;
47 | transition-duration: 1s;
48 | -webkit-transform: translateY(400px);
49 | transform: translateY(400px);
50 | opacity: 0;
51 | }
52 | }
53 |
54 | body.collapse {
55 | .trigger {
56 | -webkit-transition-delay: 0s;
57 | transition-delay: 0s;
58 | -webkit-transform: translateY(150%) scale(0.9);
59 | transform: translateY(150%) scale(0.9);
60 | opacity: 0;
61 | z-index: -1;
62 | }
63 | article{
64 | & > *:not(h1) {
65 | -webkit-transform: translateY(0);
66 | transform: translateY(0);
67 | opacity: 1;
68 | }
69 | h1 {
70 | opacity: 0;
71 | -webkit-transform: translateY(-100%) scale(0.9);
72 | transform: translateY(-100%) scale(0.9);
73 | }
74 | *:not(h1) {
75 | -webkit-transition-delay: 0.98s;
76 | transition-delay: 0.98s;
77 | }
78 |
79 | & > *:not(h1):nth-child(8) {
80 | -webkit-transition-delay: 0.5s;
81 | transition-delay: 0.5s;
82 | }
83 | & > *:nth-child(9) {
84 | -webkit-transition-delay: 0.62s;
85 | transition-delay: 0.62s;
86 | }
87 | & > *:nth-child(10) {
88 | -webkit-transition-delay: 0.74s;
89 | transition-delay: 0.74s;
90 | }
91 | & > *:nth-child(11) {
92 | -webkit-transition-delay: 0.86s;
93 | transition-delay: 0.86s;
94 | }
95 |
96 | }
97 |
98 | footer {
99 | -webkit-transform: translateY(0);
100 | transform: translateY(0);
101 | opacity: 1;
102 | -webkit-transition-delay: 0.8s;
103 | transition-delay: 0.8s;
104 | }
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/stringAnimation/js/main-alone.js:
--------------------------------------------------------------------------------
1 | /*Created By Wenting Zhang
2 | javascript color blend mode globalCompositeOperation
3 | */
4 |
5 | var canvas = document.getElementById('myCanvas');
6 | var ctx = canvas.getContext('2d');
7 |
8 | var dist = function(x, y, x0, y0){
9 | return Math.sqrt((x -= x0) * x + (y -= y0) * y);
10 | };
11 |
12 | var circleCenter = function(x0, y0, x1, y1, x2, y2){
13 | var dy1 = y1 - y0;
14 | var dx1 = x1 - x0;
15 | var dy2 = y2 - y1;
16 | var dx2 = x2 - x1;
17 |
18 | var aSlope = dy1/dx1;
19 | var bSlope = dy2/dx2;
20 |
21 | centerX = (aSlope*bSlope*(y0 - y2) + bSlope*(x0 + x1)
22 | - aSlope*(x1+x2) )/( 2* (bSlope-aSlope) );
23 | centerY = -1*(centerX - (x0+x1)/2)/aSlope + (y0+y1)/2;
24 |
25 | return [centerX, centerY];
26 | }
27 |
28 | var drawArc = function(controlX, controlY, ctx){
29 | var ctx = ctx;
30 | var controlX = controlX;
31 | var controlY = controlY;
32 |
33 | var cx = circleCenter(xp0, yp0, controlX, controlY, xp1, yp1)[0];
34 | var cy = circleCenter(xp0, yp0, controlX, controlY, xp1, yp1)[1];
35 | var r = dist(cx, cy, xp0, yp0);
36 | var angle = Math.atan2(cx-xp0, cy-yp0);
37 |
38 | /*if(controlY-yp0 < 1) {
39 | ctx.beginPath();
40 | ctx.moveTo(xp0, yp0);
41 | ctx.lineTo(xp1, yp1);
42 | ctx.stroke();
43 | } else {
44 |
45 | }*/
46 |
47 | // console.log(angle);
48 | if (!angle){
49 | ctx.beginPath();
50 | ctx.moveTo(xp0, yp0);
51 | ctx.lineTo(xp1, yp1);
52 | } else if( angle > Math.PI/2) {
53 | ctx.beginPath();
54 | ctx.arc(cx, cy, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, true);
55 | } else {
56 | ctx.beginPath();
57 | ctx.arc(cx, cy, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, false);
58 | }
59 |
60 | // console.log(angle*180/Math.PI);
61 |
62 | ctx.rect(cx, cy, 2, 2);
63 | ctx.rect(xp0, yp0, 2, 2);
64 | ctx.rect(xp1, yp1, 2, 2);
65 |
66 | // ctx.fill();
67 | ctx.stroke();
68 | }
69 | var Point = function (x,y){
70 | this.x=x;
71 | this.y=y;
72 | }
73 |
74 | window.addEventListener('resize', resizeCanvas, false);
75 | function resizeCanvas() {
76 | canvas.width = window.innerWidth;
77 | canvas.height = window.innerHeight;
78 | /**
79 | * Your drawings need to be inside this function otherwise they will be reset when
80 | * you resize the browser window and the canvas goes will be cleared.
81 | */
82 | animate();
83 | }
84 | // define global variables
85 | var mouseX, mouseY;
86 |
87 | window.requestAnimFrame = (function(callback) {
88 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
89 | function(callback) {
90 | window.setTimeout(callback, 1000 / 60);
91 | };
92 | })();
93 |
94 | xp0 = 300;
95 | yp0 = 100.5;
96 | xp1 = 600;
97 | yp1 = 100.5;
98 |
99 | var count = 0;
100 | var lastMouseX;
101 | var lastMouseY;
102 | function animate() {
103 | // update
104 |
105 | // clear
106 | ctx.clearRect(0, 0, canvas.width, canvas.height);
107 |
108 | // draw stuff
109 |
110 | // ctx.moveTo(10, 100.5);
111 | // ctx.lineTo(1000, 100.5);
112 | // ctx.stroke();
113 |
114 | var cx = circleCenter(xp0, yp0, mouseX, mouseY, xp1, yp1)[0];
115 | var cy = circleCenter(xp0, yp0, mouseX, mouseY, xp1, yp1)[1];
116 | var r = dist(cx, cy, xp0, yp0);
117 |
118 | if( r > 500 && mouseX > xp0 && mouseX < xp1 ){
119 |
120 | console.log(r);
121 | drawArc(mouseX, mouseY, ctx);
122 | lastMouseX = mouseX;
123 | lastMouseY = mouseY;
124 |
125 | count = 0;
126 | } else {
127 | drawArc(lastMouseX, yp0+(lastMouseY-yp0)*Math.cos(count/10*Math.PI)*Math.pow(0.98, count), ctx);
128 |
129 | count++;
130 | }
131 |
132 |
133 | // request new frame
134 | requestAnimFrame(function() {
135 | animate();
136 | });
137 | }
138 | animate();
139 | resizeCanvas();
140 |
141 | document.onclick = function(e)
142 | {
143 |
144 | xd = mouseX = e.clientX;
145 | yd = mouseY = e.clientY;
146 | }
147 |
148 | document.onmousemove = function(e)
149 | {
150 | xd = mouseX = e.clientX;
151 | yd = mouseY = e.clientY;
152 | }
--------------------------------------------------------------------------------
/js/underline.js:
--------------------------------------------------------------------------------
1 | var getElementStyles = function(element){
2 | // lineHeight, height, ratio, fontFamily, fontSize, fontStyle
3 | var $this = element;
4 |
5 | var baselinePositionRatio = baselineRatio(element);
6 | var lineHeight = parseFloat(window.getComputedStyle($this, null)
7 | .getPropertyValue("line-height"));
8 | var fontFamily = window.getComputedStyle($this, null)
9 | .getPropertyValue("font-family");
10 | var fontSize = window.getComputedStyle($this, null)
11 | .getPropertyValue("font-size");
12 | var fontStyle = window.getComputedStyle($this, null)
13 | .getPropertyValue("font-style");
14 | var width = $this.getBoundingClientRect().width;
15 | var height = $this.getBoundingClientRect().height;
16 | var parentWidth = $this.parentNode.getBoundingClientRect().width;
17 |
18 |
19 | var offsetLeft = $this.offsetLeft;
20 | var parentOffsetLeft = $this.parentNode.offsetLeft;
21 | var canvasLeft = parentOffsetLeft - offsetLeft;
22 | var textIndent = offsetLeft - parentOffsetLeft;
23 |
24 | // canvas.style.left= canvasLeft + 'px';
25 | return {
26 | lineHeight: lineHeight,
27 | width: width,
28 | height: height,
29 | parentWidth: parentWidth,
30 | fontFamily: fontFamily,
31 | fontSize: fontSize,
32 | fontStyle: fontStyle,
33 | baselinePositionRatio: baselinePositionRatio,
34 | canvasLeft: canvasLeft,
35 | textIndent: textIndent
36 | }
37 | };
38 |
39 | window.requestAnimFrame = (function(callback) {
40 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
41 | function(callback) {
42 | window.setTimeout(callback, 1000 / 60);
43 | };
44 | })();
45 |
46 | var myUnderlines = [];
47 | var myMultipleUnderlines = [];
48 | window.onload = function() {
49 | var underlineElements = document.querySelectorAll(".underline");
50 | for(var n = 0; n < underlineElements.length; n++) {
51 |
52 | var element = underlineElements[n];
53 |
54 | var underlineStyles = {
55 | 'text-underline-color': '#000',
56 | 'text-underline-position': 'auto', // could be ratio or todo: px
57 | 'text-underline-skip': true,
58 | 'text-underline-width': 'auto' // could be auto or px or ratio
59 | }
60 |
61 |
62 | var elementStyles = getElementStyles(element);
63 | // single line or multiple line?
64 | if (elementStyles.height > elementStyles.lineHeight) {
65 | // multiple lines
66 | // console.log('multiple lines');
67 | var myUnderline = new MultipleUnderline(element, underlineStyles, elementStyles);
68 | // myUnderline.update();
69 | // myUnderline.draw();
70 | myUnderlines.push(myUnderline);
71 | } else {
72 | // single line
73 | var myUnderline = new SingleUnderline(element, underlineStyles, elementStyles);
74 | myUnderlines.push(myUnderline);
75 | }
76 |
77 | // if(window.device)
78 | }
79 | }
80 |
81 |
82 | function animate() {
83 |
84 | for(var i = 0; i < myUnderlines.length; i++) {
85 | var myUnderline = myUnderlines[i];
86 |
87 | // clear
88 | myUnderline.clear();
89 |
90 | // update
91 | myUnderline.update();
92 |
93 | // draw stuff
94 | myUnderline.draw();
95 | }
96 |
97 |
98 | // request new frame
99 | requestAnimFrame(function() {
100 | animate();
101 | });
102 | }
103 | animate();
104 |
105 | //audio play multiple channels at the same time: http://www.storiesinflight.com/html5/audio.html
106 | var channel_max = 10; // number of channels
107 | audiochannels = new Array();
108 | for (a = 0; a < channel_max; a++) { // prepare the channels
109 | audiochannels[a] = new Array();
110 | audiochannels[a]['channel'] = new Audio(); // create a new audio object
111 | audiochannels[a]['finished'] = -1; // expected end time for this channel
112 | }
113 |
114 | function play_multi_sound(s) {
115 | for (a = 0; a < audiochannels.length; a++) {
116 | thistime = new Date();
117 | if (audiochannels[a]['finished'] < thistime.getTime()) { // is this channel finished?
118 | audiochannels[a]['finished'] = thistime.getTime() + document.getElementById(s).duration * 1000;
119 | audiochannels[a]['channel'].src = document.getElementById(s).src;
120 | audiochannels[a]['channel'].load();
121 | audiochannels[a]['channel'].play();
122 | break;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/js/single-underline.js:
--------------------------------------------------------------------------------
1 | var multiplyValue = function(value, multiplier){
2 | var str = value;
3 | var m = multiplier;
4 | var result = str.match(/(\d*\.?\d*)(.*)/);
5 | //http://stackoverflow.com/questions/2868947/split1px-into-1px-1-px-in-javascript
6 | return result[1] * m + result[2];
7 | }
8 |
9 | var optimalStrokeWidthPos = function(strokeWidth, posY){
10 | if ( strokeWidth < 1) {
11 | posY = Math.round(posY - 0.5) + 0.5;
12 | } else if ( strokeWidth >= 1 ) {
13 | strokeWidth = Math.round( strokeWidth );
14 | if ( strokeWidth % 2 ){
15 | // odd, posY -> 0.5
16 | posY = Math.round(posY - 0.5) + 0.5;
17 | } else {
18 | // even, posY -> 1
19 | posY = Math.round(posY);
20 | }
21 | }
22 | return {
23 | strokeWidth: strokeWidth,
24 | posY: posY
25 | }
26 | }
27 |
28 | function SingleUnderline(element, underlineStyles, elementStyles) {
29 | //ctor
30 | this.element = element;
31 |
32 | this.text = this.element.textContent;
33 |
34 | this.underlineStyles = underlineStyles;
35 |
36 | this.elementStyles = elementStyles;
37 | this.redrawActive = false;
38 |
39 | this.canvas = document.createElement("canvas");
40 | this.ctx = this.canvas.getContext('2d');
41 |
42 | this.ratio = window.devicePixelRatio;
43 | this.canvas.width = this.elementStyles.width*this.ratio;
44 | this.canvas.height = this.elementStyles.height*this.ratio;
45 | this.element.appendChild(this.canvas);
46 | this.canvas.style.width = this.elementStyles.width + 'px';
47 |
48 | this.ctx.font = this.font = this.elementStyles.fontStyle + ' '
49 | + multiplyValue(this.elementStyles.fontSize, this.ratio) + ' '
50 | + this.elementStyles.fontFamily;
51 |
52 | // determine the text-underline-width / strokeWidth
53 | var dotWidth = this.ctx.measureText('.')['width'];
54 | if (this.underlineStyles['text-underline-width'] == "auto") {
55 | // if set to auto, calculate the optimized width based on font
56 | this.strokeWidth = dotWidth/12;
57 | } else {
58 | //if set to px value, todo: other unit such as em?
59 | this.strokeWidth = this.underlineStyles['text-underline-width'];
60 | //get number value
61 | this.strokeWidth = parseFloat(this.strokeWidth)*this.ratio;
62 | }
63 |
64 |
65 | // determine the text-underline-position / underlinePosition
66 | // text-underline-position in ratio, todo: default and user set position ratio
67 | if (this.underlineStyles['text-underline-position'] == "auto") {
68 | // if set to auto, calculate the optimized width based on font
69 | // console.log(this.elementStyles.baselinePositionRatio);
70 | this.underlinePosition = parseFloat(this.elementStyles.height) * this.ratio
71 | * ( 1 - this.elementStyles.baselinePositionRatio +
72 | this.elementStyles.baselinePositionRatio * 0.4)
73 | + this.strokeWidth/2;
74 | } else {
75 | //if set to ratio value, todo: other unit such as em, px?
76 | var userUnderlinePosition = parseFloat(this.underlineStyles['text-underline-position']);
77 | // console.log(this.elementStyles.baselinePositionRatio);
78 | this.underlinePosition = parseFloat(this.elementStyles.height) * this.ratio *
79 | ( 1 - this.elementStyles.baselinePositionRatio +
80 | this.elementStyles.baselinePositionRatio * userUnderlinePosition)
81 | + this.strokeWidth/2;
82 | }
83 |
84 | var adjustValue = optimalStrokeWidthPos(this.strokeWidth, this.underlinePosition);
85 | this.strokeWidth = adjustValue.strokeWidth;
86 | this.underlinePosition = adjustValue.posY;
87 |
88 | // todo: if last character is a space, remove the space
89 | textWidth = this.ctx.measureText(this.text).width;
90 |
91 | this.myString = new GuitarString(this.ctx,
92 | new Point(0, this.underlinePosition),
93 | new Point(textWidth, this.underlinePosition),
94 | this.strokeWidth, this.underlineStyles['text-underline-color'], this.ratio);
95 | this.drawHoles();
96 |
97 | }
98 |
99 | SingleUnderline.prototype.drawUnderline = function(){
100 | // draw the underline
101 | this.myString.draw();
102 | }
103 |
104 | SingleUnderline.prototype.drawHoles = function(){
105 | // draw the font stroke
106 | this.ctx.font = this.font;
107 | this.ctx.textBaseline = 'top';
108 |
109 | this.ctx.globalCompositeOperation = "destination-out";
110 |
111 | this.ctx.lineWidth = 2*this.ratio + this.strokeWidth*3.6;
112 | this.ctx.strokeStyle = 'blue';
113 | this.ctx.beginPath();
114 | this.ctx.strokeText(this.text, -0.2, 0);
115 |
116 | this.ctx.fillStyle = 'green';
117 | this.ctx.beginPath();
118 | this.ctx.fillText(this.text, -0.2, 0);
119 | }
120 |
121 | SingleUnderline.prototype.clear = function(){
122 | this.redrawActive = this.myString.redrawActive;
123 | // clear
124 | if(this.myString.redrawActive) {
125 | // this.myString.clear();
126 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
127 | }
128 | };
129 |
130 |
131 | SingleUnderline.prototype.update = function(){
132 | // update
133 | if(this.myString.redrawActive) {
134 | this.myString.update();
135 | }
136 | };
137 |
138 |
139 | SingleUnderline.prototype.draw = function(){
140 | // draw
141 | if(this.redrawActive) {
142 | this.drawUnderline();
143 | this.drawHoles();
144 | }
145 | };
146 |
147 |
148 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # underline.js
2 |
3 | `A javascript library that sets out to do one simple job: draw and animate the most perfect and playful text underline`
4 |
5 |
6 | ### Demo
7 |
8 | [http://wentin.github.io/underlineJS/](http://wentin.github.io/underlineJS/)
9 |
10 | The project is currently under development.
11 |
12 | If you have 8 minutes and want to know what is the story behind creating underline.js, you can hear all about it in this [`NY Tech Meetup presentation video`](http://embed.wirewax.com/8013554/7bafa8/)
13 |
14 | ### Features
15 |
16 | Underline.js has following features:
17 | 1. It doesn't have ghost pixels. It is not just pixel perfect, but also pixel perfect on half pixel level for retina display
18 | 
19 | 2. It has an optimized thin stroke-width. It is always 1/6 of width of the period mark.
20 | 
21 | 3. It sits on the optimal Y position between the baseline and descender line, that optimal Y positon is the golden ratio point.
22 | 
23 | 4. It has holes around descenders. Completely respect the type's shape. If you ask, the size of the holes are also optimized to the perfection.
24 | 
25 |
26 | ### CSS4 Proposal to W3C
27 |
28 | Underline.js is not designed to be the most useful javascript library. It is more exploratory, and it is trying to push the boundary of web typography. I want to propose these new css rules to W3C for css4 edition:
29 |
30 | text-underline-color: #000000;
31 | // auto means the same color as the text color, or hex value
32 |
33 | text-underline-position: auto;
34 | // could be ratio or px or auto
35 |
36 | text-underline-skip: true;
37 | // true to set holes around descenders, false to turn it off
38 |
39 | text-underline-width: auto;
40 | // could be auto or px or ratio
41 |
42 | text-underline-animation: true
43 | // true or false, this one is only for underline.js
44 |
45 | ### Reference
46 |
47 | [Marcin Wichary's article on crafting Medium.com's underline](https://medium.com/designing-medium/crafting-link-underlines-on-medium-7c03a9274f9)
48 |
49 | ### Mentions (thank you!)
50 |
51 | [`Tweets`](https://storify.com/DesignJokes/underline-js-tweets)
52 |
53 | [`technical.ly article`](https://technical.ly/brooklyn/2015/02/12/wenting-zhang-underline-js/)
54 |
55 | [`codrops collective`](http://tympanus.net/codrops/collective/collective-155/)
56 | [`unheap.com`](http://www.unheap.com/user-interface/text-links/underline-js/)
57 | [`coliss.com`](http://coliss.com/articles/build-websites/operation/javascript/js-draw-and-animate-underline.html)
58 | [`speckyboy.com`](http://speckyboy.com/2015/02/24/weekly-news-for-designers-n-273/)
59 | [`cssauthor.com`](http://www.cssauthor.com/weekly-web-development-resources-and-tools-95/)
60 | [`beautifulopen.com`](http://beautifulopen.com/2015/01/06/underline-js/)
61 | [`freebiesbug.com`](http://freebiesbug.com/code-stuff/underline-js-animate-text-underline/)
62 | [`jquery-plugins.net`](http://jquery-plugins.net/underlinejs-javascript-library-to-draw-and-animate-text-underline)
63 | *Note: underline.js doesn't have dependency on jquery*
64 | [`designsrazzi.com`](http://www.designsrazzi.com/free-jquery-plugins/)
65 | [`codegeekz.com`](http://codegeekz.com/15-handy-javascript-libraries-for-march-2015/)
66 | [`bashooka.com`](http://bashooka.com/coding/javascript-libraries-for-web-typography/)
67 | [`ninodezign.com`](http://ninodezign.com/10-funny-jquery-plugins-for-your-website/)
68 | [`hongkiat.com`](http://www.hongkiat.com/blog/web-typography-tools/)
69 | [`decodering.com`](http://decodering.com/post/110635667154/underline-js-a-javascript-library-that-sets-out)
70 | [`ipixel.com.sg`](http://www.ipixel.com.sg/blog/freebies/underline-js-animate-text-underline/)
71 | [`freede.ru`](http://freede.ru/koding/animatsionnoe-podchyorkivanie-tekst-so-zvukom-pri-navedenii.html)
72 | [`gaetanpautler.com`](http://gaetanpautler.com/weekly-links-and-websites-89/)
73 | [`designmeltdown.com`](http://designmeltdown.com/#s=9406)
74 | [`html5cn.org`](http://www.html5cn.org/article-7851-1.html)
75 | [`splashnology.com`](http://mag.splashnology.com/article/tools-web-dev-march-2015/14012/)
76 | [`developersfeed.com`](http://www.developersfeed.com/25-best-web-development-tools-of-march-2015/)
77 | [`Parsons Alumni news`](http://amt.parsons.edu/blog/mfa-dt-alum-wenting-zhang-presents-underline-js-project-to-ny-tech-meetup/)
78 | [`bashooka.com`](http://bashooka.com/coding/javascript-libraries-for-web-typography/)
79 | [`habrahabr.ru`](http://habrahabr.ru/post/251759/)
80 | [`softpedia.com`](http://webscripts.softpedia.com/script/Text-Management/Text-Tools/underline-js-84277.html)
81 | [`lafermeduweb.net`](http://www.lafermeduweb.net/veille/underline-js-soulignez-a-la-perfection-vos-textes-sans-couper-les-lettres-565407442654482432.html)
82 | [`wykop.pl`](http://www.wykop.pl/wpis/11426174/https-github-com-wentin-underlinejs-fajna-bibliote/)
83 | [`sumy.ua`](http://veselov.sumy.ua/1753-underlinejs-skript-dobavleniya-pravilnogo-podcherkivaniya.html)
84 | [`us8`](http://us8.campaign-archive2.com/?u=9dc44712ae7c52996ea6e645b&id=f8356f478a&e=1d8514e3e4)
85 | [`pr-cy.ru`](http://pr-cy.ru/news/p/4967)
86 | [`takana8.tumblr.com`](http://takana8.tumblr.com/post/110873944747/underline-js-a-javascript-library-that-sets-out)
87 | [`altervista.org`](http://iwinuxfeed.altervista.org/aggregatore/underline-js/?utm_source=dlvr.it&utm_medium=twitter)
88 |
89 | ###Contact
90 | * Follow [@DesignJokes](http://twitter.com/DesignJokes) on Twitter
91 | * Email
92 | * Visit [wentin.co](http://wentin.co)
93 |
--------------------------------------------------------------------------------
/css/mobile.scss:
--------------------------------------------------------------------------------
1 | /* Smartphones (portrait and landscape) ----------- */
2 |
3 | @media screen
4 | and (min-width : 320px)
5 | and (max-width: 800px) {
6 | body {
7 | font-size: 20px;
8 | line-height: 28px;
9 | header {
10 | width: 100%;
11 | height: 90px;
12 | border-top: solid 3px $green;
13 | border-bottom: none;
14 | position: relative;
15 | z-index: 1;
16 | .logo {
17 | width: 60px;
18 | left: 20px;
19 | top: 6px;
20 | #underline {
21 | opacity: 0;
22 | }
23 | #js {
24 | -webkit-transform: translate(-218.7px, 0);
25 | transform: translate(-218.7px, 0);
26 | fill: $green;
27 | }
28 | #line {
29 | -webkit-transform: translate(-218.7px, 0);
30 | transform: translate(-218.7px, 0);
31 | fill: $green;
32 | }
33 | &:hover {
34 | #js, #line {
35 | fill: $darkGreen;
36 | }
37 | }
38 | }
39 | .hamburger {
40 | display: none;
41 | }
42 | .menu {
43 | display: block;
44 | right: 20px;
45 | a {
46 | width: 0px;
47 | overflow: hidden;
48 | padding-left: 32px;
49 | &::before {
50 | font-size: 32px;
51 | }
52 | }
53 | }
54 | &.mobile-menu-open {
55 | height: 100%;
56 | height: 100%;
57 | position: fixed;
58 | top: 0px;
59 | left: 0px;
60 | right: 0px;
61 | bottom: 0px;
62 | .logo {
63 | }
64 | .hamburger {
65 | i {
66 | width: 0px;
67 | &::before {
68 | top: 0;
69 | -webkit-transform: rotate(45deg);
70 | transform: rotate(45deg);
71 | }
72 | &::after {
73 | top: 0;
74 | -webkit-transform: rotate(-45deg);
75 | transform: rotate(-45deg);
76 | }
77 | }
78 | }
79 | .menu {
80 | display: block;
81 | opacity: 1;
82 | position: absolute;
83 | width: 100%;
84 | height: 100%;
85 | box-sizing: border-box;
86 | left: 0px;
87 | top: 0px;
88 | padding-top: 28vh;
89 | background-color: rgba(255,255,255,0.5);
90 | z-index: 1;
91 | a {
92 | font-size: 28px;
93 | line-height: 100px;
94 | position: relative;
95 | display: block;
96 | margin-left: 0px;
97 | padding-left: 70px;
98 | transition: background-color 0.4s;
99 | &::before {
100 | position: absolute;
101 | left: 20px;
102 | width: 30px;
103 | text-align: center;
104 | font-size: 30px;
105 | line-height: 100px;
106 | transition: none;
107 | }
108 | }
109 | .icon-edit {
110 | display: block;
111 | }
112 | .icon-question {
113 | display: none;
114 | }
115 | a:hover,
116 | a:active {
117 | background-color: $green;
118 | color: white;
119 | &::before {
120 | color: white;
121 | }
122 | }
123 | .icon-github::before {
124 | top: -2px;
125 | }
126 | .icon-edit::before {
127 | top: -2px;
128 | }
129 | }
130 | }
131 | }
132 | header.mobile-menu-open ~ article {
133 | margin-top: 93px;
134 | }
135 |
136 | .trigger {
137 | opacity: 0;
138 | -webkit-transition-delay: 0s;
139 | transition-delay: 0s;
140 | -webkit-transform: translateY(-100%) scale(0.9);
141 | transform: translateY(-100%) scale(0.9);
142 | z-index: -1;
143 | }
144 | article {
145 | padding: 0 20px;
146 | width: 100%;
147 | box-sizing: border-box;
148 | }
149 | footer {
150 | height: 240px;
151 | width: 100%;
152 | .share {
153 | width: 160px;
154 | top: 120px;
155 | &::before {
156 | font-size: 24px;
157 | line-height: 62px;
158 | left: 49px;
159 | top: -30px;
160 | width: 60px;
161 | height: 60px;
162 | }
163 | }
164 | }
165 | /********** Title ***********/
166 | h1 {
167 | font-size: 28px;
168 | line-height: 36px;
169 | height: auto;
170 | text-align: left;
171 | position: relative;
172 | padding: 24px 0;
173 | margin-bottom: 0px;
174 | border-bottom: solid 1px rgba($dark, 0.4);
175 | &::after {
176 | display: none;
177 | }
178 | }
179 | /********** Heading 1 ***********/
180 | h2 {
181 | font-size: 24px;
182 | line-height: 36px;
183 | font-weight: 500;
184 | padding-top: 40px;
185 | }
186 | h1 + * {
187 | padding-top: 24px !important;
188 | margin-top: 0px;
189 | }
190 | /********** Heading 2 ***********/
191 | p.heading2 {
192 | padding: 12px 0;
193 | strong{
194 | font-weight: 700;
195 | font-size: 20px;
196 | line-height: 28px;
197 | letter-spacing: 0px;
198 | }
199 | }
200 |
201 | p {
202 | font-size: 20px;
203 | line-height: 28px;
204 | }
205 |
206 | p.text a {
207 | font-size: 32px;
208 | line-height: 1.4em;
209 | }
210 | p a.title {
211 | font-size: 48px;
212 | line-height: 1.4em;
213 | }
214 | p strong {
215 | font-family: $ebgamramondsc;
216 | text-shadow: 0 0 1px rgba(0, 0, 0, 0.2);
217 | }
218 |
219 |
220 | }}
--------------------------------------------------------------------------------
/stringAnimation/js/main-old.js:
--------------------------------------------------------------------------------
1 | /*Created By Wenting Zhang
2 | About Javascript Random Seed function study
3 | Javascript Math.random() don't have random seed functionality
4 | using http://davidbau.com/encode/seedrandom-min.js makes Math.random() seedable
5 |
6 | javascript color blend mode globalCompositeOperation
7 | */
8 | var canvas = document.getElementById('myCanvas');
9 | var ctx = canvas.getContext('2d');
10 |
11 | var dist = function(x, y, x0, y0){
12 | return Math.sqrt((x -= x0) * x + (y -= y0) * y);
13 | };
14 |
15 | window.addEventListener('resize', resizeCanvas, false);
16 | function resizeCanvas() {
17 | canvas.width = window.innerWidth;
18 | canvas.height = window.innerHeight;
19 | /**
20 | * Your drawings need to be inside this function otherwise they will be reset when
21 | * you resize the browser window and the canvas goes will be cleared.
22 | */
23 | animate();
24 | }
25 | // define global variables
26 | var mouseX, mouseY;
27 | // current position and original position
28 | var xp0, yp0, ypt0;
29 | var xp1, yp1, ypt1;
30 | // store distance
31 | var dx, dy;
32 | // array of current start/end points
33 | // PVector pt0, pt1;
34 | // store original position
35 | // PVector pto0, pto1;
36 |
37 | // my permanent midpoint
38 | var xMid, yMid;
39 | // the position of my swinging pendulum povar (midpoint)
40 | var xc, yc;
41 | // my grabbed povar by user
42 | var xg, yg, xgi, ygi;
43 | var xg1, yg1, xg0, yg0;
44 | // drawing point
45 | var xd, yd;
46 | // ratio for curvature. Make this around 0.5 or higher
47 | var rBezier = 0.2;
48 | // distance we can pull perpendicularly from middle pt of string (as ratio length)
49 | // (amplitude of wave)
50 | var rDistMax = 0.15;
51 | // minimum distance to force string to move, when you brush it
52 | var rDistMin = 0.01;
53 | // max amplitude of wave when oscillating (as ratio of length)
54 | var rAmpMax = 0.072;
55 | // minimum distance to move (px), amplitude, so if you brush it it always shows movement
56 | var ampPxMin = 5;
57 | // maximum pixel distance to move, amplitude
58 | var ampPxMax = 33;
59 | // pan range (-1 to 1) - range is -1 to 1, but make it slight because
60 | // it will shift already playing sounds
61 | var pan0 = -0.4; var pan1 = 0.4;
62 | // frequency of oscillation - this is the increment per frame for t value.
63 | // higher gives higher frequency
64 | var freq0 = 0.5; // frequency for long strings
65 | var freq1 = 2.5; // frequency for short strings
66 | var freq;
67 |
68 | // amplitude dampening - how quickly it dampens to nothing - ratio 0 to 1
69 | var ampDamp0 = 0.95;
70 | var ampDamp1 = 0.87;
71 | var ampDamp;
72 | // length where we cap it highest/lowest pitch (px)
73 | // our longest thread is 658, shortest is 19
74 | var len0 = 30; var len1 = 480;
75 | // temporary distance variables
76 | var distMax; var distPerp;
77 | // how close do we have to be to instantly grab a thread - perpendicular distance (px)
78 | var distInstantPerp = 6;
79 |
80 | // stores ratio from 0 to 1 where user has grabbed along the string
81 | var rGrab, rHalf;
82 | // my main angle
83 | var ang; var angOrig;
84 | // my perpendicular angle
85 | var angPerp;
86 | // total length of this thread (when unstretched)
87 | var len; var lenOrig;
88 | // how much are we stretched, as a ratio from 0 (straight line) to 1 (max elastic)
89 | var rStretch = 0;
90 | // easing resize ratio
91 | var resizeEase = 0.08;
92 |
93 |
94 | // temporary variables
95 | var dx0, dy0, dx1, dy1, dist0, dist1;
96 | var dxBez0, dyBez0, dxBez1, dyBez1;
97 |
98 | // my index number within the route sequence
99 | var ind;
100 | // stroke
101 | var str0 = 1; var str1 = 4; var str;
102 | // hex value
103 | var hex;
104 |
105 | // frame counter
106 | var ctGrab = 0;
107 | // oscillation increment
108 | var t = 0;
109 | // current amplitude
110 | var amp, ampMax;
111 | // current stretch strength as ratio
112 | var rStrength;
113 |
114 | // my pitch index (0, 1, 2...) - and as ratio
115 | var pitchInd; var rPitch;
116 | // reference to my audio sample
117 | // AudioSample au;
118 | // lowest and highest volume for notes triggered by user
119 | var vol0 = 0.3; var vol1 = 0.6;
120 | // gain range triggered by user (db change)
121 | var gain0 = -10; var gain1 = -1;
122 | // is update on
123 | var isUpdOn = false;
124 | // oscillation direction (-1 or 1)
125 | var oscDir;
126 |
127 | // currently grabbed
128 | var isGrabbed = false;
129 | // currently oscillating
130 | var isOsc = false;
131 | // was just dropped
132 | var isFirstOsc = false;
133 | // not drawn yet
134 | var isVisible = false;
135 | //
136 | var isFirstRun = true;
137 | // is resizing
138 | var isResizing = false;
139 |
140 |
141 |
142 | window.requestAnimFrame = (function(callback) {
143 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
144 | function(callback) {
145 | window.setTimeout(callback, 1000 / 60);
146 | };
147 | })();
148 |
149 | xp0 = 10;
150 | yp0 = 300.5;
151 | xp1 = 500;
152 | yp1 = 300.5;
153 |
154 | dx = xp1-xp0;
155 | dy = yp1-yp0;
156 | // store angle
157 | ang = Math.atan2(dy, dx);
158 |
159 | function animate() {
160 | // update
161 |
162 | // clear
163 | ctx.clearRect(0, 0, canvas.width, canvas.height);
164 |
165 | // draw stuff
166 |
167 | // ctx.moveTo(10, 100.5);
168 | // ctx.lineTo(1000, 100.5);
169 | // ctx.stroke();
170 |
171 |
172 | // if (isGrabbed || isFirstOsc) {
173 | // xd = xg; yd = yg;
174 | // // oscillating freely mode
175 | // } else {
176 | // xd = xc; yd = yc;
177 | // }
178 | dx0 = xd-xp0; dy0 = yd-yp0;
179 | dx1 = xp1-xd; dy1 = yp1-yd;
180 | // distance
181 | dist0 = dist(xp0, yp0, xd, yd);
182 | dist1 = dist(xd, yd, xp1, yp1);
183 | // move to the center pendulum point
184 | dxBez0 = rBezier*dist0*Math.cos(ang);
185 | dyBez0 = rBezier*dist0*Math.sin(ang);
186 | // move to the center pendulum point
187 | dxBez1 = rBezier*dist1*Math.cos(ang);
188 | dyBez1 = rBezier*dist1*Math.sin(ang);
189 | // draw bezier - point, control, control, point
190 |
191 | ctx.beginPath();
192 | ctx.moveTo(xp0, yp0);
193 | ctx.bezierCurveTo(xd-dxBez0, yd-dyBez0, xd-dxBez0, yd-dyBez0, xd, yd);
194 | ctx.bezierCurveTo(xd+dxBez1, yd+dyBez1, xd+dxBez1, yd+dyBez1, xp1, yp1);
195 | // bezier(xp0, yp0, xd-dxBez0, yd-dyBez0, xd-dxBez0, yd-dyBez0, xd, yd);
196 | // bezier(xd, yd, xd+dxBez1, yd+dyBez1, xd+dxBez1, yd+dyBez1, xp1, yp1);
197 | ctx.stroke();
198 |
199 | ctx.fillStyle = "red";
200 | ctx.rect(xp0, yp0, 2, 2);
201 | ctx.rect(xd, yd, 2, 2);
202 | ctx.rect(xd-dxBez0, yd-dyBez0, 2, 2);
203 | ctx.rect(xd+dxBez1, yd+dyBez1, 2, 2);
204 | ctx.rect(xp1, yp1, 2, 2);
205 | ctx.fill();
206 |
207 | // request new frame
208 | requestAnimFrame(function() {
209 | animate();
210 | });
211 | }
212 | animate();
213 | resizeCanvas();
214 |
215 | document.onclick = function(e)
216 | {
217 |
218 | xd = mouseX = e.clientX;
219 | yd = mouseY = e.clientY;
220 | }
221 |
222 | document.onmousemove = function(e)
223 | {
224 | xd = mouseX = e.clientX;
225 | yd = mouseY = e.clientY;
226 | }
--------------------------------------------------------------------------------
/stringAnimation/js/class.js:
--------------------------------------------------------------------------------
1 | function String(id, startPoint, endPoint, strokeWidth, strokeColor) {
2 | //ctor
3 | this.canvas = document.getElementById(id);
4 | this.ctx = this.canvas.getContext('2d');
5 |
6 | // console.dir(this.canvas);
7 | this.canvas.width = this.canvas.clientWidth;
8 | this.canvas.height = this.canvas.clientHeight;
9 |
10 | this.startPoint = startPoint;
11 | this.endPoint = endPoint;
12 | this.strokeWidth = strokeWidth;
13 | this.strokeColor = strokeColor;
14 | this.controlPoint = new Point(0,0);
15 | this.thirdPoint = new Point(0,0);
16 |
17 | this.ctx.lineWidth = this.strokeWidth;
18 | this.ctx.strokeStyle = this.strokeColor;
19 |
20 |
21 | this.waveInitX = (this.startPoint.x + this.endPoint.x)/2;
22 | this.waveInitY = this.startPoint.y;
23 |
24 | this.lastMouseX = this.controlPoint.x;
25 | this.lastMouseY = this.controlPoint.y;
26 | this.waveCount = 0;
27 | this.damping = 0.98;
28 |
29 | this.userInControl = false;
30 | this.userPlucked = false;
31 | this.waveInControl = false;
32 | this.waveFinished = false;
33 |
34 | //add event listener
35 | var self = this;
36 | this.canvas.addEventListener('mousemove', function(pos) {
37 | // console.dir(pos);
38 | self.mouseMove(self, pos)
39 | }, false);
40 | }
41 |
42 | String.prototype.drawArc = function(startPoint, thirdPoint, endPoint, ctx){
43 | var ctx = ctx;
44 |
45 | var dy1 = thirdPoint.y - startPoint.y;
46 | var dx1 = thirdPoint.x - startPoint.x;
47 | var dy2 = endPoint.y - thirdPoint.y;
48 | var dx2 = endPoint.x - thirdPoint.x;
49 |
50 | var aSlope = dy1/dx1;
51 | var bSlope = dy2/dx2;
52 |
53 |
54 | var centerX = (aSlope*bSlope*(startPoint.y - endPoint.y) + bSlope*(startPoint.x + thirdPoint.x)
55 | - aSlope*(thirdPoint.x+endPoint.x) )/( 2* (bSlope-aSlope) );
56 | var centerY = -1*(centerX - (startPoint.x+thirdPoint.x)/2)/aSlope + (startPoint.y+thirdPoint.y)/2;
57 |
58 | // var centerX = (aSlope*bSlope*(y0 - y2) + bSlope*(x0 + x1)
59 | // - aSlope*(x1+x2) )/( 2* (bSlope-aSlope) );
60 | // var centerY = -1*(centerX - (x0+x1)/2)/aSlope + (y0+y1)/2;
61 | var r = dist(centerX, centerY, startPoint.x, startPoint.y)
62 |
63 | var angle = Math.atan2(centerX-startPoint.x, centerY-startPoint.y);
64 |
65 | if (!angle){
66 | // console.log(angle);
67 | ctx.beginPath();
68 | ctx.moveTo(startPoint.x, startPoint.y);
69 | ctx.lineTo(endPoint.x, endPoint.y);
70 | } else {
71 | if( angle > Math.PI/2) {
72 | ctx.beginPath();
73 | ctx.arc(centerX, centerY, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, true);
74 | } else {
75 | ctx.beginPath();
76 | ctx.arc(centerX, centerY, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, false);
77 | }
78 | }
79 | // ctx.rect(centerX, centerY, 2, 2);
80 | // ctx.rect(startPoint.x, startPoint.y, 2, 2);
81 | // ctx.rect(endPoint.x, endPoint.y, 2, 2);
82 | ctx.stroke();
83 |
84 | }
85 | String.prototype.draw = function(){
86 |
87 | // draw stuff
88 | var initState = (!this.userInControl) && (!this.waveInControl) && (!this.waveFinished)
89 | if ( this.waveFinished || initState){
90 | // console.log('line');
91 | this.ctx.beginPath();
92 | this.ctx.moveTo(this.startPoint.x, this.startPoint.y);
93 | this.ctx.lineTo(this.endPoint.x, this.endPoint.y);
94 | this.ctx.stroke();
95 | } else {
96 | this.drawArc(this.startPoint, this.thirdPoint, this.endPoint, this.ctx);
97 | }
98 | };
99 |
100 | String.prototype.clear = function(){
101 | // clear
102 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
103 | };
104 |
105 |
106 | String.prototype.update = function(){
107 | // update
108 | var radius = circleCenter( new Point(this.startPoint.x, this.startPoint.y),
109 | new Point(this.controlPoint.x, this.controlPoint.y),
110 | new Point(this.endPoint.x, this.endPoint.y) ).r;
111 |
112 | var lastRadius = circleCenter( new Point(this.startPoint.x, this.startPoint.y),
113 | new Point(this.lastMouseX, this.lastMouseY),
114 | new Point(this.endPoint.x, this.endPoint.y) ).r;
115 | // console.log(r);
116 |
117 |
118 | var mouseInGrabRange = radius > 9000
119 | && this.controlPoint.x > this.startPoint.x
120 | && this.controlPoint.x < this.endPoint.x;
121 |
122 | var lastMouseOutGrabRange = !(lastRadius > 9000
123 | && this.lastMouseX > this.startPoint.x
124 | && this.lastMouseY < this.endPoint.x);
125 |
126 | var mouseOutControlRange = !(radius > 900
127 | && this.controlPoint.x > this.startPoint.x
128 | && this.controlPoint.x < this.endPoint.x);
129 |
130 | var lastMouseInControlRange = lastRadius > 900
131 | && this.lastMouseX > this.startPoint.x
132 | && this.lastMouseY < this.endPoint.x;
133 |
134 | /*if( !this.userPlucked ){
135 | this.userPlucked = intersects(this.lastMouseX, this.lastMouseY,
136 | this.controlPoint.x, this.controlPoint.y,
137 | this.startPoint.x, this.startPoint.y,
138 | this.endPoint.x, this.endPoint.y);
139 | if (this.userPlucked) {
140 | this.userInControl = false;
141 | this.waveInControl = true;
142 | this.waveInitX = (this.startPoint.x + this.endPoint.y)/2;
143 | this.waveInitY = this.endPoint.y + 15;
144 | }
145 | }*/
146 |
147 |
148 | if( mouseInGrabRange && lastMouseOutGrabRange ){
149 | this.waveCount = 0;
150 | this.waveFinished = false;
151 | this.userInControl = true;
152 | this.waveInControl = false;
153 |
154 | } else if ( mouseOutControlRange && lastMouseInControlRange){
155 |
156 | this.userInControl = false;
157 | this.waveInControl = true;
158 | this.waveInitX = this.lastMouseX;
159 | this.waveInitY = this.lastMouseY;
160 | // this.drawArc(this.startPoint, wavePoint, this.endPoint, this.ctx);
161 | }
162 |
163 |
164 |
165 | if ( this.userInControl ){
166 | // this.drawArc(this.startPoint, this.controlPoint, this.endPoint, this.ctx);
167 | this.thirdPoint = new Point(this.controlPoint.x, this.controlPoint.y);
168 | } else if ( this.waveInControl && !this.waveFinished ){
169 | // console.log(this.lastMouseY);
170 | // console.log(this.waveInitY);
171 | var waveX = this.waveInitX;
172 | var waveY = this.startPoint.y +
173 | (this.waveInitY-this.startPoint.y)
174 | *Math.cos(this.waveCount/5*Math.PI)
175 | *Math.pow(this.damping, this.waveCount);
176 |
177 | if ( Math.pow(this.damping, this.waveCount) < 0.01) {
178 | // wave damped to a straight line, wave is finished
179 | // console.log('damp to line');
180 | this.waveInControl = false;
181 | this.waveFinished = true;
182 | // this.userPlucked = false;
183 | } else {
184 | // still waving ....
185 | this.thirdPoint = new Point(waveX, waveY);
186 | this.waveCount++;
187 | }
188 | }
189 |
190 | this.lastMouseX = this.controlPoint.x;
191 | this.lastMouseY = this.controlPoint.y;
192 |
193 | };
194 |
195 | String.prototype.resize = function(){
196 | // resize canvas
197 | this.canvas.width = this.canvas.clientWidth;
198 | this.canvas.height = this.canvas.clientHeight;
199 | };
200 |
201 | String.prototype.mouseMove = function(self, pos){
202 | self.controlPoint.x = pos.layerX;
203 | self.controlPoint.y = pos.layerY;
204 | };
--------------------------------------------------------------------------------
/css/mobile.css:
--------------------------------------------------------------------------------
1 | /*
2 | Error: Undefined variable: "$green".
3 | on line 12 of ./mobile.scss
4 |
5 | 7: font-size: 20px;
6 | 8: line-height: 28px;
7 | 9: header {
8 | 10: width: 100%;
9 | 11: height: 90px;
10 | 12: border-top: solid 3px $green;
11 | 13: border-bottom: none;
12 | 14: position: relative;
13 | 15: z-index: 1;
14 | 16: .logo {
15 | 17: width: 60px;
16 |
17 | Backtrace:
18 | ./mobile.scss:12
19 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/script/tree/variable.rb:49:in `_perform'
20 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/script/tree/node.rb:50:in `perform'
21 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/script/tree/list_literal.rb:62:in `block in _perform'
22 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/script/tree/list_literal.rb:62:in `map'
23 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/script/tree/list_literal.rb:62:in `_perform'
24 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/script/tree/node.rb:50:in `perform'
25 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:384:in `visit_prop'
26 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:36:in `visit'
27 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
28 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `block in with_base'
29 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:115:in `with_frame'
30 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `with_base'
31 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `visit'
32 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:420:in `block (2 levels) in visit_rule'
33 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:420:in `map'
34 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:420:in `block in visit_rule'
35 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
36 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:418:in `visit_rule'
37 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:36:in `visit'
38 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
39 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `block in with_base'
40 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:115:in `with_frame'
41 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `with_base'
42 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `visit'
43 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:420:in `block (2 levels) in visit_rule'
44 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:420:in `map'
45 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:420:in `block in visit_rule'
46 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
47 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:418:in `visit_rule'
48 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:36:in `visit'
49 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
50 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `block in with_base'
51 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:115:in `with_frame'
52 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `with_base'
53 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `visit'
54 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:52:in `block in visit_children'
55 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:52:in `map'
56 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:52:in `visit_children'
57 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:167:in `block in visit_children'
58 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
59 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:166:in `visit_children'
60 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:36:in `block in visit'
61 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:502:in `visit_media'
62 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:36:in `visit'
63 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `block in visit'
64 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `block in with_base'
65 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:115:in `with_frame'
66 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/stack.rb:79:in `with_base'
67 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:158:in `visit'
68 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:52:in `block in visit_children'
69 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:52:in `map'
70 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:52:in `visit_children'
71 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:167:in `block in visit_children'
72 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:179:in `with_environment'
73 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:166:in `visit_children'
74 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:36:in `block in visit'
75 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:186:in `visit_root'
76 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/base.rb:36:in `visit'
77 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:157:in `visit'
78 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/visitors/perform.rb:8:in `visit'
79 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/root_node.rb:36:in `css_tree'
80 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/tree/root_node.rb:29:in `render_with_sourcemap'
81 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/engine.rb:368:in `_render_with_sourcemap'
82 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/engine.rb:285:in `render_with_sourcemap'
83 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/plugin/compiler.rb:489:in `update_stylesheet'
84 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/plugin/compiler.rb:215:in `block in update_stylesheets'
85 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/plugin/compiler.rb:209:in `each'
86 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/plugin/compiler.rb:209:in `update_stylesheets'
87 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/plugin/compiler.rb:469:in `on_file_changed'
88 | /Library/Ruby/Gems/2.0.0/gems/sass-3.4.6/lib/sass/plugin/compiler.rb:328:in `block in watch'
89 | /Library/Ruby/Gems/2.0.0/gems/listen-1.3.1/lib/listen/listener.rb:252:in `call'
90 | /Library/Ruby/Gems/2.0.0/gems/listen-1.3.1/lib/listen/listener.rb:252:in `on_change'
91 | /Library/Ruby/Gems/2.0.0/gems/listen-1.3.1/lib/listen/listener.rb:290:in `block in initialize_adapter'
92 | /Library/Ruby/Gems/2.0.0/gems/listen-1.3.1/lib/listen/adapter.rb:252:in `call'
93 | /Library/Ruby/Gems/2.0.0/gems/listen-1.3.1/lib/listen/adapter.rb:252:in `report_changes'
94 | /Library/Ruby/Gems/2.0.0/gems/listen-1.3.1/lib/listen/adapter.rb:321:in `poll_changed_directories'
95 | /Library/Ruby/Gems/2.0.0/gems/listen-1.3.1/lib/listen/adapter.rb:297:in `block in start_poller'
96 | */
97 | body:before {
98 | white-space: pre;
99 | font-family: monospace;
100 | content: "Error: Undefined variable: \"$green\".\A on line 12 of ./mobile.scss\A \A 7: font-size: 20px;\A 8: line-height: 28px;\A 9: header {\A 10: width: 100%;\A 11: height: 90px;\A 12: border-top: solid 3px $green;\A 13: border-bottom: none;\A 14: position: relative;\A 15: z-index: 1;\A 16: .logo {\A 17: width: 60px;"; }
101 |
--------------------------------------------------------------------------------
/i/logo-long.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/js/multiple.js:
--------------------------------------------------------------------------------
1 |
2 | function MultipleUnderline(element, underlineStyles, elementStyles) {
3 | //ctor
4 | this.element = element;
5 |
6 | this.text = this.element.textContent;
7 |
8 | this.underlineStyles = underlineStyles;
9 |
10 | // this.elementStyles = getElementStyles(element);
11 | this.elementStyles = elementStyles;
12 |
13 | this.canvas = document.createElement("canvas");
14 | this.canvas.width = this.elementStyles.width;
15 | this.canvas.height = this.elementStyles.height;
16 | this.canvas.style.left = this.elementStyles.canvasLeft + 'px';
17 | this.element.appendChild(this.canvas);
18 | this.canvas.width = this.canvas.clientWidth;
19 | this.canvas.height = this.canvas.clientHeight + this.elementStyles.lineHeight;
20 |
21 | this.ctx = this.canvas.getContext('2d');
22 | this.ctx.font = this.font = this.elementStyles.fontStyle + ' ' + this.elementStyles.fontSize + ' ' + this.elementStyles.fontFamily;
23 |
24 | this.multipleRedrawActive = false;
25 | if (is_chrome) {
26 | // chrome floor the lineheight when it is not a whole number
27 | this.elementStyles.lineHeight = Math.floor(this.elementStyles.lineHeight);
28 | }
29 |
30 |
31 | // determine the text-underline-width / strokeWidth
32 | this.dotWidth = this.ctx.measureText('.')['width'];
33 | if (this.underlineStyles['text-underline-width'] == "auto") {
34 | // if set to auto, calculate the optimized width based on font
35 | if (this.dotWidth / 6 <= 2) {
36 | this.strokeWidth = Math.round(this.dotWidth / 3) / 2;
37 | } else {
38 | this.strokeWidth = Math.round(this.dotWidth / 6);
39 | }
40 | } else {
41 | //if set to px value
42 | this.strokeWidth = this.underlineStyles['text-underline-width'];
43 | //get number value
44 | this.strokeWidth = parseFloat(this.strokeWidth);
45 | }
46 |
47 | // determine the text-underline-position / underlinePosition
48 | // text-underline-position in ratio
49 | this.underlinePosition = parseFloat(this.elementStyles.fontSize) * 0.89;
50 | if (this.strokeWidth <= 1 || (this.strokeWidth % 2 && this.strokeWidth > 2)) {
51 | this.underlinePosition = Math.round(this.underlinePosition - 0.5) + 0.5;
52 | } else {
53 | this.underlinePosition = Math.round(this.underlinePosition);
54 | }
55 |
56 | this.lines = [];
57 | this.myStrings = [];
58 |
59 | var words = this.text.match(/[^\s-]+-?\s?/g);
60 | var line = '';
61 |
62 | var linePositionY = 0;
63 | var firstLineCount = 0;
64 | for (var n = 0; n < words.length; n++) {
65 | // add the whitespace after getting the width measurement
66 | if (words[n].match(/\s+$/)) {
67 | // the last character of words[n] is whitespace
68 | var newWord = words[n].replace(/\s+$/, '');
69 | var testLine = line + newWord;
70 | var testLineMetrics = this.ctx.measureText(testLine);
71 | var testLineWidth = testLineMetrics.width;
72 | testLine = testLine + ' ';
73 | } else {
74 | var testLine = line + words[n];
75 | var testLineMetrics = this.ctx.measureText(testLine);
76 | var testLineWidth = testLineMetrics.width;
77 | }
78 |
79 | if (!firstLineCount) {
80 | //the first line, should consider startingPointX
81 | if (testLineWidth + this.elementStyles.textIndent > this.elementStyles.parentWidth && n > 0) {
82 | // draw the underline
83 | if (line.match(/\s+$/)) {
84 | // the last character of line is whitespace
85 | var lineMetrics = this.ctx.measureText(line.replace(/\s+$/, ''));
86 | var lineWidth = lineMetrics.width;
87 | } else {
88 | var lineMetrics = this.ctx.measureText(line);
89 | var lineWidth = lineMetrics.width;
90 | }
91 |
92 | var tempLine = {
93 | lineText: line,
94 | lineTextIndent: this.elementStyles.textIndent,
95 | linePositionY: linePositionY,
96 | lineMeasureWidth: lineWidth
97 | }
98 | this.lines.push(tempLine)
99 |
100 | line = words[n];
101 | linePositionY += this.elementStyles.lineHeight;
102 | firstLineCount++;
103 | } else {
104 | line = testLine;
105 | }
106 | } else {
107 | if (testLineWidth > this.elementStyles.parentWidth && n > 0) {
108 | // draw the underline
109 | if (line.match(/\s+$/)) {
110 | // the last character of line is whitespace
111 | var lineMetrics = this.ctx.measureText(line.replace(/\s+$/, ''));
112 | var lineWidth = lineMetrics.width;
113 | } else {
114 | var lineMetrics = this.ctx.measureText(line);
115 | var lineWidth = lineMetrics.width;
116 | }
117 |
118 | var tempLine = {
119 | lineText: line,
120 | lineTextIndent: 0,
121 | linePositionY: linePositionY,
122 | lineMeasureWidth: lineWidth
123 | }
124 | this.lines.push(tempLine);
125 |
126 | line = words[n];
127 | linePositionY += this.elementStyles.lineHeight;
128 | } else {
129 | line = testLine;
130 | }
131 | }
132 | }
133 | // draw the last line
134 | // draw the underline
135 | if (line.match(/\s+$/)) {
136 | // the last character of line is whitespace
137 | var lineMetrics = this.ctx.measureText(line.replace(/\s+$/, ''));
138 | var lineWidth = lineMetrics.width;
139 | } else {
140 | var lineMetrics = this.ctx.measureText(line);
141 | var lineWidth = lineMetrics.width;
142 | }
143 |
144 | var tempLine = {
145 | lineText: line,
146 | lineTextIndent: 0,
147 | linePositionY: linePositionY,
148 | lineMeasureWidth: lineWidth
149 | }
150 | this.lines.push(tempLine);
151 |
152 |
153 |
154 | for(var i = 0; i < this.lines.length; i++) {
155 | var tempLine = this.lines[i];
156 | var myString = new GuitarString(
157 | this.ctx,
158 | new Point(tempLine.lineTextIndent, tempLine.linePositionY + this.underlinePosition),
159 | new Point(tempLine.lineTextIndent + tempLine.lineMeasureWidth, tempLine.linePositionY + this.underlinePosition),
160 | this.strokeWidth, this.underlineStyles['text-underline-color'], 1);
161 | this.myStrings.push(myString);
162 | }
163 |
164 | this.drawUnderline();
165 | this.drawHoles();
166 |
167 | }
168 |
169 |
170 | MultipleUnderline.prototype.clear = function(){
171 | // clear
172 | var lastMultipleRedrawActive = this.multipleRedrawActive;
173 | this.multipleRedrawActive = false;
174 | for(var i = 0; i < this.myStrings.length; i++) {
175 | var tempString = this.myStrings[i];
176 | // this.myString.clear();
177 | // console.log(tempString.redrawActive);
178 | if(tempString.redrawActive) {
179 | this.multipleRedrawActive = true;
180 | }
181 | }
182 | // console.log(this.multipleRedrawActive);
183 | if (this.multipleRedrawActive) {
184 | console.log('clear now!')
185 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
186 | }
187 | // if (!lastMultipleRedrawActive && this.multipleRedrawActive) {
188 | // for(var i = 0; i < this.myStrings.length; i++) {
189 | // var tempString = this.myStrings[i];
190 | // tempString.drawLine();
191 | // }
192 | // }
193 |
194 | };
195 |
196 | MultipleUnderline.prototype.update = function(){
197 | //update
198 | };
199 |
200 |
201 | MultipleUnderline.prototype.draw = function(){
202 | // draw
203 | if (this.multipleRedrawActive) {
204 | this.drawUnderline();
205 | this.drawHoles();
206 | }
207 | };
208 |
209 |
210 | MultipleUnderline.prototype.drawUnderline = function(){
211 | // draw the underline
212 | for(var i = 0; i < this.myStrings.length; i++) {
213 | var tempString = this.myStrings[i];
214 | // tempString.clear();
215 | tempString.update();
216 | tempString.draw();
217 | }
218 |
219 | };
220 |
221 |
222 | MultipleUnderline.prototype.drawHoles = function(){
223 | // draw the font stroke
224 | for(var i = 0; i < this.lines.length; i++) {
225 | var tempLine = this.lines[i];
226 |
227 | this.ctx.globalCompositeOperation = "destination-out";
228 | this.ctx.font = this.font;
229 | this.ctx.fillStyle = 'green';
230 | this.ctx.textBaseline = 'top';
231 | this.ctx.fillText(tempLine.lineText, tempLine.lineTextIndent, tempLine.linePositionY);
232 | this.ctx.lineWidth = 3 + this.strokeWidth;
233 | this.ctx.strokeStyle = 'blue';
234 | this.ctx.strokeText(tempLine.lineText, tempLine.lineTextIndent, tempLine.linePositionY);
235 |
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/js/multiple-underline.js:
--------------------------------------------------------------------------------
1 |
2 | function MultipleUnderline(element, underlineStyles, elementStyles) {
3 | //ctor
4 | this.element = element;
5 |
6 | this.text = this.element.textContent;
7 |
8 | this.underlineStyles = underlineStyles;
9 |
10 | // this.elementStyles = getElementStyles(element);
11 | this.elementStyles = elementStyles;
12 |
13 | this.canvas = document.createElement("canvas");
14 | this.ctx = this.canvas.getContext('2d');
15 |
16 |
17 | this.ratio = window.devicePixelRatio;
18 | this.canvas.width = this.elementStyles.width*this.ratio;
19 | this.canvas.height = this.elementStyles.height*this.ratio;
20 | // this.canvas.height = this.canvas.clientHeight + this.elementStyles.lineHeight;
21 | this.canvas.style.left = this.elementStyles.canvasLeft + 'px';
22 | this.element.appendChild(this.canvas);
23 | this.canvas.style.width = this.elementStyles.width + 'px';
24 |
25 | this.ctx.font = this.font = this.elementStyles.fontStyle + ' '
26 | + multiplyValue(this.elementStyles.fontSize, this.ratio) + ' '
27 | + this.elementStyles.fontFamily;
28 |
29 | this.multipleRedrawActive = false;
30 | if (is_chrome) {
31 | // chrome floor the lineheight when it is not a whole number
32 | // this.elementStyles.lineHeight = Math.floor(this.elementStyles.lineHeight * this.ratio);
33 | this.elementStyles.lineHeight = this.elementStyles.lineHeight * this.ratio;
34 | } else {
35 | this.elementStyles.lineHeight = this.elementStyles.lineHeight * this.ratio;
36 | }
37 |
38 | // determine the text-underline-width / strokeWidth
39 | var dotWidth = this.ctx.measureText('.')['width'];
40 | if (this.underlineStyles['text-underline-width'] == "auto") {
41 | // if set to auto, calculate the optimized width based on font
42 | this.strokeWidth = dotWidth/12;
43 | } else {
44 | //if set to px value, todo: other unit such as em?
45 | this.strokeWidth = this.underlineStyles['text-underline-width'];
46 | //get number value
47 | this.strokeWidth = parseFloat(this.strokeWidth)*this.ratio;
48 | }
49 |
50 | // determine the text-underline-position / underlinePosition
51 | // text-underline-position in ratio, todo: default and user set position ratio
52 | if (this.underlineStyles['text-underline-position'] == "auto") {
53 | // if set to auto, calculate the optimized width based on font
54 | this.underlinePosition = parseFloat(this.elementStyles.fontSize) * this.ratio
55 | * ( 1 - this.elementStyles.baselinePositionRatio +
56 | this.elementStyles.baselinePositionRatio * 0.4)
57 | + this.strokeWidth/2;
58 | } else {
59 | //if set to ratio value, todo: other unit such as em, px?
60 | var userUnderlinePosition = parseFloat(this.underlineStyles['text-underline-position']);
61 | // console.log(userUnderlinePosition);
62 | this.underlinePosition = parseFloat(this.elementStyles.fontSize) * this.ratio *
63 | ( 1 - this.elementStyles.baselinePositionRatio +
64 | this.elementStyles.baselinePositionRatio * userUnderlinePosition)
65 | + this.strokeWidth/2;
66 | }
67 |
68 |
69 | var adjustValue = optimalStrokeWidthPos(this.strokeWidth, this.underlinePosition);
70 | this.strokeWidth = adjustValue.strokeWidth;
71 | this.underlinePosition = adjustValue.posY;
72 |
73 | this.lines = [];
74 | this.myStrings = [];
75 |
76 | var words = this.text.match(/[^\s-]+-?\s?/g);
77 | var line = '';
78 |
79 | var linePositionY = 0;
80 | var firstLineCount = 0;
81 | for (var n = 0; n < words.length; n++) {
82 | // add the whitespace after getting the width measurement
83 | if (words[n].match(/\s+$/)) {
84 | // the last character of words[n] is whitespace
85 | var newWord = words[n].replace(/\s+$/, '');
86 | var testLine = line + newWord;
87 | var testLineMetrics = this.ctx.measureText(testLine);
88 | var testLineWidth = testLineMetrics.width;
89 | testLine = testLine + ' ';
90 | } else {
91 | var testLine = line + words[n];
92 | var testLineMetrics = this.ctx.measureText(testLine);
93 | var testLineWidth = testLineMetrics.width;
94 | }
95 |
96 | if (!firstLineCount) {
97 | //the first line, should consider startingPointX
98 | if (testLineWidth + this.elementStyles.textIndent * this.ratio > this.elementStyles.parentWidth * this.ratio && n > 0) {
99 | // draw the underline
100 | if (line.match(/\s+$/)) {
101 | // the last character of line is whitespace
102 | var lineMetrics = this.ctx.measureText(line.replace(/\s+$/, ''));
103 | var lineWidth = lineMetrics.width;
104 | } else {
105 | var lineMetrics = this.ctx.measureText(line);
106 | var lineWidth = lineMetrics.width;
107 | }
108 |
109 | var tempLine = {
110 | lineText: line,
111 | lineTextIndent: this.elementStyles.textIndent * this.ratio - 0.2,
112 | linePositionY: linePositionY,
113 | lineMeasureWidth: lineWidth
114 | }
115 | this.lines.push(tempLine)
116 |
117 | line = words[n];
118 | linePositionY += this.elementStyles.lineHeight;
119 | firstLineCount++;
120 | } else {
121 | line = testLine;
122 | }
123 | } else {
124 | if (testLineWidth > this.elementStyles.parentWidth * this.ratio && n > 0) {
125 | // draw the underline
126 | if (line.match(/\s+$/)) {
127 | // the last character of line is whitespace
128 | var lineMetrics = this.ctx.measureText(line.replace(/\s+$/, ''));
129 | var lineWidth = lineMetrics.width;
130 | } else {
131 | var lineMetrics = this.ctx.measureText(line);
132 | var lineWidth = lineMetrics.width;
133 | }
134 |
135 | var tempLine = {
136 | lineText: line,
137 | lineTextIndent: -0.2,
138 | linePositionY: linePositionY,
139 | lineMeasureWidth: lineWidth
140 | }
141 | this.lines.push(tempLine);
142 |
143 | line = words[n];
144 | linePositionY += this.elementStyles.lineHeight;
145 | } else {
146 | line = testLine;
147 | }
148 | }
149 | }
150 | // draw the last line
151 | // draw the underline
152 | if (line.match(/\s+$/)) {
153 | // the last character of line is whitespace
154 | var lineMetrics = this.ctx.measureText(line.replace(/\s+$/, ''));
155 | var lineWidth = lineMetrics.width;
156 | } else {
157 | var lineMetrics = this.ctx.measureText(line);
158 | var lineWidth = lineMetrics.width;
159 | }
160 |
161 | var tempLine = {
162 | lineText: line,
163 | lineTextIndent: -0.2,
164 | linePositionY: linePositionY,
165 | lineMeasureWidth: lineWidth
166 | }
167 | this.lines.push(tempLine);
168 | for(var i = 0; i < this.lines.length; i++) {
169 | var tempLine = this.lines[i];
170 | var myString = new GuitarString(
171 | this.ctx,
172 | new Point(tempLine.lineTextIndent, tempLine.linePositionY + this.underlinePosition),
173 | new Point(tempLine.lineTextIndent + tempLine.lineMeasureWidth, tempLine.linePositionY + this.underlinePosition),
174 | this.strokeWidth, this.underlineStyles['text-underline-color'], this.ratio);
175 | this.myStrings.push(myString);
176 | }
177 |
178 | this.drawUnderline();
179 | this.drawHoles();
180 |
181 | }
182 |
183 | MultipleUnderline.prototype.drawUnderline = function(){
184 | // draw the underline
185 | for(var i = 0; i < this.myStrings.length; i++) {
186 | var tempString = this.myStrings[i];
187 | // tempString.clear();
188 | tempString.update();
189 | tempString.draw();
190 | }
191 |
192 | };
193 |
194 |
195 | MultipleUnderline.prototype.drawHoles = function(){
196 | // draw the font stroke
197 | for(var i = 0; i < this.lines.length; i++) {
198 | var tempLine = this.lines[i];
199 |
200 | this.ctx.globalCompositeOperation = "destination-out";
201 | this.ctx.font = this.font;
202 |
203 | this.ctx.fillStyle = 'green';
204 | this.ctx.textBaseline = 'top';
205 | this.ctx.fillText(tempLine.lineText, tempLine.lineTextIndent, tempLine.linePositionY);
206 |
207 | this.ctx.lineWidth = 2*this.ratio + this.strokeWidth*3.6;
208 | this.ctx.strokeStyle = 'blue';
209 | this.ctx.strokeText(tempLine.lineText, tempLine.lineTextIndent, tempLine.linePositionY);
210 |
211 | }
212 | }
213 |
214 | MultipleUnderline.prototype.clear = function(){
215 | // clear
216 | var lastMultipleRedrawActive = this.multipleRedrawActive;
217 | this.multipleRedrawActive = false;
218 | for(var i = 0; i < this.myStrings.length; i++) {
219 | var tempString = this.myStrings[i];
220 | // this.myString.clear();
221 | // console.log(tempString.redrawActive);
222 | if(tempString.redrawActive) {
223 | this.multipleRedrawActive = true;
224 | }
225 | }
226 | // console.log(this.multipleRedrawActive);
227 | if (this.multipleRedrawActive) {
228 | console.log('clear now!')
229 | this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
230 | }
231 | // if (!lastMultipleRedrawActive && this.multipleRedrawActive) {
232 | // for(var i = 0; i < this.myStrings.length; i++) {
233 | // var tempString = this.myStrings[i];
234 | // tempString.drawLine();
235 | // }
236 | // }
237 |
238 | };
239 |
240 | MultipleUnderline.prototype.update = function(){
241 | //update
242 | };
243 |
244 |
245 | MultipleUnderline.prototype.draw = function(){
246 | // draw
247 | if (this.multipleRedrawActive) {
248 | this.drawUnderline();
249 | this.drawHoles();
250 | }
251 | };
252 |
253 |
254 |
--------------------------------------------------------------------------------
/css/style.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": "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",
4 | "sources": ["reset.scss","style.scss","animation.scss","mobile.scss","tablet.scss"],
5 | "names": [],
6 | "file": "style.css"
7 | }
--------------------------------------------------------------------------------
/css/style.scss:
--------------------------------------------------------------------------------
1 | @import 'reset';
2 | $green: #CDDC39;
3 | $darkGreen: #212121;
4 | $lightGreen: #B2FF9E;
5 | $dark: #212121;
6 | $fira: 'Fira Sans';
7 | $ebgaramond: 'EB Garamond';
8 | $ebgamramondsc: 'EB Garamond SC';
9 | $sourcecodepro: 'Source Code Pro';
10 | $icon: 'hack-the-hackpad-icon';
11 | $fullWidth: 760px;
12 | $transition: all 0.4s ease;
13 | @font-face {
14 | font-family: 'EB Garamond SC';
15 | src: url('../fonts/ebgaramond12-sc.eot');
16 | src: url('../fonts/ebgaramond12-sc.eot?#iefix') format('embedded-opentype'),
17 | url('../fonts/ebgaramond12-sc.woff2') format('woff2'),
18 | url('../fonts/ebgaramond12-sc.woff') format('woff'),
19 | url('../fonts/ebgaramond12-sc.ttf') format('truetype'),
20 | url('../fonts/ebgaramond12-sc.svg#eb_garamond12_sc_regular') format('svg');
21 | font-weight: normal;
22 | font-style: normal;
23 | }
24 | @font-face {
25 | font-family: 'hack-the-hackpad-icon';
26 | src:url('../fonts/hack-the-hackpad-icon.eot?ksq0g9');
27 | src:url('../fonts/hack-the-hackpad-icon.eot?#iefixksq0g9') format('embedded-opentype'),
28 | url('../fonts/hack-the-hackpad-icon.woff?ksq0g9') format('woff'),
29 | url('../fonts/hack-the-hackpad-icon.ttf?ksq0g9') format('truetype'),
30 | url('../fonts/hack-the-hackpad-icon.svg?ksq0g9#hack-the-hackpad-icon') format('svg');
31 | font-weight: normal;
32 | font-style: normal;
33 | }
34 |
35 | [class^="icon-"]::before, [class*=" icon-"]::before {
36 | font-family: $icon;
37 | speak: none;
38 | font-style: normal;
39 | font-weight: normal;
40 | font-variant: normal;
41 | text-transform: none;
42 | -webkit-font-smoothing: antialiased;
43 | -moz-osx-font-smoothing: grayscale;
44 | }
45 | ::selection {
46 | background: rgba($green, 0.5);
47 | }
48 | ::-moz-selection {
49 | background: rgba($green, 0.5);
50 | }
51 | input[type=text], textarea {
52 | -webkit-transition: all 0.30s ease-in-out;
53 | -moz-transition: all 0.30s ease-in-out;
54 | -ms-transition: all 0.30s ease-in-out;
55 | -o-transition: all 0.30s ease-in-out;
56 | outline: none;
57 | border: none;
58 | }
59 |
60 | input[type=text]:focus, textarea:focus {
61 | box-shadow: inset 0 0 5px rgba($green, 0);
62 | border: 1px solid rgba($green, 0);
63 | }
64 | body {
65 | font-family: $ebgaramond !important;
66 | font-size: 24px;
67 | line-height: 36px;
68 | color: $dark;
69 | margin: 0;
70 | padding: 0;
71 | -moz-osx-font-smoothing: grayscale;
72 | -webkit-font-smoothing: antialiased;
73 | -moz-osx-font-smoothing: grayscale;
74 | text-rendering: optimizeLegibility;
75 | -moz-font-feature-settings: "kern=1", "liga=1", "dlig=1", "hlig=1";
76 | -moz-font-feature-settings: "kern" on, "liga" on, "dlig" on, "hlig" on;
77 | -webkit-font-feature-settings: "kern","liga","dlig","hlig";
78 | -ms-font-feature-settings: "kern","liga","dlig","hlig";
79 | font-feature-settings: "kern","liga","dlig","hlig";
80 | }
81 | a {
82 | text-decoration: none;
83 | color: $dark;
84 | }
85 | img {
86 | max-width: 100%;
87 | }
88 | header {
89 | width: 100%;
90 | height: 60px;
91 | border-top: solid 4px $green;
92 | // border-bottom: solid 1px rgba($dark, 0.4);
93 | position: fixed;
94 | top: 0;
95 | background-color: rgba(255,255,255,0.92);
96 | z-index: 1;
97 | .logo {
98 | z-index: 2;
99 | position: absolute;
100 | cursor: pointer;
101 | top: 20px;
102 | left: 40px;
103 | overflow: hidden;
104 | width: 264px;
105 | transition: all 0.6s cubic-bezier(0.7,0,0.3,1);
106 | // -webkit-transition-delay: 0.25s;
107 | // transition-delay: 0.25s;
108 | #underline, #js, #line {
109 | transition: all 0.6s cubic-bezier(0.7,0,0.3,1);
110 | }
111 | #underline {
112 | fill: $darkGreen;
113 | }
114 | #js {
115 | -webkit-transform: translate(0, 0);
116 | transform: translate(0, 0);
117 | fill: $darkGreen;
118 | }
119 | #line {
120 | fill: $darkGreen;
121 | }
122 | &:hover {
123 | -webkit-transition-delay: 0.25s;
124 | transition-delay: 0.25s;
125 | #underline {
126 | fill: $green;
127 | }
128 | #js {
129 | fill: $green;
130 | }
131 | #line {
132 | fill: $green;
133 | }
134 | }
135 | .collapse & {
136 | width: 45px;
137 | #underline, #js, #line {
138 | }
139 | #line {
140 | -webkit-transform: translate(-218.7px, 0);
141 | transform: translate(-218.7px, 0);
142 | fill: $green;
143 |
144 | }
145 | #underline {
146 | opacity: 0;
147 |
148 | }
149 | #js {
150 | -webkit-transform: translate(-218.7px, 0);
151 | transform: translate(-218.7px, 0);
152 | fill: $green;
153 | }
154 | }
155 | }
156 | .hamburger {
157 | display: none;
158 | width: 64px;
159 | height: 64px;
160 | z-index: 2;
161 | position: absolute;
162 | right: 0;
163 | top: 0;
164 | cursor: pointer;
165 | -webkit-user-select: none;
166 | -moz-user-select: none;
167 | -ms-user-select: none;
168 | -o-user-select: none;
169 | user-select: none;
170 | i {
171 | display: block;
172 | width: 24px;
173 | height: 3px;
174 | position: absolute;
175 | left: 20px;
176 | top: 28px;
177 | background-color: $green;
178 | transition: $transition;
179 | &::before {
180 | content: '';
181 | display: block;
182 | width: 24px;
183 | height: 3px;
184 | position: absolute;
185 | left: 0px;
186 | top: -8px;
187 | background-color: $green;
188 | transition: $transition;
189 | }
190 | &::after {
191 | content: '';
192 | display: block;
193 | width: 24px;
194 | height: 3px;
195 | position: absolute;
196 | left: 0px;
197 | top: 8px;
198 | background-color: $green;
199 | transition: $transition;
200 | }
201 | }
202 |
203 | }
204 | .menu {
205 | font-weight: 300;
206 | font-size: 24px;
207 | line-height: 60px;
208 | position: absolute;
209 | top: 2px;
210 | right: 40px;
211 | height: 60px;
212 | a {
213 | font-family: $fira;
214 | position: relative;
215 | display: inline-block;
216 | margin-left: 30px;
217 | padding-left: 28px;
218 | color: $dark;
219 | transition: color 0.4s;
220 | &::before {
221 | transition: color 0.4s;
222 | font-family: $icon;
223 | font-style: normal;
224 | position: absolute;
225 | width: 20px;
226 | text-align: right;
227 | left: 0px;
228 | font-size: 24px;
229 | color: $darkGreen;
230 | }
231 | }
232 | a:hover {
233 | color: $green;
234 | // color: $darkGreen;
235 | &::before {
236 | color: $green;
237 | // text-shadow: 0px 0px 3px rgba($green, 0.5);
238 | }
239 | }
240 | .icon-edit {
241 | display: inline-block;
242 | }
243 | .icon-question {
244 | display: none;
245 | }
246 | .icon-github::before {
247 | content: '\e60b';
248 | top: -2px;
249 | }
250 | .icon-edit::before {
251 | content: '\e611';
252 | top: -2px;
253 | }
254 | .icon-question::before {
255 | content: '\e612';
256 | top: -2px;
257 | }
258 | }
259 | }
260 | .trigger {
261 | width: 100%;
262 | height: 40px;
263 | position: fixed;
264 | bottom: 20px;
265 | cursor: pointer;
266 | z-index: 3;
267 | transition: $transition;
268 | -webkit-transition-delay: 0.6s;
269 | transition-delay: 0.6s;
270 | &::before {
271 | content: '';
272 | display: block;
273 | width: 40px;
274 | height: 40px;
275 | margin: 0 auto;
276 | margin-top: -20px;
277 | transition: $transition;
278 | border-bottom: solid 1px rgba($dark, 1);
279 | border-right: solid 1px rgba($dark, 1);
280 | -webkit-transform: rotate(45deg);
281 | transform: rotate(45deg);
282 | }
283 | &:hover::before {
284 | border-bottom: solid 1px rgba($green, 1);
285 | border-right: solid 1px rgba($green, 1);
286 | }
287 | }
288 | article {
289 | width: $fullWidth;
290 | margin: 0 auto;
291 | font-size: 24px;
292 | line-height: 36px;
293 | position: relative;
294 | }
295 | footer {
296 | height: 360px;
297 | width: $fullWidth;
298 | margin: 0 auto;
299 | .share {
300 | display: block;
301 | position: relative;
302 | top: 150px;
303 | margin: 0 auto 0 auto;
304 | width: 240px;
305 | height: 1px;
306 | background-color: rgba($dark, 0.4);
307 | cursor: pointer;
308 | &::before {
309 | content: '\e615';
310 | text-align: center;
311 | font-size: 32px;
312 | line-height: 82px;
313 | display: block;
314 | position: absolute;
315 | left: 79px;
316 | top: -40px;
317 | width: 80px;
318 | height: 80px;
319 | border-radius: 100%;
320 | border: solid 1px rgba($dark, 0.4);
321 | background-color: white;
322 | // color: $darkGreen;
323 | transition: $transition;
324 | }
325 | &:hover::before {
326 | color: $green;
327 | }
328 | }
329 | }
330 | /********** Title ***********/
331 | h1 {
332 | width: 100%;
333 | height: 100vh;
334 | padding-top: 38.2vh;
335 | box-sizing: border-box;
336 | font-family: $fira;
337 | font-weight: 700;
338 | font-size: 48px;
339 | line-height: 60px;
340 | text-align: center;
341 | margin-bottom: 100px;
342 | position: absolute;
343 | top: 0px;
344 | &::after {
345 | // content: '';
346 | display: block;
347 | position: absolute;
348 | width: 240px;
349 | height: 1px;
350 | background-color: rgba($dark, 0.4);
351 | margin: 0 auto;
352 | bottom: -1px;
353 | left: 260px;
354 | }
355 | }
356 | /********** Heading 1 ***********/
357 | h2 {
358 | font-family: $fira;
359 | font-weight: 500;
360 | color: $dark;
361 | font-size: 32px;
362 | line-height: 40px;
363 | font-weight: 500;
364 | letter-spacing: -0.5px;
365 | padding-top: 40px;
366 | }
367 | /********** Heading 2 ***********/
368 | p.heading2 {
369 | padding: 16px 0;
370 | strong{
371 | font-family: $fira;
372 | font-size: 24px;
373 | line-height: 36px;
374 | display: block;
375 | letter-spacing: -0.8px;
376 | text-shadow: none;
377 | }
378 | }
379 |
380 | p {
381 | font-family: $ebgaramond;
382 | margin-top: 24px;
383 | }
384 | p.text a {
385 | font-size: 48px;
386 | line-height: 1.4em;
387 | font-style: italic;
388 | }
389 | p a.title {
390 | font-size: 126px;
391 | line-height: 1.4em;
392 | }
393 | p strong {
394 | font-family: $ebgamramondsc;
395 | text-shadow: 0 0 2px rgba(0, 0, 0, 0.3);
396 | }
397 | p em {
398 | font-style: italic;
399 | }
400 | p:empty {
401 | margin-top: 0px;
402 | }
403 |
404 |
405 | @import 'animation';
406 | @import 'mobile';
407 | @import 'tablet';
--------------------------------------------------------------------------------
/js/guitar-string.js:
--------------------------------------------------------------------------------
1 | var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
2 |
3 |
4 | var circleCenter = function(startPoint, thirdPoint, endPoint){
5 | var dy1 = thirdPoint.y - startPoint.y;
6 | var dx1 = thirdPoint.x - startPoint.x;
7 | var dy2 = endPoint.y - thirdPoint.y;
8 | var dx2 = endPoint.x - thirdPoint.x;
9 |
10 | var aSlope = dy1/dx1;
11 | var bSlope = dy2/dx2;
12 |
13 |
14 | var centerX = (aSlope*bSlope*(startPoint.y - endPoint.y) + bSlope*(startPoint.x + thirdPoint.x)
15 | - aSlope*(thirdPoint.x+endPoint.x) )/( 2* (bSlope-aSlope) );
16 | var centerY = -1*(centerX - (startPoint.x+thirdPoint.x)/2)/aSlope + (startPoint.y+thirdPoint.y)/2;
17 | var r = dist(centerX, centerY, startPoint.x, startPoint.y)
18 |
19 | return {
20 | x: centerX,
21 | y: centerY,
22 | r: r
23 | };
24 | }
25 |
26 | var dist = function(x, y, x0, y0){
27 | return Math.sqrt((x -= x0) * x + (y -= y0) * y);
28 | };
29 |
30 | var Point = function (x,y){
31 | this.x=x;
32 | this.y=y;
33 | }
34 |
35 |
36 | var intersects = function(a, b, c, d, p, q, r, s) {
37 | // returns true if the line from (a,b)->(c,d) intersects with (p,q)->(r,s)
38 | var det, gamma, lambda;
39 | det = (c - a) * (s - q) - (r - p) * (d - b);
40 | if (det === 0) {
41 | return false;
42 | } else {
43 | lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / det;
44 | gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / det;
45 | return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1);
46 | }
47 | };
48 |
49 | var musicLevel = function(startPoint, endPoint, ratio){
50 | var length = dist(startPoint.x, startPoint.y, endPoint.x, endPoint.y)/ratio;
51 |
52 | level = Math.floor(length/30);
53 | if (level > 19 ) {
54 | level = 19;
55 | }
56 | level = 19 - level
57 | if (level < 10) {
58 | level = '0' + level
59 | }
60 | return level;
61 | };
62 | function GuitarString(ctx, startPoint, endPoint, strokeWidth, strokeColor, ratio) {
63 | //ctor
64 | this.ctx = ctx;
65 | this.canvas = ctx.canvas;
66 | this.startPoint = startPoint;
67 | this.endPoint = endPoint;
68 | this.strokeWidth = strokeWidth;
69 | this.strokeColor = strokeColor;
70 | this.ratio = ratio;
71 |
72 | this.level = musicLevel(this.startPoint, this.endPoint, this.ratio);
73 |
74 | // this.canvas.width = this.canvas.clientWidth;
75 | // this.canvas.height = this.canvas.clientHeight*1.2;
76 |
77 | this.maxGrabDistance = this.strokeWidth * 2;
78 | this.maxControlDistance = this.strokeWidth * 6;
79 |
80 | this.ctx.lineWidth = this.strokeWidth;
81 | this.ctx.strokeStyle = this.strokeColor;
82 | this.ctx.beginPath();
83 | this.ctx.moveTo(this.startPoint.x, this.startPoint.y);
84 | this.ctx.lineTo(this.endPoint.x, this.endPoint.y);
85 | this.ctx.globalCompositeOperation = "source-over";
86 | this.ctx.stroke();
87 |
88 | this.currentMouseX;
89 | this.currentMouseY;
90 | this.lastMouseX;
91 | this.lastMouseY;
92 | this.waveInitX = (this.startPoint.x + this.endPoint.x)/2;
93 | this.waveInitY = this.startPoint.y - this.maxControlDistance;
94 | this.waveCount = 0;
95 | this.damping = 0.9;
96 |
97 | this.thirdPoint = new Point((this.startPoint.x + this.endPoint.x)/2, this.startPoint.y);
98 |
99 |
100 | // state flags
101 | this.userInControl = false;
102 | this.userPlucked = false;
103 | this.waveInControl = false;
104 | this.waveFinished = false;
105 | this.initState = true;
106 | this.lastRedraw = false;
107 | this.redrawActive = false;
108 |
109 | //add event listener
110 | var self = this;
111 | this.canvas.addEventListener('mouseover', function(event) {
112 | self.mouseOver(self, event);
113 | }, false);
114 |
115 | this.canvas.addEventListener('mousemove', function(event) {
116 | self.mouseMove(self, event);
117 | }, false);
118 |
119 | this.canvas.addEventListener ("mouseleave", function(event){
120 | self.mouseLeave(self, event);
121 | }, false);
122 |
123 | this.canvas.addEventListener ("mouseout", function(event){
124 | self.mouseOut(self, event);
125 | }, false);
126 |
127 | this.canvas.addEventListener("touchstart", function(event) {
128 | self.touchDown(self, event);
129 | }, false);
130 | this.canvas.addEventListener("touchmove", function(event) {
131 | self.touchXY(self, event);
132 | }, false);
133 | this.canvas.addEventListener("touchend", function(event) {
134 | self.touchUp(self, event);
135 | }, false);
136 |
137 | }
138 |
139 | GuitarString.prototype.mouseOver = function(self, event){
140 | // console.log('mouseOver');
141 | this.currentMouseX = event.layerX*this.ratio;
142 | this.currentMouseX = event.layerY*this.ratio;
143 | };
144 | GuitarString.prototype.mouseMove = function (self, event){
145 | // console.log('mouseMove');
146 | this.lastMouseX = this.currentMouseX;
147 | this.lastMouseY = this.currentMouseY;
148 | this.currentMouseX = event.layerX * this.ratio;
149 | this.currentMouseY = event.layerY * this.ratio;
150 |
151 | var radius = circleCenter( new Point(this.startPoint.x, this.startPoint.y),
152 | new Point(this.currentMouseX, this.currentMouseY),
153 | new Point(this.endPoint.x, this.endPoint.y) ).r;
154 | var currentWaveDistance = radius - Math.sqrt( Math.pow(radius, 2) - Math.pow((Math.abs(this.endPoint.x - this.startPoint.x))/2, 2) );
155 | var lastRadius = circleCenter( new Point(this.startPoint.x, this.startPoint.y),
156 | new Point(this.lastMouseX, this.lastMouseY),
157 | new Point(this.endPoint.x, this.endPoint.y) ).r;
158 | var lastWaveDistance = lastRadius - Math.sqrt( Math.pow(lastRadius, 2)
159 | - Math.pow((Math.abs(this.endPoint.x - this.startPoint.x))/2, 2) );
160 |
161 |
162 |
163 | var mouseInGrabRange = currentWaveDistance < this.maxGrabDistance
164 | && this.currentMouseX > this.startPoint.x
165 | && this.currentMouseX < this.endPoint.x;
166 |
167 | var lastMouseOutGrabRange = !(lastWaveDistance < this.maxGrabDistance
168 | && this.lastMouseX > this.startPoint.x
169 | && this.lastMouseX < this.endPoint.x);
170 |
171 | var mouseOutControlRange = !(currentWaveDistance < this.maxControlDistance
172 | && this.currentMouseX > this.startPoint.x
173 | && this.currentMouseX < this.endPoint.x);
174 |
175 | var lastMouseInControlRange = lastWaveDistance < this.maxControlDistance
176 | && this.lastMouseX > this.startPoint.x
177 | && this.lastMouseY < this.endPoint.x;
178 |
179 | var mouseCrossed = intersects(this.lastMouseX, this.lastMouseY,
180 | this.currentMouseX, this.currentMouseY,
181 | this.startPoint.x, this.startPoint.y,
182 | this.endPoint.x, this.endPoint.y);
183 |
184 | if( mouseInGrabRange && lastMouseOutGrabRange && (!this.userInControl) ){
185 | // console.log('grab!');
186 | this.initState = false;
187 | this.userInControl = true;
188 | this.waveInControl = false;
189 | this.waveFinished = false;
190 |
191 | this.redrawActive = true;
192 | } else if ( mouseOutControlRange && lastMouseInControlRange && this.userInControl){
193 | // console.log('boing!');
194 | this.initState = false;
195 | this.userInControl = false;
196 | this.waveInControl = true;
197 | this.waveFinished = false;
198 | this.waveCount = 0;
199 | // this.waveInitX = this.lastMouseX;
200 | // this.waveInitY = this.lastMouseY;
201 | this.waveInitX = (this.startPoint.x + this.endPoint.x)/2;
202 | this.waveInitY = this.endPoint.y + this.maxControlDistance;
203 | // play audio
204 | play_multi_sound('audio' + this.level);
205 | // createjs.Sound.play('cello_' + this.level);
206 |
207 | }
208 |
209 | if( (!this.userInControl)&&mouseCrossed ) {
210 | // console.log('i just plucked!');
211 | this.initState = false;
212 | this.userInControl = false;
213 | this.waveInControl = true;
214 | this.waveFinished = false;
215 | this.redrawActive = true;
216 | this.waveCount = 0;
217 | this.waveInitX = (this.startPoint.x + this.endPoint.y)/2;
218 | this.waveInitY = this.endPoint.y + this.maxGrabDistance * 2 / 3;
219 | }
220 | };
221 | GuitarString.prototype.mouseLeave = function(self, event){
222 | // console.log('mouseLeave');
223 | if( this.userInControl ) {
224 | this.initState = false;
225 | this.userInControl = false;
226 | this.waveInControl = true;
227 | this.waveFinished = false;
228 | this.redrawActive = true;
229 | this.waveCount = 0;
230 |
231 | this.waveInitX = event.layerX*this.ratio;
232 | this.waveInitY = event.layerY*this.ratio;
233 |
234 | }
235 | };
236 | GuitarString.prototype.mouseOut = function(self, event){
237 | // console.log('mouseOut');
238 | };
239 | GuitarString.prototype.touchDown = function(self, event){
240 | // console.log('touchDown');
241 | this.currentMouseX = event.layerX*this.ratio;
242 | this.currentMouseX = event.layerY*this.ratio;
243 | };
244 | GuitarString.prototype.touchXY = function (self, event){
245 | // console.log('touchMove');
246 | this.lastMouseX = this.currentMouseX;
247 | this.lastMouseY = this.currentMouseY;
248 | this.currentMouseX = event.layerX * this.ratio;
249 | this.currentMouseY = event.layerY * this.ratio;
250 |
251 | var radius = circleCenter( new Point(this.startPoint.x, this.startPoint.y),
252 | new Point(this.currentMouseX, this.currentMouseY),
253 | new Point(this.endPoint.x, this.endPoint.y) ).r;
254 | var currentWaveDistance = radius - Math.sqrt( Math.pow(radius, 2) - Math.pow((Math.abs(this.endPoint.x - this.startPoint.x))/2, 2) );
255 | var lastRadius = circleCenter( new Point(this.startPoint.x, this.startPoint.y),
256 | new Point(this.lastMouseX, this.lastMouseY),
257 | new Point(this.endPoint.x, this.endPoint.y) ).r;
258 | var lastWaveDistance = lastRadius - Math.sqrt( Math.pow(lastRadius, 2)
259 | - Math.pow((Math.abs(this.endPoint.x - this.startPoint.x))/2, 2) );
260 |
261 |
262 |
263 | var mouseInGrabRange = currentWaveDistance < this.maxGrabDistance
264 | && this.currentMouseX > this.startPoint.x
265 | && this.currentMouseX < this.endPoint.x;
266 |
267 | var lastMouseOutGrabRange = !(lastWaveDistance < this.maxGrabDistance
268 | && this.lastMouseX > this.startPoint.x
269 | && this.lastMouseX < this.endPoint.x);
270 |
271 | var mouseOutControlRange = !(currentWaveDistance < this.maxControlDistance
272 | && this.currentMouseX > this.startPoint.x
273 | && this.currentMouseX < this.endPoint.x);
274 |
275 | var lastMouseInControlRange = lastWaveDistance < this.maxControlDistance
276 | && this.lastMouseX > this.startPoint.x
277 | && this.lastMouseY < this.endPoint.x;
278 |
279 | var mouseCrossed = intersects(this.lastMouseX, this.lastMouseY,
280 | this.currentMouseX, this.currentMouseY,
281 | this.startPoint.x, this.startPoint.y,
282 | this.endPoint.x, this.endPoint.y);
283 |
284 | if( mouseInGrabRange && lastMouseOutGrabRange && (!this.userInControl) ){
285 | // console.log('grab!');
286 | this.initState = false;
287 | this.userInControl = true;
288 | this.waveInControl = false;
289 | this.waveFinished = false;
290 |
291 | this.redrawActive = true;
292 | } else if ( mouseOutControlRange && lastMouseInControlRange && this.userInControl){
293 | // console.log('boing!');
294 | this.initState = false;
295 | this.userInControl = false;
296 | this.waveInControl = true;
297 | this.waveFinished = false;
298 | this.waveCount = 0;
299 | // this.waveInitX = this.lastMouseX;
300 | // this.waveInitY = this.lastMouseY;
301 | this.waveInitX = (this.startPoint.x + this.endPoint.x)/2;
302 | this.waveInitY = this.endPoint.y + this.maxControlDistance;
303 | // play audio
304 | play_multi_sound('audio' + this.level);
305 |
306 | }
307 |
308 | if( (!this.userInControl)&&mouseCrossed ) {
309 | // console.log('i just plucked!');
310 | this.initState = false;
311 | this.userInControl = false;
312 | this.waveInControl = true;
313 | this.waveFinished = false;
314 | this.redrawActive = true;
315 | this.waveCount = 0;
316 | this.waveInitX = (this.startPoint.x + this.endPoint.y)/2;
317 | this.waveInitY = this.endPoint.y + this.maxGrabDistance * 2 / 3;
318 | // play audio
319 | // play_multi_sound('audio' + this.level);
320 |
321 | }
322 | };
323 | GuitarString.prototype.touchUp = function(self, event){
324 | // console.log('touchUp');
325 | if( this.userInControl ) {
326 | this.initState = false;
327 | this.userInControl = false;
328 | this.waveInControl = true;
329 | this.waveFinished = false;
330 | this.redrawActive = true;
331 | this.waveCount = 0;
332 |
333 | this.waveInitX = event.layerX*this.ratio;
334 | this.waveInitY = event.layerY*this.ratio;
335 |
336 | }
337 | };
338 |
339 |
340 | GuitarString.prototype.clear = function(){
341 | // clear
342 | // if(this.redrawActive){
343 | // this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
344 | // }
345 | };
346 |
347 | GuitarString.prototype.update = function(){
348 | // console.log(this.redrawActive);
349 | // if(this.redrawActive){
350 | if ( this.userInControl ){
351 | this.thirdPoint = new Point(this.currentMouseX, this.currentMouseY);
352 | }
353 | if ( this.waveInControl ){
354 | var waveX = this.waveInitX;
355 | var waveY = this.startPoint.y +
356 | (this.waveInitY-this.startPoint.y)
357 | *Math.cos(this.waveCount/5*Math.PI)
358 | *Math.pow(this.damping, this.waveCount);
359 |
360 | if ( Math.pow(this.damping, this.waveCount) > 0.03) {
361 | // still waving ....
362 | this.thirdPoint = new Point(waveX, waveY);
363 | this.waveCount++;
364 | } else {
365 | // wave damped to a straight line, wave is finished
366 | this.waveInControl = false;
367 | this.waveFinished = true;
368 | this.lastRedraw = true;
369 | this.thirdPoint = new Point(waveX, waveY);
370 | }
371 | }
372 | // }
373 | }
374 |
375 | GuitarString.prototype.draw = function(){
376 | // if(this.redrawActive){
377 | // draw stuff
378 | // }
379 | if(this.lastRedraw) {
380 | this.drawLine();
381 | this.lastRedraw = false;
382 | this.redrawActive = false;
383 | } else {
384 | this.drawArc(this.startPoint, this.thirdPoint, this.endPoint);
385 | }
386 | };
387 | GuitarString.prototype.drawLine = function(){
388 | // draw a line instead of a flat curve when it stops redraw, pixel-perfect
389 | this.ctx.lineWidth = this.strokeWidth;
390 | this.ctx.strokeStyle = this.strokeColor;
391 | this.ctx.beginPath();
392 | this.ctx.moveTo(this.startPoint.x, this.startPoint.y);
393 | this.ctx.lineTo(this.endPoint.x, this.endPoint.y);
394 | this.ctx.globalCompositeOperation = "source-over";
395 | this.ctx.stroke();
396 | };
397 |
398 |
399 | GuitarString.prototype.drawArc = function(startPoint, thirdPoint, endPoint){
400 | var ctx = this.ctx;
401 | ctx.lineWidth = this.strokeWidth;
402 | ctx.strokeStyle = this.strokeColor;
403 |
404 | var centerObject = circleCenter( new Point(startPoint.x, startPoint.y),
405 | new Point(thirdPoint.x, thirdPoint.y),
406 | new Point(endPoint.x, endPoint.y) );
407 | var centerX = centerObject.x;
408 | var centerY = centerObject.y;
409 | var r = centerObject.r
410 |
411 | var angle = Math.atan2(centerX-startPoint.x, centerY-startPoint.y);
412 | // console.log(centerObject);
413 | if (!angle){
414 | ctx.beginPath();
415 | ctx.moveTo(startPoint.x, startPoint.y);
416 | ctx.lineTo(endPoint.x, endPoint.y);
417 | } else {
418 | if( angle > Math.PI/2) {
419 | ctx.beginPath();
420 | ctx.arc(centerX, centerY, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, true);
421 | } else {
422 | ctx.beginPath();
423 | ctx.arc(centerX, centerY, r, Math.PI * 1.5-angle, Math.PI * 1.5 + angle, false);
424 | }
425 | }
426 | ctx.globalCompositeOperation = "source-over";
427 | ctx.stroke();
428 |
429 | }
430 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | underline.js -- A javascript library that sets out to do one simple job: draw and animate the most perfect and playful text underline
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
64 |
65 |
66 | Live Demo
67 |
68 | Twelfth Night
69 |
70 |
71 | Make me a willow cabin
72 |
73 | at your gate
74 |
75 | And call upon my soul within the house.
76 |
77 | Write loyal cantons of
78 |
79 | contemned love
80 |
81 | And sing them loud
82 |
83 | even in the dead of night.
84 |
85 | Halloo your name
86 |
87 | to the reverberate hills
88 |
89 | And make the babbling gossip of the air
90 |
91 | Cry out “Olivia!”
92 |
93 | Oh,
94 |
95 | you should not rest
96 |
97 | Between the elements of air and earth,
98 |
99 | But you should pity me.
100 |
101 |
102 |
103 |
104 |
105 |
110 |
259 |
269 |
270 |
271 |
--------------------------------------------------------------------------------
/fonts/hack-the-hackpad-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/css/style.css:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 | html, body, div, span, applet, object, iframe,
6 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
7 | a, abbr, acronym, address, big, cite, code,
8 | del, dfn, em, img, ins, kbd, q, s, samp,
9 | small, strike, strong, sub, sup, tt, var,
10 | b, u, i, center,
11 | dl, dt, dd, ol, ul, li,
12 | fieldset, form, label, legend,
13 | table, caption, tbody, tfoot, thead, tr, th, td,
14 | article, aside, canvas, details, embed,
15 | figure, figcaption, footer, header, hgroup,
16 | menu, nav, output, ruby, section, summary,
17 | time, mark, audio, video {
18 | margin: 0;
19 | padding: 0;
20 | border: 0;
21 | font-size: 100%;
22 | font: inherit;
23 | vertical-align: baseline; }
24 |
25 | /* HTML5 display-role reset for older browsers */
26 | article, aside, details, figcaption, figure,
27 | footer, header, hgroup, menu, nav, section {
28 | display: block; }
29 |
30 | body {
31 | line-height: 1; }
32 |
33 | ol, ul {
34 | list-style: none; }
35 |
36 | blockquote, q {
37 | quotes: none; }
38 |
39 | blockquote:before, blockquote:after,
40 | q:before, q:after {
41 | content: '';
42 | content: none; }
43 |
44 | table {
45 | border-collapse: collapse;
46 | border-spacing: 0; }
47 |
48 | @font-face {
49 | font-family: 'EB Garamond SC';
50 | src: url("../fonts/ebgaramond12-sc.eot");
51 | src: url("../fonts/ebgaramond12-sc.eot?#iefix") format("embedded-opentype"), url("../fonts/ebgaramond12-sc.woff2") format("woff2"), url("../fonts/ebgaramond12-sc.woff") format("woff"), url("../fonts/ebgaramond12-sc.ttf") format("truetype"), url("../fonts/ebgaramond12-sc.svg#eb_garamond12_sc_regular") format("svg");
52 | font-weight: normal;
53 | font-style: normal; }
54 | @font-face {
55 | font-family: 'hack-the-hackpad-icon';
56 | src: url("../fonts/hack-the-hackpad-icon.eot?ksq0g9");
57 | src: url("../fonts/hack-the-hackpad-icon.eot?#iefixksq0g9") format("embedded-opentype"), url("../fonts/hack-the-hackpad-icon.woff?ksq0g9") format("woff"), url("../fonts/hack-the-hackpad-icon.ttf?ksq0g9") format("truetype"), url("../fonts/hack-the-hackpad-icon.svg?ksq0g9#hack-the-hackpad-icon") format("svg");
58 | font-weight: normal;
59 | font-style: normal; }
60 | [class^="icon-"]::before, [class*=" icon-"]::before {
61 | font-family: "hack-the-hackpad-icon";
62 | speak: none;
63 | font-style: normal;
64 | font-weight: normal;
65 | font-variant: normal;
66 | text-transform: none;
67 | -webkit-font-smoothing: antialiased;
68 | -moz-osx-font-smoothing: grayscale; }
69 |
70 | ::selection {
71 | background: rgba(205, 220, 57, 0.5); }
72 |
73 | ::-moz-selection {
74 | background: rgba(205, 220, 57, 0.5); }
75 |
76 | input[type=text], textarea {
77 | -webkit-transition: all 0.30s ease-in-out;
78 | -moz-transition: all 0.30s ease-in-out;
79 | -ms-transition: all 0.30s ease-in-out;
80 | -o-transition: all 0.30s ease-in-out;
81 | outline: none;
82 | border: none; }
83 |
84 | input[type=text]:focus, textarea:focus {
85 | box-shadow: inset 0 0 5px rgba(205, 220, 57, 0);
86 | border: 1px solid rgba(205, 220, 57, 0); }
87 |
88 | body {
89 | font-family: "EB Garamond" !important;
90 | font-size: 24px;
91 | line-height: 36px;
92 | color: #212121;
93 | margin: 0;
94 | padding: 0;
95 | -moz-osx-font-smoothing: grayscale;
96 | -webkit-font-smoothing: antialiased;
97 | -moz-osx-font-smoothing: grayscale;
98 | text-rendering: optimizeLegibility;
99 | -moz-font-feature-settings: "kern=1", "liga=1", "dlig=1", "hlig=1";
100 | -moz-font-feature-settings: "kern" on, "liga" on, "dlig" on, "hlig" on;
101 | -webkit-font-feature-settings: "kern","liga","dlig","hlig";
102 | -ms-font-feature-settings: "kern","liga","dlig","hlig";
103 | font-feature-settings: "kern","liga","dlig","hlig"; }
104 |
105 | a {
106 | text-decoration: none;
107 | color: #212121; }
108 |
109 | img {
110 | max-width: 100%; }
111 |
112 | header {
113 | width: 100%;
114 | height: 60px;
115 | border-top: solid 4px #CDDC39;
116 | position: fixed;
117 | top: 0;
118 | background-color: rgba(255, 255, 255, 0.92);
119 | z-index: 1; }
120 | header .logo {
121 | z-index: 2;
122 | position: absolute;
123 | cursor: pointer;
124 | top: 20px;
125 | left: 40px;
126 | overflow: hidden;
127 | width: 264px;
128 | transition: all 0.6s cubic-bezier(0.7, 0, 0.3, 1); }
129 | header .logo #underline, header .logo #js, header .logo #line {
130 | transition: all 0.6s cubic-bezier(0.7, 0, 0.3, 1); }
131 | header .logo #underline {
132 | fill: #212121; }
133 | header .logo #js {
134 | -webkit-transform: translate(0, 0);
135 | transform: translate(0, 0);
136 | fill: #212121; }
137 | header .logo #line {
138 | fill: #212121; }
139 | header .logo:hover {
140 | -webkit-transition-delay: 0.25s;
141 | transition-delay: 0.25s; }
142 | header .logo:hover #underline {
143 | fill: #CDDC39; }
144 | header .logo:hover #js {
145 | fill: #CDDC39; }
146 | header .logo:hover #line {
147 | fill: #CDDC39; }
148 | .collapse header .logo {
149 | width: 45px; }
150 | .collapse header .logo #line {
151 | -webkit-transform: translate(-218.7px, 0);
152 | transform: translate(-218.7px, 0);
153 | fill: #CDDC39; }
154 | .collapse header .logo #underline {
155 | opacity: 0; }
156 | .collapse header .logo #js {
157 | -webkit-transform: translate(-218.7px, 0);
158 | transform: translate(-218.7px, 0);
159 | fill: #CDDC39; }
160 | header .hamburger {
161 | display: none;
162 | width: 64px;
163 | height: 64px;
164 | z-index: 2;
165 | position: absolute;
166 | right: 0;
167 | top: 0;
168 | cursor: pointer;
169 | -webkit-user-select: none;
170 | -moz-user-select: none;
171 | -ms-user-select: none;
172 | -o-user-select: none;
173 | user-select: none; }
174 | header .hamburger i {
175 | display: block;
176 | width: 24px;
177 | height: 3px;
178 | position: absolute;
179 | left: 20px;
180 | top: 28px;
181 | background-color: #CDDC39;
182 | transition: all 0.4s ease; }
183 | header .hamburger i::before {
184 | content: '';
185 | display: block;
186 | width: 24px;
187 | height: 3px;
188 | position: absolute;
189 | left: 0px;
190 | top: -8px;
191 | background-color: #CDDC39;
192 | transition: all 0.4s ease; }
193 | header .hamburger i::after {
194 | content: '';
195 | display: block;
196 | width: 24px;
197 | height: 3px;
198 | position: absolute;
199 | left: 0px;
200 | top: 8px;
201 | background-color: #CDDC39;
202 | transition: all 0.4s ease; }
203 | header .menu {
204 | font-weight: 300;
205 | font-size: 24px;
206 | line-height: 60px;
207 | position: absolute;
208 | top: 2px;
209 | right: 40px;
210 | height: 60px; }
211 | header .menu a {
212 | font-family: "Fira Sans";
213 | position: relative;
214 | display: inline-block;
215 | margin-left: 30px;
216 | padding-left: 28px;
217 | color: #212121;
218 | transition: color 0.4s; }
219 | header .menu a::before {
220 | transition: color 0.4s;
221 | font-family: "hack-the-hackpad-icon";
222 | font-style: normal;
223 | position: absolute;
224 | width: 20px;
225 | text-align: right;
226 | left: 0px;
227 | font-size: 24px;
228 | color: #212121; }
229 | header .menu a:hover {
230 | color: #CDDC39; }
231 | header .menu a:hover::before {
232 | color: #CDDC39; }
233 | header .menu .icon-edit {
234 | display: inline-block; }
235 | header .menu .icon-question {
236 | display: none; }
237 | header .menu .icon-github::before {
238 | content: '\e60b';
239 | top: -2px; }
240 | header .menu .icon-edit::before {
241 | content: '\e611';
242 | top: -2px; }
243 | header .menu .icon-question::before {
244 | content: '\e612';
245 | top: -2px; }
246 |
247 | .trigger {
248 | width: 100%;
249 | height: 40px;
250 | position: fixed;
251 | bottom: 20px;
252 | cursor: pointer;
253 | z-index: 3;
254 | transition: all 0.4s ease;
255 | -webkit-transition-delay: 0.6s;
256 | transition-delay: 0.6s; }
257 | .trigger::before {
258 | content: '';
259 | display: block;
260 | width: 40px;
261 | height: 40px;
262 | margin: 0 auto;
263 | margin-top: -20px;
264 | transition: all 0.4s ease;
265 | border-bottom: solid 1px #212121;
266 | border-right: solid 1px #212121;
267 | -webkit-transform: rotate(45deg);
268 | transform: rotate(45deg); }
269 | .trigger:hover::before {
270 | border-bottom: solid 1px #cddc39;
271 | border-right: solid 1px #cddc39; }
272 |
273 | article {
274 | width: 760px;
275 | margin: 0 auto;
276 | font-size: 24px;
277 | line-height: 36px;
278 | position: relative; }
279 |
280 | footer {
281 | height: 360px;
282 | width: 760px;
283 | margin: 0 auto; }
284 | footer .share {
285 | display: block;
286 | position: relative;
287 | top: 150px;
288 | margin: 0 auto 0 auto;
289 | width: 240px;
290 | height: 1px;
291 | background-color: rgba(33, 33, 33, 0.4);
292 | cursor: pointer; }
293 | footer .share::before {
294 | content: '\e615';
295 | text-align: center;
296 | font-size: 32px;
297 | line-height: 82px;
298 | display: block;
299 | position: absolute;
300 | left: 79px;
301 | top: -40px;
302 | width: 80px;
303 | height: 80px;
304 | border-radius: 100%;
305 | border: solid 1px rgba(33, 33, 33, 0.4);
306 | background-color: white;
307 | transition: all 0.4s ease; }
308 | footer .share:hover::before {
309 | color: #CDDC39; }
310 |
311 | /********** Title ***********/
312 | h1 {
313 | width: 100%;
314 | height: 100vh;
315 | padding-top: 38.2vh;
316 | box-sizing: border-box;
317 | font-family: "Fira Sans";
318 | font-weight: 700;
319 | font-size: 48px;
320 | line-height: 60px;
321 | text-align: center;
322 | margin-bottom: 100px;
323 | position: absolute;
324 | top: 0px; }
325 | h1::after {
326 | display: block;
327 | position: absolute;
328 | width: 240px;
329 | height: 1px;
330 | background-color: rgba(33, 33, 33, 0.4);
331 | margin: 0 auto;
332 | bottom: -1px;
333 | left: 260px; }
334 |
335 | /********** Heading 1 ***********/
336 | h2 {
337 | font-family: "Fira Sans";
338 | font-weight: 500;
339 | color: #212121;
340 | font-size: 32px;
341 | line-height: 40px;
342 | font-weight: 500;
343 | letter-spacing: -0.5px;
344 | padding-top: 40px; }
345 |
346 | /********** Heading 2 ***********/
347 | p.heading2 {
348 | padding: 16px 0; }
349 | p.heading2 strong {
350 | font-family: "Fira Sans";
351 | font-size: 24px;
352 | line-height: 36px;
353 | display: block;
354 | letter-spacing: -0.8px;
355 | text-shadow: none; }
356 |
357 | p {
358 | font-family: "EB Garamond";
359 | margin-top: 24px; }
360 |
361 | p.text a {
362 | font-size: 48px;
363 | line-height: 1.4em;
364 | font-style: italic; }
365 |
366 | p a.title {
367 | font-size: 126px;
368 | line-height: 1.4em; }
369 |
370 | p strong {
371 | font-family: "EB Garamond SC";
372 | text-shadow: 0 0 2px rgba(0, 0, 0, 0.3); }
373 |
374 | p em {
375 | font-style: italic; }
376 |
377 | p:empty {
378 | margin-top: 0px; }
379 |
380 | /* -------------------------- */
381 | /* Push */
382 | /* -------------------------- */
383 | @-webkit-keyframes rotating {
384 | from {
385 | -webkit-transform: rotate(0deg); }
386 | to {
387 | -webkit-transform: rotate(360deg); } }
388 | @media screen and (min-width: 801px) {
389 | body article > * {
390 | -webkit-transition-property: opacity, -webkit-transform;
391 | transition-property: opacity, transform;
392 | -webkit-transition-duration: 1s;
393 | transition-duration: 1s; }
394 | body article > *:not(h1) {
395 | -webkit-transform: translateY(400px);
396 | transform: translateY(400px);
397 | opacity: 0; }
398 | body article h1 {
399 | -webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
400 | transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
401 | -webkit-transition-duration: 1.2s;
402 | transition-duration: 1.2s; }
403 | body article h1 + * {
404 | padding-top: 105px !important;
405 | margin-top: 0px; }
406 | body footer {
407 | -webkit-transition-property: opacity, -webkit-transform;
408 | transition-property: opacity, transform;
409 | -webkit-transition-duration: 1s;
410 | transition-duration: 1s;
411 | -webkit-transform: translateY(400px);
412 | transform: translateY(400px);
413 | opacity: 0; }
414 |
415 | body.collapse .trigger {
416 | -webkit-transition-delay: 0s;
417 | transition-delay: 0s;
418 | -webkit-transform: translateY(150%) scale(0.9);
419 | transform: translateY(150%) scale(0.9);
420 | opacity: 0;
421 | z-index: -1; }
422 | body.collapse article > *:not(h1) {
423 | -webkit-transform: translateY(0);
424 | transform: translateY(0);
425 | opacity: 1; }
426 | body.collapse article h1 {
427 | opacity: 0;
428 | -webkit-transform: translateY(-100%) scale(0.9);
429 | transform: translateY(-100%) scale(0.9); }
430 | body.collapse article *:not(h1) {
431 | -webkit-transition-delay: 0.98s;
432 | transition-delay: 0.98s; }
433 | body.collapse article > *:not(h1):nth-child(8) {
434 | -webkit-transition-delay: 0.5s;
435 | transition-delay: 0.5s; }
436 | body.collapse article > *:nth-child(9) {
437 | -webkit-transition-delay: 0.62s;
438 | transition-delay: 0.62s; }
439 | body.collapse article > *:nth-child(10) {
440 | -webkit-transition-delay: 0.74s;
441 | transition-delay: 0.74s; }
442 | body.collapse article > *:nth-child(11) {
443 | -webkit-transition-delay: 0.86s;
444 | transition-delay: 0.86s; }
445 | body.collapse footer {
446 | -webkit-transform: translateY(0);
447 | transform: translateY(0);
448 | opacity: 1;
449 | -webkit-transition-delay: 0.8s;
450 | transition-delay: 0.8s; } }
451 | /* Smartphones (portrait and landscape) ----------- */
452 | @media screen and (min-width: 320px) and (max-width: 800px) {
453 | body {
454 | font-size: 20px;
455 | line-height: 28px;
456 | /********** Title ***********/
457 | /********** Heading 1 ***********/
458 | /********** Heading 2 ***********/ }
459 | body header {
460 | width: 100%;
461 | height: 90px;
462 | border-top: solid 3px #CDDC39;
463 | border-bottom: none;
464 | position: relative;
465 | z-index: 1; }
466 | body header .logo {
467 | width: 60px;
468 | left: 20px;
469 | top: 6px; }
470 | body header .logo #underline {
471 | opacity: 0; }
472 | body header .logo #js {
473 | -webkit-transform: translate(-218.7px, 0);
474 | transform: translate(-218.7px, 0);
475 | fill: #CDDC39; }
476 | body header .logo #line {
477 | -webkit-transform: translate(-218.7px, 0);
478 | transform: translate(-218.7px, 0);
479 | fill: #CDDC39; }
480 | body header .logo:hover #js, body header .logo:hover #line {
481 | fill: #212121; }
482 | body header .hamburger {
483 | display: none; }
484 | body header .menu {
485 | display: block;
486 | right: 20px; }
487 | body header .menu a {
488 | width: 0px;
489 | overflow: hidden;
490 | padding-left: 32px; }
491 | body header .menu a::before {
492 | font-size: 32px; }
493 | body header.mobile-menu-open {
494 | height: 100%;
495 | height: 100%;
496 | position: fixed;
497 | top: 0px;
498 | left: 0px;
499 | right: 0px;
500 | bottom: 0px; }
501 | body header.mobile-menu-open .hamburger i {
502 | width: 0px; }
503 | body header.mobile-menu-open .hamburger i::before {
504 | top: 0;
505 | -webkit-transform: rotate(45deg);
506 | transform: rotate(45deg); }
507 | body header.mobile-menu-open .hamburger i::after {
508 | top: 0;
509 | -webkit-transform: rotate(-45deg);
510 | transform: rotate(-45deg); }
511 | body header.mobile-menu-open .menu {
512 | display: block;
513 | opacity: 1;
514 | position: absolute;
515 | width: 100%;
516 | height: 100%;
517 | box-sizing: border-box;
518 | left: 0px;
519 | top: 0px;
520 | padding-top: 28vh;
521 | background-color: rgba(255, 255, 255, 0.5);
522 | z-index: 1; }
523 | body header.mobile-menu-open .menu a {
524 | font-size: 28px;
525 | line-height: 100px;
526 | position: relative;
527 | display: block;
528 | margin-left: 0px;
529 | padding-left: 70px;
530 | transition: background-color 0.4s; }
531 | body header.mobile-menu-open .menu a::before {
532 | position: absolute;
533 | left: 20px;
534 | width: 30px;
535 | text-align: center;
536 | font-size: 30px;
537 | line-height: 100px;
538 | transition: none; }
539 | body header.mobile-menu-open .menu .icon-edit {
540 | display: block; }
541 | body header.mobile-menu-open .menu .icon-question {
542 | display: none; }
543 | body header.mobile-menu-open .menu a:hover,
544 | body header.mobile-menu-open .menu a:active {
545 | background-color: #CDDC39;
546 | color: white; }
547 | body header.mobile-menu-open .menu a:hover::before,
548 | body header.mobile-menu-open .menu a:active::before {
549 | color: white; }
550 | body header.mobile-menu-open .menu .icon-github::before {
551 | top: -2px; }
552 | body header.mobile-menu-open .menu .icon-edit::before {
553 | top: -2px; }
554 | body header.mobile-menu-open ~ article {
555 | margin-top: 93px; }
556 | body .trigger {
557 | opacity: 0;
558 | -webkit-transition-delay: 0s;
559 | transition-delay: 0s;
560 | -webkit-transform: translateY(-100%) scale(0.9);
561 | transform: translateY(-100%) scale(0.9);
562 | z-index: -1; }
563 | body article {
564 | padding: 0 20px;
565 | width: 100%;
566 | box-sizing: border-box; }
567 | body footer {
568 | height: 240px;
569 | width: 100%; }
570 | body footer .share {
571 | width: 160px;
572 | top: 120px; }
573 | body footer .share::before {
574 | font-size: 24px;
575 | line-height: 62px;
576 | left: 49px;
577 | top: -30px;
578 | width: 60px;
579 | height: 60px; }
580 | body h1 {
581 | font-size: 28px;
582 | line-height: 36px;
583 | height: auto;
584 | text-align: left;
585 | position: relative;
586 | padding: 24px 0;
587 | margin-bottom: 0px;
588 | border-bottom: solid 1px rgba(33, 33, 33, 0.4); }
589 | body h1::after {
590 | display: none; }
591 | body h2 {
592 | font-size: 24px;
593 | line-height: 36px;
594 | font-weight: 500;
595 | padding-top: 40px; }
596 | body h1 + * {
597 | padding-top: 24px !important;
598 | margin-top: 0px; }
599 | body p.heading2 {
600 | padding: 12px 0; }
601 | body p.heading2 strong {
602 | font-weight: 700;
603 | font-size: 20px;
604 | line-height: 28px;
605 | letter-spacing: 0px; }
606 | body p {
607 | font-size: 20px;
608 | line-height: 28px; }
609 | body p.text a {
610 | font-size: 32px;
611 | line-height: 1.4em; }
612 | body p a.title {
613 | font-size: 48px;
614 | line-height: 1.4em; }
615 | body p strong {
616 | font-family: "EB Garamond SC";
617 | text-shadow: 0 0 1px rgba(0, 0, 0, 0.2); } }
618 | /* iPads (portrait) ----------- */
619 | @media only screen and (min-width: 801px) and (max-width: 960px) {
620 | body header .menu {
621 | right: 20px; }
622 | body header .logo {
623 | left: 20px; }
624 | body ul.comment {
625 | width: 100%;
626 | margin: 40px 0 40px 0;
627 | padding: 40px 0px; }
628 | body ul.comment::before {
629 | width: 120px;
630 | height: 24px; }
631 | body ul.comment::after {
632 | width: 120px;
633 | height: 24px; } }
634 | @media only screen and (min-device-width: 768px) and (max-device-width: 1024px) and (orientation: landscape) {
635 | .collapse header .logo #ackpad {
636 | -webkit-transform: translate(0, 0);
637 | transform: translate(0, 0);
638 | opacity: 0; } }
639 |
640 | /*# sourceMappingURL=style.css.map */
641 |
--------------------------------------------------------------------------------