Skip to content

Commit

Permalink
Add distortion grid
Browse files Browse the repository at this point in the history
  • Loading branch information
mihaip committed Dec 31, 2012
1 parent 00b99e3 commit 827c84d
Show file tree
Hide file tree
Showing 14 changed files with 3,431 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Various prototypes, experiments and proofs of concept that have appeared on [per
* [Demo](http://persistent.info/web-experiments/sensors/)
* [Source](https://github.com/mihaip/web-experiments/tree/master/sensors)
* [Blog post](http://blog.persistent.info/2010/12/visualizing-deviceorientation-events.html)
* Distortion grid using CSS 3D transforms - _November 2010_
* [Demo](http://persistent.info/web-experiments/distortion/)
* [Source](https://github.com/mihaip/web-experiments/tree/master/distortion)
* [Blog post](http://blog.persistent.info/2010/11/distortion-grid-using-css-3d-transforms.html)
* Rendering text in `<canvas>` via font textures - _Feburary 2006_
* [Demo](http://persistent.info/web-experiments/canvas-text/)
* [Source](https://github.com/mihaip/web-experiments/tree/master/canvas-text)
Expand Down
3 changes: 3 additions & 0 deletions distortion/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Distortion grid using CSS 3D transforms

Created in November of 2010. For more details, see [this blog post](http://blog.persistent.info/2010/11/distortion-grid-using-css-3d-transforms.html).
26 changes: 26 additions & 0 deletions distortion/TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
TODO

DONE
- image datasource
- scale points modifier (shift? and use option for decay?)
- grid checkbox
- point checkbox
- make tile size selectable
- prevent convex quads
- gradient as background?
- only recompute matrices that actually need it
- url datasource
- video datasrouce
- "overscan" to avoid seams
- catch click events (for url datasource?)
- help bubble to mention option and shift modifier
- permalinks for datasources
- ipad support
- make datasources cacheable
- warning when missing WebKitCSSMatrix and/or 3d transforms

LATER
- shapshots that can be restored (with transitions)
- permalinks for distortions
- prevent scrolling when dragging points down
- basic Firefox 4.0 support
170 changes: 170 additions & 0 deletions distortion/datasources.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
function Datasource(width, height) {
this.width = width;
this.height = height;
}

Datasource.prototype = {
fillTile: function(tile) {
throw Error('Datasource implementations must implement fillTile');
},

start: function() {},
stop: function() {}
};

function CheckerboardDatasource(width, height) {
Datasource.call(this, width, height);
}

CheckerboardDatasource.prototype = {
__proto__: Datasource.prototype,
fillTile: function(tile) {
tile.node.style.backgroundColor =
(tile.xIndex % 2 + tile.yIndex) % 2 ? 'blue' : 'yellow';
}
};

function ImageDatasource(url, width, height) {
Datasource.call(this, width, height);
this.url_ = url;
}

ImageDatasource.prototype = {
__proto__: Datasource.prototype,
start: function() {
if (!this.image_) {
this.image_ = new Image();
this.image_.onload = this.onload_.bind(this);
this.image_.src = this.url_;
}
},

onload_: function() {
this.isLoaded_ = true;
},

fillTile: function(tile) {
if (!this.isLoaded_) {
setTimeout(this.fillTile.bind(this, tile), 50);
return;
}

var height = tile.height;
if (tile.y + height > this.height) {
height = this.height - tile.y;
}
var width = tile.width;
if (tile.x + width > this.width) {
width = this.width - tile.x;
}

var tileCanvas = document.createElement('canvas');
tileCanvas.width = width;
tileCanvas.height = height;
var tileContext = tileCanvas.getContext('2d');

tileContext.drawImage(
this.image_,
tile.x, tile.y, width, height,
0, 0, width, height);

// When running locally Chrome considers the file:/// URL that the image was
// read from to be a separate origin, so we instead just use the tile canvas
// in the tile.
try {
tile.node.style.backgroundImage = 'url(' + tileCanvas.toDataURL() + ')';
} catch (err) {
tile.node.appendChild(tileCanvas);
}
}
};

function IframeDatasource(url, width, height) {
Datasource.call(this, width, height);

this.iframe_ = document.createElement('iframe');
this.iframe_.width = width;
this.iframe_.height = height;
this.iframe_.src = url;
this.iframe_.sandbox = '';
this.iframe_.style.overflow = 'hidden';
this.iframe_.style.position = 'absolute';
}

IframeDatasource.prototype = {
__proto__: Datasource.prototype,
fillTile : function(tile) {
var tileIframe = this.iframe_.cloneNode(false);
tileIframe.style.top = -tile.y + 'px';
tileIframe.style.left = -tile.x + 'px';
tile.node.style.overflow = 'hidden';
tile.node.appendChild(tileIframe);

// Add a "cover" to prevent the iframe from stealing mouse events (setting
// -webkit-mouse-events: none on it does not help).
var cover = document.createElement('div');
cover.className = 'cover';
tile.node.appendChild(cover);
}
};

function VideoDatasource(url, width, height) {
Datasource.call(this, width, height);
this.url_ = url;
}

VideoDatasource.prototype = {
__proto__: Datasource.prototype,
start: function() {
if (!this.video_) {
this.video_ = document.createElement('video');
this.video_.src = this.url_;
this.video_.width = this.width;
this.video_.height = this.height;
this.video_.autoplay = false;
this.video_.loop = true;

this.frameCanvas_ = document.createElement('canvas');
this.frameCanvas_.width = this.width;
this.frameCanvas_.height = this.height;
}

this.video_.play();
this.frameInterval_ = setInterval(this.updateTiles_.bind(this), 30);
this.tiles_ = [];
},

stop: function() {
this.video_.pause();
clearInterval(this.frameInterval_);
},

fillTile: function(tile) {
this.tiles_.push(tile);
var tileCanvas = document.createElement('canvas');
tileCanvas.width = tile.width;
tileCanvas.height = tile.height;
tile.node.appendChild(tileCanvas);
},

updateTiles_: function() {
this.frameCanvas_.getContext('2d').drawImage(this.video_, 0, 0);
this.tiles_.forEach(function(tile) {
var tileCanvas = tile.node.lastChild;
var tileContext = tileCanvas.getContext('2d');
var height = tile.height;
if (tile.y + height > this.height) {
height = this.height - tile.y;
}
var width = tile.width;
if (tile.x + width > this.width) {
width = this.width - tile.x;
}

tileContext.drawImage(
this.frameCanvas_,
tile.x, tile.y, width, height,
0, 0, width, height);
}, this);
},
};
Loading

0 comments on commit 827c84d

Please sign in to comment.