Skip to content

Instantly share code, notes, and snippets.

@amirnaeem
Created September 21, 2014 16:54
Show Gist options
  • Save amirnaeem/59518d51e1d0f387d8a8 to your computer and use it in GitHub Desktop.
Save amirnaeem/59518d51e1d0f387d8a8 to your computer and use it in GitHub Desktop.
A Pen by Rachel Smith.

CSS Shapes experiment (webkit only)

** Please refresh if you resize :) I may update to auto resize soon. **

I wanted to do something with CSS shapes so here it is. If you don't know what CSS Shapes are about then check out http://alistapart.com/article/css-shapes-101. There is little browser support for shapes right now so this is a Chrome/Safari only demo.

This layout/interaction was very heavily inspired cough cough by this site http://www.mcdonalds.co.uk/ukhome/testing/favourites-awards.html which was built by talented folks at http://www.goodboydigital.com/. Their implementation is in Canvas which is BY ALL MEANS the way to go for this sort of thing in production. I just wanted to give a glimpse in to the possibility of a future where we can literally bend DOM elements to our Will with CSS (also, I am a crazy person, clearly).

A Pen by Rachel Smith on CodePen.

License.

/* Some of this code is a little repetitive as I just typed it out as it was forming in my brain. Could definitely use some refactoring for length/neatness I couldn't be bothered right now ¯\_(ツ)_/¯ */
(function() {
// vars
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var size = Math.ceil(windowWidth/6);
var points = [];
var squares = [];
var nPoints = 7*(Math.ceil(windowHeight/size)+1);
var nSquares = 6*Math.ceil(windowHeight/size);
var x = 0, y = 0;
function init() {
// set up the points
for(var i = 0; i <= nPoints; i++) {
var p = new Point(x,y);
console.log(i);
if((i+1)%7 == 0) {
x = 0;
y = y + size;
} else {
x = x + size;
}
points.push(p);
}
// set up the squares
for(var i = 0, p=0; i < nSquares; i++, p++) {
var sPoints = [
points[p], points[p+1], points[p+7+1], points[p+7],
];
var s = new Square(sPoints, i);
squares.push(s);
if((i+1)%6 == 0) {
p++;
}
}
// let the fun begin
animate();
}
function animate() {
for(var i = 0; i < squares.length; i++) {
squares[i].update(i);
}
requestAnimationFrame(animate);
}
// Points & Squares
function Point(x,y) {
this.x = x;
this.y = y;
this.originX = x;
this.originY = y;
}
function Square(ps, color) {
var _this = this;
// init
this.points = ps;
this.color = color;
this.lightening = 50;
this.offset = {
x: _this.points[0].x,
y: _this.points[0].y
};
createDiv();
function createDiv() {
_this.p1 = {
x : (_this.points[0].x-_this.offset.x)+size*0.4,
y : (_this.points[0].y-_this.offset.y)+size*0.4
};
_this.p2 = {
x: (_this.points[1].x-_this.offset.x)+size*0.4,
y: (_this.points[1].y-_this.offset.y)+size*0.4,
};
_this.p3 = {
x: (_this.points[2].x-_this.offset.x)+size*0.4,
y: (_this.points[2].y-_this.offset.y)+size*0.4,
};
_this.p4 = {
x: (_this.points[3].x-_this.offset.x)+size*0.4,
y: (_this.points[3].y-_this.offset.y)+size*0.4,
};
var shapeString = 'polygon('+_this.p1.x+'px '+_this.p1.y+'px, '+
_this.p2.x+'px '+_this.p2.y+'px, '+
_this.p3.x+'px '+_this.p3.y+'px, '+
_this.p4.x+'px '+_this.p4.y+'px)';
_this.div = document.createElement('div');
document.body.appendChild(_this.div);
_this.div.style.width = size*1.8+'px';
_this.div.style.height = size*1.8+'px';
_this.div.style.backgroundColor = 'hsla('+Math.floor(_this.color*20)+',50%,'+_this.lightening+'%,1)';
_this.div.style.shapeInside = shapeString;
_this.div.style.webkitClipPath = shapeString;
_this.div.style.webkitTransform = 'translate('+(_this.offset.x-size*0.4)+'px, '+(_this.offset.y-size*0.4)+'px)';
_this.div.object = _this;
_this.div.addEventListener('mouseover', mouseover);
_this.div.addEventListener('mouseover', mouseout);
}
function mouseover(e) {
if(e.target.object.active) return;
e.target.object.active = true;
for(var i = 0; i < points.length; i++) {
if(points[i] != e.target.object.points[0] ||
points[i] != e.target.object.points[1] ||
points[i] != e.target.object.points[2] ||
points[i] != e.target.object.points[3]) {
TweenLite.to(points[i], 0.8, {x: points[i].originX, y: points[i].originY, ease: Elastic.easeOut});
}
}
TweenLite.to(e.target.object, 0.4, {lightening: 85, ease: Sine.easeOut});
TweenLite.to(e.target.object.points[0], 0.8, {x: e.target.object.points[0].originX + Math.random()*size*-0.15, y: e.target.object.points[0].originY + Math.random()*size*-0.15, ease: Elastic.easeOut});
TweenLite.to(e.target.object.points[1], 0.8, {x: e.target.object.points[1].originX + Math.random()*size*0.15, y: e.target.object.points[1].originY + Math.random()*size*-0.15, ease: Elastic.easeOut});
TweenLite.to(e.target.object.points[2], 0.8, {x: e.target.object.points[2].originX + Math.random()*size*0.15, y: e.target.object.points[2].originY + Math.random()*size*0.15, ease: Elastic.easeOut});
TweenLite.to(e.target.object.points[3], 0.8, {x: e.target.object.points[3].originX + Math.random()*size*-0.15, y: e.target.object.points[3].originY + Math.random()*size*0.15, ease: Elastic.easeOut});
}
function mouseout(e) {
e.target.object.active = false;
TweenLite.to(e.target.object, 0.8, {lightening: 50, ease: Elastic.easeOut});
}
this.update = function(i) {
_this.p1.x = (_this.points[0].x-_this.offset.x)+size*0.4;
_this.p1.y = (_this.points[0].y-_this.offset.y)+size*0.4;
_this.p2.x = (_this.points[1].x-_this.offset.x)+size*0.4;
_this.p2.y = (_this.points[1].y-_this.offset.y)+size*0.4;
_this.p3.x = (_this.points[2].x-_this.offset.x)+size*0.4;
_this.p3.y = (_this.points[2].y-_this.offset.y)+size*0.4;
_this.p4.x = (_this.points[3].x-_this.offset.x)+size*0.4;
_this.p4.y = (_this.points[3].y-_this.offset.y)+size*0.4;
var shapeString = 'polygon('+_this.p1.x+'px '+_this.p1.y+'px, '+
_this.p2.x+'px '+_this.p2.y+'px, '+
_this.p3.x+'px '+_this.p3.y+'px, '+
_this.p4.x+'px '+_this.p4.y+'px)';
_this.div.style.shapeInside = shapeString;
_this.div.style.webkitClipPath = shapeString;
_this.div.style.backgroundColor = 'hsla('+Math.floor(_this.color*20)+',50%,'+_this.lightening+'%,1)';
};
}
init();
})();
/**
HEY! WTF?! YOU SAID THIS WAS CSS SHAPES. WHERE IS THE CSS???
Rest easy my friend, this demo is definitely using CSS, it is just being applied with JavaScript, there is quite a bit of layout logic going on here that I believe can't achieved with a CSS only implementation - but feel free to give it a shot :)
**/
* {
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
html, body {
margin: 0; padding: 0;
}
body {
overflow: hidden;
}
div {
position: absolute;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment