A Pen by Matthew Daniel Brown on CodePen.
Created
January 2, 2019 05:21
-
-
Save matt-daniel-brown/2a0a6b1803c54547102af99645f7936f to your computer and use it in GitHub Desktop.
Pressure Sensitive Dot Matrix in CSS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| - var blocksPerRow= 8 | |
| - var numBlocks= blocksPerRow*blocksPerRow | |
| body(ontouchstart="") | |
| .mouse | |
| .circle | |
| section | |
| .wrapper | |
| - for (var i= 0; i < numBlocks; i++) | |
| div.selector | |
| - for (var i= 0; i < numBlocks; i++) | |
| span.visible | |
| .el(data-delay=Math.ceil(Math.random()*10)) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @import "breakpoint"; | |
| @import "modularscale@3.*"; | |
| @import "bourbon@5.*"; | |
| $blocksPerRow: 8; | |
| $numBlocks: $blocksPerRow*$blocksPerRow; | |
| $marginCalc: 3%; | |
| $dimensions: 100/$blocksPerRow *1%; | |
| $transEase: cubic-bezier(.5, -0.5, .5, 1.5); | |
| $transEase: ease-in-out; | |
| $pulseDur: 2; | |
| .custom-cursor * { | |
| cursor: none; | |
| -webkit-touch-callout: none; /* iOS Safari */ | |
| -webkit-user-select: none; /* Safari */ | |
| -khtml-user-select: none; /* Konqueror HTML */ | |
| -moz-user-select: none; /* Firefox */ | |
| -ms-user-select: none; /* Internet Explorer/Edge */ | |
| user-select: none; /* Non-prefixed version, currently | |
| supported by Chrome and Opera */ | |
| } | |
| @mixin flexCode() { | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| } | |
| html, body { | |
| background: darken(blue, 45%); | |
| } | |
| section { | |
| width: 100vw; | |
| height: 100vh; | |
| perspective: 1000px; | |
| transform-style: preserve-3d; | |
| @include flexCode(); | |
| } | |
| .wrapper { | |
| $size: 65vmin; | |
| width: $size; | |
| height: $size; | |
| position: relative; | |
| transform-style: preserve-3d; | |
| flex-wrap: wrap; | |
| transform: rotateX(60deg); | |
| // transition: transform .5s ease-out; | |
| will-change: transform; | |
| @include flexCode(); | |
| } | |
| span, | |
| div { | |
| $dimensions: 100/$blocksPerRow *1%; | |
| width: $dimensions; | |
| height: $dimensions; | |
| // margin: $marginCalc; | |
| display: block; | |
| // border-radius: 50% 50%; | |
| position: relative; | |
| z-index: 99999; | |
| } | |
| $trans-position: translateY( $blocksPerRow * -100%); | |
| span.visible { | |
| transform: $trans-position; | |
| position: relative; | |
| z-index: 1; | |
| transform-style: preserve-3d; | |
| @include flexCode(); | |
| .el { | |
| $size: 15%; | |
| width: $size; | |
| height: $size; | |
| border-radius: 50% 50%; | |
| transition: transform .4s $transEase; | |
| will-change: transform; | |
| } | |
| @for $i from 1 through $numBlocks { | |
| &:nth-of-type(#{$i}) .el { | |
| background: mix(cyan, blue, 100/$numBlocks*$i); | |
| } | |
| } | |
| @for $i from 1 through 10 { | |
| & .el[data-delay='#{$i}'] { | |
| animation: animateIn 1.2s ease-out; | |
| animation-delay: $i*.12s; | |
| animation-fill-mode: backwards; | |
| } | |
| } | |
| } | |
| div.selector { | |
| @for $i from 1 through $numBlocks { | |
| &:active:nth-of-type(#{$i}) { | |
| $outerLayer: .5, .75, 1; | |
| $midLayer: 1.5, 2; | |
| $centerLayer: 2.5; | |
| $trans-amt: -30px; | |
| //center | |
| & ~ span.visible:nth-of-type(#{$i}) .el { | |
| transform: translateZ($trans-amt*$centerLayer); | |
| } | |
| //make sure theres not a split depression on the left side when pressing a 10th dot | |
| @if $i % $blocksPerRow !=0 { | |
| //right | |
| & ~ span.visible:nth-of-type(#{$i + 1}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 2)); | |
| } | |
| //midLayer - above right | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow + 1}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 1)); | |
| } | |
| //midLayer - below right | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow + 1}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 1)); | |
| } | |
| //outerLayer - above right mid | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow*2 + 1}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| //outerLayer - below mid right | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow*2 + 1}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| //make sure theres not a split depression on left side when pressing a 9th dot | |
| @if ($i + 1) % $blocksPerRow !=0 { | |
| //outerLayer - mid right mid | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow + 2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| //outerLayer - mid right | |
| & ~ span.visible:nth-of-type(#{$i + 2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 3)); | |
| } | |
| //outerLayer - below mid right | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow + 2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| } | |
| } | |
| //make sure theres not a split depression on left side when pressing a 1st dot | |
| @if ($i - 1) % $blocksPerRow !=0 { | |
| //left | |
| & ~ span.visible:nth-of-type(#{$i - 1}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 2)); | |
| } | |
| //midLayer - above left | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow - 1}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 1)); | |
| } | |
| //midLayer - below left | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow - 1}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 1)); | |
| } | |
| //outerLayer - above left mid | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow*2 - 1}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| //outerLayer - below mid left | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow*2 - 1}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| //make sure theres not a split depression on left side when pressing a 2nd dot | |
| @if ($i - 2) % $blocksPerRow !=0 { | |
| //outerLayer - mid left mid | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow - 2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| //outerLayer - mid left | |
| & ~ span.visible:nth-of-type(#{$i - 2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 3)); | |
| } | |
| //outerLayer - below mid left | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow - 2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 2)); | |
| } | |
| } | |
| } | |
| //midLayer - above mid | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 2)); | |
| } | |
| //midLayer - below mid | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow}) .el { | |
| transform: translateZ($trans-amt*nth($midLayer, 2)); | |
| } | |
| //outerLayer - above mid | |
| & ~ span.visible:nth-of-type(#{$i - $blocksPerRow*2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 3)); | |
| } | |
| //outerLayer - below mid mid | |
| & ~ span.visible:nth-of-type(#{$i + $blocksPerRow*2}) .el { | |
| transform: translateZ($trans-amt*nth($outerLayer, 3)); | |
| } | |
| } | |
| } | |
| } | |
| @keyframes animateIn { | |
| 0% {opacity: 0; transform: translateZ(-100px);} | |
| 50% {opacity: .2} | |
| 100% {opacity: 1; transform: translateZ(0px);} | |
| } | |
| .mouse { | |
| visibility: hidden; | |
| position: fixed; | |
| pointer-events: none; | |
| width: 50px; | |
| height: 50px; | |
| animation: showMouse .75s ease-in-out; | |
| animation-delay: 3s; | |
| animation-fill-mode: both; | |
| .circle { | |
| width: 40px; | |
| height: 40px; | |
| background: radial-gradient(circle at 50% -10%, rgba(255,255,255,1) 0%, rgba(255,255,255,0.4) 100%); | |
| border-radius: 100%; | |
| transition: all .2s ease-in-out; | |
| pointer-events: none; | |
| opacity: .3; | |
| } | |
| &.active .circle { | |
| opacity: .2; | |
| transform: scale(.9); | |
| } | |
| } | |
| .custom-cursor .mouse { | |
| visibility: visible; | |
| } | |
| @keyframes showMouse { | |
| 0% {opacity: 0} | |
| 100% {opacity: 1} | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment