Forked from: Event's Simple MediaRSS Viewer diff(1028) MediaRSS Viewer with *crazy* transition gct256 Follow 2010-09-14 14:59:47 License: MIT License Fork2 Fav22 View2209 Play Stop Reload Fullscreen Smart Phone Fork tree Readme JavaScript 940 lines HTML 11 lines CSS 90 lines MediaRSS Viewer with *crazy* transition q3dlib / quickie 3d library /* ------------------------------------------------ */ /* configuration */ var FPS = 20; var SIZE = 400; q3d_setDefaultColor('#111', '#000'); q3d_setDepth(4); /* ------------------------------------------------ */ /* utils */ function combine(base, splited) { if (splited == null) return base; var r = /^\s+|\s+$/g; var v = ('' + splited).split(/ +/), s, l, i; for (l = v.length, i = 0; i < l; ++i) if ((s = v[i].replace(r, '')).length > 0) base.push(s); return base; } Array.prototype.shuffle = function() { var i = this.length, j, x; while (i) { j = Math.floor(Math.random() * i); x = this[--i]; this[i] = this[j]; this[j] = x; } return this; }; /* ------------------------------------------------ */ /* easing (0 <= t <= 1) */ var Easing = { linear: function(t) { return t; }, swing: function(t) { return (3 - 2 * t) * t * t; }, up: function(t) { return t * t; }, up3: function(t) { return t * t * t; }, down: function(t) { return 2 * t - t * t; }, down3: function(t) { var t2 = t * t; return t2 * t - 3 * t2 + 3 * t; }, tri: function(t) { return (1 - Math.cos(Math.PI * t)) / 2; }, re: /^(linear|swing|up|up3|down|down3|tri)$/i, select: function(v) { if (v instanceof Function) return v; if ((typeof v == 'string' || v instanceof String) && (Easing.re.test(v))) return Easing[v]; return Easing.swing; } }; /* ------------------------------------------------ */ /* interpolating */ var Interpolating = { linear: function(t, v0, v1) { return v0 * (1 - t) + v1 * t; }, quadratic: function(t, v0, v1, a) { var s = 1 - t; return (s * s * v0 + 2 * t * s * a + t * t * t * v1); }, bezier: function(t, v0, v1, a, b) { var s = 1 - t, t2 = t * 2, s2 = s * s; return (s2 * s * v0 + 3 * s2 * t * a + 3 * s * t2 * b + t2 * v1); }, catmull_rom: function(t, v0, v1, a, b) { var v = (v1 - a) / 2; var w = (b - v0) / 2; var t2 = t * t; return ( 2 * v0 - 2 * v1 + v + w) * t2 * t + (-3 * v0 + 3 * v1 - 2 * v - w) * t2 + v * t + v0; } }; /* ------------------------------------------------ */ /* image list */ var ImageList = function() { this.items = []; this.position = 0; }; q3d_extend(ImageList.prototype, { addFromFlickr: function(tags, count, callback) { var t = this; var url = 'http://api.flickr.com/services/' + 'feeds/photos_public.gne?tags=' + encodeURIComponent(tags) + '&format=rss_200'; var it = ImageList.Item; var gf = google.feeds; var feed = new gf.Feed(url); feed.setNumEntries(count|0); feed.setResultFormat(gf.Feed.MIXED_FORMAT); feed.load(function(result) { if (!result.error) { var entries = result.feed.entries, l, i, item; for (l = entries.length, i = 0; i < l; ++i) { item = it.fromMediaRSS(entries[i].xmlNode); if (item) t.items.push(item); } } callback(); }); }, addFromURLs: function() { var a = arguments, l = a.length, i, item; for (i = 0; i < l; ++i) { item = ImageList.Item.fromURL(a[i]); if (item) this.items.push(item); } }, prev: function() { if (this.position > 0) { --this.position; return true; } return false; }, next: function() { if (this.position < this.items.length - 1) { ++this.position; return true; } return false; }, isFirst: function() { return this.position == 0; }, isLast: function() { return this.position == this.items.length - 1; }, pagination: function() { return (this.position + 1) + '/' + this.items.length; }, getContent: function(callback) { if (this.items.length > 0) this.items[this.position].getContent(callback); else callback(null, 0, 0, null); } }); /* ------------------------------------------------ */ /* Image wrapper */ ImageList.Image = function(url) { this.url = url; this.image = null; }; q3d_extend(ImageList.Image.prototype, { load: function(callback, item) { var img = this.image; if (img && img.complete) { callback(img, img.width, img.height, item); return; } img = this.image = new Image; img.addEventListener('load', function() { callback(img, img.width, img.height, item); }, false); img.addEventListener('error', function() { callback(null, 0, 0, item); }, false); img.src = this.url; } }); /* ------------------------------------------------ */ /* an item of image list */ ImageList.Item = function() { this.content = this.thumbnail = null; this.title = ''; this.credit = {}; this.category = []; }; q3d_extend(ImageList.Item, { fromMediaRSS: function(xmlNode) { var item = new ImageList.Item; var node, i, l, url; var get = google.feeds.getElementsByTagNameNS; var media_rss = 'http://search.yahoo.com/mrss/'; item.content = null; node = get(xmlNode, media_rss, 'content'); if (node.length > 0) { switch (node[0].getAttribute('type')) { case 'image/jpeg': case 'image/gif': // case 'image/png': url = node[0].getAttribute('url'); item.content = new ImageList.Image(url); break; } } item.thumbnail = null; node = get(xmlNode, media_rss, 'thumbnail'); if (node.length > 0) { url = node[0].getAttribute('url'); item.thumbnail = new ImageList.Image(url); } item.title = ''; node = get(xmlNode, media_rss, 'title'); if (node.length > 0) item.title = node[0].textContent; item.credit = {}; node = get(xmlNode, media_rss, 'credit'); for (l = node.length, i = 0; i < l; ++i) item.credit[node[i].getAttribute('role')] = node[i].textContent; item.category = []; node = get(xmlNode, media_rss, 'category'); for (l = node.length, i = 0; i < l; ++i) switch (node[i].getAttribute('scheme')) { case 'urn:flickr:tags': combine(item.category, node[i].textContent); break; } item.format(); return item.content ? item : null; }, fromURL: function(url) { var item = new ImageList.Item; item.content = new ImageList.Image(url); item.format(); return item; } }); q3d_extend(ImageList.Item.prototype, { format: function() { var s = (this.title.length > 0 ? this.title : '(no title)') + '\n', v = []; for (var x in this.credit) v[v.length] = x + ':' + this.credit[x]; s += v.join(' / '); this.formatted = s; }, getContent: function(callback) { if (!this.content) callback(null, 0, 0, this); else this.content.load(callback, this); } }); /* ------------------------------------------------ */ /* camera object */ var Camera = function(ex,ey,ez, ox,oy,oz, ux,uy,uz, zoom) { this.ex = ex; this.ey = ey; this.ez = ez; this.ox = ox; this.oy = oy; this.oz = oz; this.ux = ux; this.uy = uy; this.uz = uz; this.zoom = zoom; }; Camera.blend = function(c0, c1, c2, c3, t) { var c = Interpolating.catmull_rom; return new Camera(c(t, c1.ex, c2.ex, c0.ex, c3.ex), c(t, c1.ey, c2.ey, c0.ey, c3.ey), c(t, c1.ez, c2.ez, c0.ez, c3.ez), c(t, c1.ox, c2.ox, c0.ox, c3.ox), c(t, c1.oy, c2.oy, c0.oy, c3.oy), c(t, c1.oz, c2.oz, c0.oz, c3.oz), c(t, c1.ux, c2.ux, c0.ux, c3.ux), c(t, c1.uy, c2.uy, c0.uy, c3.uy), c(t, c1.uz, c2.uz, c0.uz, c3.uz), c(t, c1.zoom, c2.zoom, c0.zoom, c3.zoom)); }; Camera.prototype.apply = function() { q3d_lookAt(this.ex, this.ey, this.ez, this.ox, this.oy, this.oz, this.ux, this.uy, this.uz); q3d_scale(this.zoom, this.zoom, this.zoom); }; /* ------------------------------------------------ */ /* motion with catmul-rom curve */ var Motion = function() { this.cameras = []; this.frames = this.count = 0; this.easing = Easing.swing; }; q3d_extend(Motion.prototype, { add: function(camera) { this.cameras.push(camera); }, reset: function() { this.frames = this.count = 0; }, begin: function(frames, easing) { this.frames = frames; this.count = 0; this.easing = Easing.select(easing); }, apply: function() { var c = this.cameras, l = c.length; if (this.frames == 0) { if (l > 0) c[0].apply(); else q3d_loadIdentity(); return; } var tf = this.count++ / this.frames; tf = this.easing(tf) * (l - 1); var ti = Math.floor(tf), t = tf - ti; if (ti >= l) { c[l - 1].apply(); return; } Camera.blend(c[ti < 1 ? 0 : ti - 1], c[ti], c[ti > l - 2 ? l - 1 : ti + 1], c[ti > l - 3 ? l - 1 : ti + 2], t). apply(); } }); /* ------------------------------------------------ */ /* 3d model caches */ var Cache = {}; // cube var Cube = function(x,y,z) { this.x = x; this.y = y; this.z = z; this.rx = 0; this.ry = 0; this.rz = 0; this.cube = new q3d_Cuboid(0,0,0, 40,40,40); }; q3d_extend(Cube.prototype, { reset: function() { this.rx = 0; this.ry = 0; this.rz = 0; return this; }, update: function(t) { t *= 3; if (t < 1) this.rx = t * 90; else if (t < 2) this.ry = (t - 1) * 90; else this.rz = (2 - t) * 90; return this; }, put: function() { q3d_pushMatrix(); q3d_translate(this.x, this.y, this.z); q3d_pushMatrix(); q3d_rotateZ(this.rz); q3d_rotateY(this.ry); q3d_rotateX(this.rx); this.cube.put(); q3d_popMatrix(); q3d_popMatrix(); } }); (function() { var g = new q3d_Group, c; for (var x = -120; x <= 120; x += 120) for (var y = -120; y <= 120; y += 120) g.add(new Cube(x,y,0)); var g2 = new q3d_Group; g2.add(new q3d_Patch(-500,-500,0, 500,-500,0, -500, 500,0)); g2.add(new q3d_Patch(-500,-500,0, 500,-500,0, -500, 500,0).culling(1,0)); q3d_cleanup(); q3d_loadIdentity(); g.put(); for (var l = g.length, i = 0; i < l; ++i) { g[i].cube. genUV1(3, 200, 200). genUV1(4, 200, 200). genUV1(5, 200, 200); g[i].rx = g[i].ry = 90; g[i].rz = -90; } q3d_translate(-125,-125,-500); q3d_rotateX(0); g2[0].put().genUV(200, 200); q3d_cleanup(); q3d_loadIdentity(); g.put(); for (i = 0; i < l; ++i) { g[i].cube. genUV1(0, 200, 200). genUV1(1, 200, 200). genUV1(2, 200, 200); g[i].reset(); } q3d_translate(-125,-125,-500); q3d_rotateX(180); g2[1].put().genUV(200, 200); Cache.cube = { group: g, group2: g2 }; })(); // stairs (function() { var g = new q3d_Group; var m = new Motion; var c0 = new Camera( 0,0, 200, 0,0,0, 0,1,0, 1); var c1 = new Camera( 0,0,-200, 0,0,0, -1,0,0, 1); g.add(new q3d_Cuboid(-200,-200,400, 100,100,100, 1)); g.add(new q3d_Cuboid(0,0,0, 100,100,100, 1)); g.add(new q3d_Cuboid(-200,0,200, 100,100,100, 1)); g.add(new q3d_Cuboid(0,-200,200, 100,100,100, 1)); g.add(new q3d_Cuboid(200,-200,0, 100,100,100, 1)); g.add(new q3d_Cuboid(-200,200,0, 100,100,100, 1)); g.add(new q3d_Cuboid(200,0,-200, 100,100,100, 1)); g.add(new q3d_Cuboid(0,200,-200, 100,100,100, 1)); g.add(new q3d_Cuboid(200,200,-400, 100,100,100, 1)); m.add(c0); m.add(new Camera(200,0,0, 0,0,0, 0,1,0, 0.2)); m.add(new Camera(-200,0,0, 0,0,0, 0,1,0, 1)); m.add(new Camera(-200,0,0, 0,0,0, 0,0,1, 0.5)); m.add(c1); q3d_cleanup(); q3d_loadIdentity(); c0.apply(); g.put(); var l = g.length, i; for (i = 0; i < l; ++i) g[i].genUV1(3,200,200). genUV1(4,200,200). genUV1(5,200,200); q3d_cleanup(); q3d_loadIdentity(); c1.apply(); g.put(); for (i = 0; i < l; ++i) g[i].genUV1(0,200,200). genUV1(1,200,200). genUV1(2,200,200); Cache.stairs = { group: g, motion: m }; })(); // pillars (function() { var p0 = new q3d_Group; var p1 = new q3d_Group; var p2 = new q3d_Group; var p3 = new q3d_Group; var p4 = new q3d_Group; var p5 = new q3d_Group; var x0,x1,x2,z0,z1,z2, l, i, m, r = 90; for (i = 0; i < 360; i += 48) { x0 = Math.cos(i * q3d_TO_RADIAN) * r; x1 = Math.cos((i + 48) * q3d_TO_RADIAN) * r; z0 = Math.sin(i * q3d_TO_RADIAN) * r; z1 = Math.sin((i + 48) * q3d_TO_RADIAN) * r; if (i < 180) { p0.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p3.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p4.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); } else { p1.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p2.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p5.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); } } x0 = -100; z0 = 200; x1 = 0; z1 = 0; x2 = 200; z2 = 200; q3d_cleanup(); q3d_loadIdentity(); q3d_loadIdentity(); q3d_translate(x0, 0, z0); p0.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x1, 0, z1); p3.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x2, 0, z2); p4.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x0, 0, z0); q3d_rotateY(180); p1.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x1, 0, z1); q3d_rotateY(180); p2.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x2, 0, z2); q3d_rotateY(180); p5.put().genUV(200,200); Cache.pillars = { p0: p0, p1: p1, p2: p2, p3: p3, p4: p4, p5: p5, x0: x0, x1: x1, x2: x2, z0: z0, z1: z1, z2: z2 }; })(); // board (function() { var f = new q3d_Group, b = new q3d_Group, x = f; var h = 400, c0 = 0, c1 = 1; for (var i = 0; i < 2; ++i) { x.add(new q3d_Patch(-300,-h, 0, -200,-h, 0, -300, h, 0).culling(c0, c1)). add(new q3d_Patch(-250,-h,-100, -150,-h,-100, -250, h,-100).culling(c0, c1)). add(new q3d_Patch(-150,-h, 100, -50,-h, 100, -150, h, 100).culling(c0, c1)). add(new q3d_Patch(-150,-h,-200, -50,-h,-200, -150, h,-200).culling(c0, c1)). add(new q3d_Patch( 100,-h, 200, 200,-h, 200, 100, h, 200).culling(c0, c1)). add(new q3d_Patch(-100,-h,-300, 0,-h,-300, -100, h,-300).culling(c0, c1)). add(new q3d_Patch( 150,-h, 0, 250,-h, 0, 150, h, 0).culling(c0, c1)); x = b; c0 = 1; c1 = 0; } var m = new Motion; c0 = new Camera(0,0,200, 0,0,0, 0,1,0, 1); c1 = new Camera(0,0,-50, 0,0,0, 0,1,0, 1); m.add(c0); m.add(new Camera(100,100,-50, 0,0,0, 0,1,0, 0.4)); m.add(new Camera(0,0,-50, 0,0,0, 0,1,0, 0.4)); m.add(c1); q3d_cleanup(); q3d_loadIdentity(); c0.apply(); f.put(); f.genUV(200,200); q3d_cleanup(); q3d_loadIdentity(); c1.apply(); b.put(); b.genUV(200,200); Cache.board = { front: f, back: b, motion: m }; })(); /* ------------------------------------------------ */ /* transitions */ var Transitions = function() { this.img0 = this.img1 = null; this.frames = this.count = 0; this.callback = function(){}; this.handler = function(){}; this.first = true; }; q3d_extend(Transitions.prototype, { begin: function(img0, img1, frames, easing, reverse, callback, handler, data) { this.img0 = img0; this.img1 = img1; this.frames = frames; this.count = 0; this.easing = Easing.select(easing); this.reverse = reverse; this.callback = callback; this.handler = handler; this.data = data; this.apply(); }, apply: function() { var t = this.easing(this.count++ / this.frames); this.handler(t, 1 - t, this.data); if (this.count <= this.frames) { t = this; setTimeout(function() { t.apply(); }, 1000 / FPS); } else { this.callback(); } }, select: function(img0, img1, frames, easing, reverse, callback) { if (this.first) { this.first = false; this.dissolve(img0, img1, frames, easing, reverse, callback); return; } switch (Math.floor(Math.random() * 4)) { case 0: this.stairs(img0, img1, frames, easing, reverse, callback); break; case 1: this.pillars(img0, img1, frames, easing, reverse, callback); break; case 2: this.board(img0, img1, frames, easing, reverse, callback); break; case 3: this.cube(img0, img1, frames, easing, reverse, callback); break; } }, cube: function(img0, img1, frames, easing, reverse, callback) { var g = Cache.cube.group; for (var l = g.length, i = 0; i < l; ++i) { g[i].reset(); if (img0) g[i].cube. setTexture1(3, img0). setTexture1(4, img0). setTexture1(5, img0); if (img1) g[i].cube. setTexture1(0, img1). setTexture1(1, img1). setTexture1(2, img1); } g = Cache.cube.group2; if (img0) g[0].setTexture(img0); if (img1) g[1].setTexture(img1); this.begin(img0, img1, frames * 3, 'swing', reverse, callback, this._cube, Cache.cube); }, _cube: function(t, s, data) { q3d_cleanup(); q3d_loadIdentity(); var g = data.group, l = g.length, i; for (i = 0; i < l; ++i) data.group[i].update(t).put(); q3d_translate(-125,-125,-500); q3d_rotateX(t * 180); data.group2.put(); q3d_updateCanvas(); }, stairs: function(img0, img1, frames, easing, reverse, callback) { var g = Cache.stairs.group, i, l = g.length; if (img0) { for (i = 0; i < l; ++i) g[i].setTexture1(3, img0). setTexture1(4, img0). setTexture1(5, img0); } if (img1) { for (i = 0; i < l; ++i) g[i].setTexture1(0, img1). setTexture1(1, img1). setTexture1(2, img1); } Cache.stairs.motion.begin(frames * 6, 'linear'); this.begin(img0, img1, frames * 6, easing, reverse, callback, this._stairs, Cache.stairs); }, _stairs: function(t, s, data) { q3d_cleanup(); q3d_loadIdentity(); data.motion.apply(); data.group.put(); q3d_updateCanvas(); }, pillars: function(img0, img1, frames, easing, reverse, callback) { var p = Cache.pillars; if (img0) { p.p0.setTexture(img0); p.p2.setTexture(img0); p.p4.setTexture(img0); } if (img1) { p.p1.setTexture(img1); p.p3.setTexture(img1); p.p5.setTexture(img1); } this.begin(img0, img1, frames * 2, easing, reverse, callback, this._pillars, p); }, _pillars: function(t, s, data) { var v = 2 * t * t - 2 * t + 1; q3d_cleanup(); q3d_loadIdentity(); q3d_translate(data.x0, 0, data.z0); q3d_rotateY(t * 180); q3d_scale(v, v, v); data.p0.put(); data.p1.put(); q3d_loadIdentity(); q3d_translate(data.x1, 0, data.z1); q3d_rotateY(s * 180); q3d_scale(v, v, v); data.p2.put(); data.p3.put(); q3d_loadIdentity(); q3d_translate(data.x2, 0, data.z2); q3d_rotateY(t * 180); q3d_scale(v, v, v); data.p4.put(); data.p5.put(); q3d_updateCanvas(); }, board: function(img0, img1, frames, easing, reverse, callback) { var f = Cache.board.front; var b = Cache.board.back; if (img0) f.setTexture(img0); if (img1) b.setTexture(img1); Cache.board.motion.begin(frames * 4, 'swing'); this.begin(img0, img1, frames * 4, easing, reverse, callback, this._board, Cache.board); }, _board: function(t, s, data) { q3d_cleanup(); q3d_loadIdentity(); data.motion.apply(); data.front.put(); data.back.put(); q3d_updateCanvas(); }, dissolve: function(img0, img1, frames, easing, reverse, callback) { this.begin(img0, img1, frames, easing, reverse, callback, this._dissolve); }, _dissolve: function(t, s) { var cx = q3d_CONTEXT; cx.save(); cx.globalAlpha = s; if (this.img0) cx.drawImage(this.img0, 0, 0); cx.globalAlpha = t; if (this.img1) cx.drawImage(this.img1, 0, 0); cx.restore(); } }); /* ------------------------------------------------ */ /* main */ var MAIN = new ImageList; var TRAN = new Transitions; var PAGE = q3d_element('page'); var INFO = q3d_element('info'); var PREV = q3d_element('prev'); var NEXT = q3d_element('next'); var TAGS = q3d_element('tags'); var MSG = q3d_element('msg'); var LOCK = []; function lock(msg) { LOCK.push(msg); MSG.textContent = LOCK.join(' > '); } function unlock() { LOCK.pop(); MSG.textContent = LOCK.join(' > '); } function isLocked() { return LOCK.length > 0; } function img2canvas(img) { var w = img.width, h = img.height; var cv = document.createElement('CANVAS'); var cx = cv.getContext('2d'); var d = Math.min(1, Math.max(SIZE / w, SIZE / h)); var dw = w * d, dh = h * d; cv.width = cv.height = SIZE; cx.fillStyle = '#000'; cx.fillRect(0, 0, SIZE, SIZE); q3d_drawImage(cx, img, 0, 0, w, h, (SIZE - dw) / 2, (SIZE - dh) / 2, dw, dh); return cv; } function initialize() { PREV.addEventListener('click', function(ev) { prevImage(); ev.preventDefault(); }, false); NEXT.addEventListener('click', function(ev) { nextImage(); ev.preventDefault(); }, false); q3d_bindCanvas('canvas'); q3d_resizeCanvas(SIZE, SIZE); changeTag('kamakura'); } function changeTag(tag) { PAGE.textContent = ''; INFO.textContent = ''; TAGS.textContent = ''; PREV.style.display = 'none'; NEXT.style.display = 'none'; MAIN = new ImageList; lock('load from flickr.com with tag:' + tag); MAIN.addFromFlickr(tag, 50, function() { unlock(); loadImage(); }); } function loadImage() { PAGE.textContent = ''; INFO.textContent = ''; TAGS.textContent = ''; PREV.style.display = 'none'; NEXT.style.display = 'none'; lock('loading image #' + MAIN.position); MAIN.getContent(plotImage); } function plotImage(img, w, h, item) { if (img == null) { unlock(); INFO.textContent = 'image not found.'; return; } var cv = img2canvas(img); TRAN.select(TRAN.img1, cv, FPS, 'swing', false, function() { q3d_CONTEXT.save(); q3d_CONTEXT.setTransform(1,0, 0,1, 0,0); q3d_CONTEXT.drawImage(cv, 0, 0); q3d_CONTEXT.restore(); PAGE.textContent = MAIN.pagination(); INFO.textContent = item.formatted; TAGS.textContent = ''; PREV.style.display = MAIN.isFirst() ? 'none' : 'block'; NEXT.style.display = MAIN.isLast() ? 'none' : 'block'; var e, c = item.category, l = c.length, i; for (i = 0; i < l; ++i) { e = document.createElement('SPAN'); e.textContent = c[i]; e.addEventListener('click', (function(tag) { return function(ev) { changeTag(tag); }; })(c[i]), false); TAGS.appendChild(e); } unlock(); }); } function prevImage() { if (!isLocked() && MAIN.prev()) loadImage(); } function nextImage() { if (!isLocked() && MAIN.next()) loadImage(); } /* ------------------------------------------------ */ /* start ! */ google.load('feeds', '1'); google.setOnLoadCallback(initialize); <script src="http://www.google.com/jsapi?key=ABQIAAAAv7CFgLxkvXPvX2wsDe8U7RTgesIKiW70LgsG7i-NXW8R52TaOBR8U55UVRx4tOOPzns9Z3etYprOww" type="text/javascript"></script> <pre id="page"></pre> <pre id="info"></pre> <canvas id="canvas" width="400" height="400"></canvas> <ul id="nav"> <li id="prev"><</li> <li id="next">></li> </ul> <pre id="tags"></pre> <pre id="msg"></pre> MediaRSS Viewer with *crazy* transition BODY { color:#0f0; overflow:hidden; background:#000; } PRE { margin:0; padding:0; position:absolute; font-size:12px; } #page { left:5px;top:1px; } #info { right:5px;top:1px; text-align:right; } #canvas { position:absolute; left:50%;top:50%; margin:-200px 0 0 -200px; } #nav > LI { list-style:none; position:absolute; display:block; top:50%; width:24px;height:30px; line-height:30px; margin-top:-15px; text-align:center; cursor:pointer; } #nav > LI:hover { background:#0f0; color:#000; } #nav > #prev { left:0; display:none; } #prev:hover { -moz-border-radius-topright:10px; -moz-border-radius-bottomright:10px; -webkit-border-top-right-radius:10px; -webkit-border-bottom-right-radius:10px; border-top-right-radius:10px; border-bottom-right-radius:10px; } #next { right:0; } #next:hover { -moz-border-radius-topleft:10px; -moz-border-radius-bottomleft:10px; -webkit-border-top-left-radius:10px; -webkit-border-bottom-left-radius:10px; border-top-left-radius:10px; border-bottom-left-radius:10px; } #tags { left:5px;bottom:5px; } #tags > SPAN { margin-right:0.5em; padding:0 0.2em; color:#000; background:#0f0; -webkit-border-radius:3px; -moz-border-radius:3px; border-radius:3px; cursor:pointer; } #msg { right:5px;bottom:5px; color:#f00; } /* ------------------------------------------------ */ /* configuration */ var FPS = 20; var SIZE = 400; q3d_setDefaultColor('#111', '#000'); q3d_setDepth(4); /* ------------------------------------------------ */ /* utils */ function combine(base, splited) { if (splited == null) return base; var r = /^\s+|\s+$/g; var v = ('' + splited).split(/ +/), s, l, i; for (l = v.length, i = 0; i < l; ++i) if ((s = v[i].replace(r, '')).length > 0) base.push(s); return base; } Array.prototype.shuffle = function() { var i = this.length, j, x; while (i) { j = Math.floor(Math.random() * i); x = this[--i]; this[i] = this[j]; this[j] = x; } return this; }; /* ------------------------------------------------ */ /* easing (0 <= t <= 1) */ var Easing = { linear: function(t) { return t; }, swing: function(t) { return (3 - 2 * t) * t * t; }, up: function(t) { return t * t; }, up3: function(t) { return t * t * t; }, down: function(t) { return 2 * t - t * t; }, down3: function(t) { var t2 = t * t; return t2 * t - 3 * t2 + 3 * t; }, tri: function(t) { return (1 - Math.cos(Math.PI * t)) / 2; }, re: /^(linear|swing|up|up3|down|down3|tri)$/i, select: function(v) { if (v instanceof Function) return v; if ((typeof v == 'string' || v instanceof String) && (Easing.re.test(v))) return Easing[v]; return Easing.swing; } }; /* ------------------------------------------------ */ /* interpolating */ var Interpolating = { linear: function(t, v0, v1) { return v0 * (1 - t) + v1 * t; }, quadratic: function(t, v0, v1, a) { var s = 1 - t; return (s * s * v0 + 2 * t * s * a + t * t * t * v1); }, bezier: function(t, v0, v1, a, b) { var s = 1 - t, t2 = t * 2, s2 = s * s; return (s2 * s * v0 + 3 * s2 * t * a + 3 * s * t2 * b + t2 * v1); }, catmull_rom: function(t, v0, v1, a, b) { var v = (v1 - a) / 2; var w = (b - v0) / 2; var t2 = t * t; return ( 2 * v0 - 2 * v1 + v + w) * t2 * t + (-3 * v0 + 3 * v1 - 2 * v - w) * t2 + v * t + v0; } }; /* ------------------------------------------------ */ /* image list */ var ImageList = function() { this.items = []; this.position = 0; }; q3d_extend(ImageList.prototype, { addFromFlickr: function(tags, count, callback) { var t = this; var url = 'http://api.flickr.com/services/' + 'feeds/photos_public.gne?tags=' + encodeURIComponent(tags) + '&format=rss_200'; var it = ImageList.Item; var gf = google.feeds; var feed = new gf.Feed(url); feed.setNumEntries(count|0); feed.setResultFormat(gf.Feed.MIXED_FORMAT); feed.load(function(result) { if (!result.error) { var entries = result.feed.entries, l, i, item; for (l = entries.length, i = 0; i < l; ++i) { item = it.fromMediaRSS(entries[i].xmlNode); if (item) t.items.push(item); } } callback(); }); }, addFromURLs: function() { var a = arguments, l = a.length, i, item; for (i = 0; i < l; ++i) { item = ImageList.Item.fromURL(a[i]); if (item) this.items.push(item); } }, prev: function() { if (this.position > 0) { --this.position; return true; } return false; }, next: function() { if (this.position < this.items.length - 1) { ++this.position; return true; } return false; }, isFirst: function() { return this.position == 0; }, isLast: function() { return this.position == this.items.length - 1; }, pagination: function() { return (this.position + 1) + '/' + this.items.length; }, getContent: function(callback) { if (this.items.length > 0) this.items[this.position].getContent(callback); else callback(null, 0, 0, null); } }); /* ------------------------------------------------ */ /* Image wrapper */ ImageList.Image = function(url) { this.url = url; this.image = null; }; q3d_extend(ImageList.Image.prototype, { load: function(callback, item) { var img = this.image; if (img && img.complete) { callback(img, img.width, img.height, item); return; } img = this.image = new Image; img.addEventListener('load', function() { callback(img, img.width, img.height, item); }, false); img.addEventListener('error', function() { callback(null, 0, 0, item); }, false); img.src = this.url; } }); /* ------------------------------------------------ */ /* an item of image list */ ImageList.Item = function() { this.content = this.thumbnail = null; this.title = ''; this.credit = {}; this.category = []; }; q3d_extend(ImageList.Item, { fromMediaRSS: function(xmlNode) { var item = new ImageList.Item; var node, i, l, url; var get = google.feeds.getElementsByTagNameNS; var media_rss = 'http://search.yahoo.com/mrss/'; item.content = null; node = get(xmlNode, media_rss, 'content'); if (node.length > 0) { switch (node[0].getAttribute('type')) { case 'image/jpeg': case 'image/gif': // case 'image/png': url = node[0].getAttribute('url'); item.content = new ImageList.Image(url); break; } } item.thumbnail = null; node = get(xmlNode, media_rss, 'thumbnail'); if (node.length > 0) { url = node[0].getAttribute('url'); item.thumbnail = new ImageList.Image(url); } item.title = ''; node = get(xmlNode, media_rss, 'title'); if (node.length > 0) item.title = node[0].textContent; item.credit = {}; node = get(xmlNode, media_rss, 'credit'); for (l = node.length, i = 0; i < l; ++i) item.credit[node[i].getAttribute('role')] = node[i].textContent; item.category = []; node = get(xmlNode, media_rss, 'category'); for (l = node.length, i = 0; i < l; ++i) switch (node[i].getAttribute('scheme')) { case 'urn:flickr:tags': combine(item.category, node[i].textContent); break; } item.format(); return item.content ? item : null; }, fromURL: function(url) { var item = new ImageList.Item; item.content = new ImageList.Image(url); item.format(); return item; } }); q3d_extend(ImageList.Item.prototype, { format: function() { var s = (this.title.length > 0 ? this.title : '(no title)') + '\n', v = []; for (var x in this.credit) v[v.length] = x + ':' + this.credit[x]; s += v.join(' / '); this.formatted = s; }, getContent: function(callback) { if (!this.content) callback(null, 0, 0, this); else this.content.load(callback, this); } }); /* ------------------------------------------------ */ /* camera object */ var Camera = function(ex,ey,ez, ox,oy,oz, ux,uy,uz, zoom) { this.ex = ex; this.ey = ey; this.ez = ez; this.ox = ox; this.oy = oy; this.oz = oz; this.ux = ux; this.uy = uy; this.uz = uz; this.zoom = zoom; }; Camera.blend = function(c0, c1, c2, c3, t) { var c = Interpolating.catmull_rom; return new Camera(c(t, c1.ex, c2.ex, c0.ex, c3.ex), c(t, c1.ey, c2.ey, c0.ey, c3.ey), c(t, c1.ez, c2.ez, c0.ez, c3.ez), c(t, c1.ox, c2.ox, c0.ox, c3.ox), c(t, c1.oy, c2.oy, c0.oy, c3.oy), c(t, c1.oz, c2.oz, c0.oz, c3.oz), c(t, c1.ux, c2.ux, c0.ux, c3.ux), c(t, c1.uy, c2.uy, c0.uy, c3.uy), c(t, c1.uz, c2.uz, c0.uz, c3.uz), c(t, c1.zoom, c2.zoom, c0.zoom, c3.zoom)); }; Camera.prototype.apply = function() { q3d_lookAt(this.ex, this.ey, this.ez, this.ox, this.oy, this.oz, this.ux, this.uy, this.uz); q3d_scale(this.zoom, this.zoom, this.zoom); }; /* ------------------------------------------------ */ /* motion with catmul-rom curve */ var Motion = function() { this.cameras = []; this.frames = this.count = 0; this.easing = Easing.swing; }; q3d_extend(Motion.prototype, { add: function(camera) { this.cameras.push(camera); }, reset: function() { this.frames = this.count = 0; }, begin: function(frames, easing) { this.frames = frames; this.count = 0; this.easing = Easing.select(easing); }, apply: function() { var c = this.cameras, l = c.length; if (this.frames == 0) { if (l > 0) c[0].apply(); else q3d_loadIdentity(); return; } var tf = this.count++ / this.frames; tf = this.easing(tf) * (l - 1); var ti = Math.floor(tf), t = tf - ti; if (ti >= l) { c[l - 1].apply(); return; } Camera.blend(c[ti < 1 ? 0 : ti - 1], c[ti], c[ti > l - 2 ? l - 1 : ti + 1], c[ti > l - 3 ? l - 1 : ti + 2], t). apply(); } }); /* ------------------------------------------------ */ /* 3d model caches */ var Cache = {}; // cube var Cube = function(x,y,z) { this.x = x; this.y = y; this.z = z; this.rx = 0; this.ry = 0; this.rz = 0; this.cube = new q3d_Cuboid(0,0,0, 40,40,40); }; q3d_extend(Cube.prototype, { reset: function() { this.rx = 0; this.ry = 0; this.rz = 0; return this; }, update: function(t) { t *= 3; if (t < 1) this.rx = t * 90; else if (t < 2) this.ry = (t - 1) * 90; else this.rz = (2 - t) * 90; return this; }, put: function() { q3d_pushMatrix(); q3d_translate(this.x, this.y, this.z); q3d_pushMatrix(); q3d_rotateZ(this.rz); q3d_rotateY(this.ry); q3d_rotateX(this.rx); this.cube.put(); q3d_popMatrix(); q3d_popMatrix(); } }); (function() { var g = new q3d_Group, c; for (var x = -120; x <= 120; x += 120) for (var y = -120; y <= 120; y += 120) g.add(new Cube(x,y,0)); var g2 = new q3d_Group; g2.add(new q3d_Patch(-500,-500,0, 500,-500,0, -500, 500,0)); g2.add(new q3d_Patch(-500,-500,0, 500,-500,0, -500, 500,0).culling(1,0)); q3d_cleanup(); q3d_loadIdentity(); g.put(); for (var l = g.length, i = 0; i < l; ++i) { g[i].cube. genUV1(3, 200, 200). genUV1(4, 200, 200). genUV1(5, 200, 200); g[i].rx = g[i].ry = 90; g[i].rz = -90; } q3d_translate(-125,-125,-500); q3d_rotateX(0); g2[0].put().genUV(200, 200); q3d_cleanup(); q3d_loadIdentity(); g.put(); for (i = 0; i < l; ++i) { g[i].cube. genUV1(0, 200, 200). genUV1(1, 200, 200). genUV1(2, 200, 200); g[i].reset(); } q3d_translate(-125,-125,-500); q3d_rotateX(180); g2[1].put().genUV(200, 200); Cache.cube = { group: g, group2: g2 }; })(); // stairs (function() { var g = new q3d_Group; var m = new Motion; var c0 = new Camera( 0,0, 200, 0,0,0, 0,1,0, 1); var c1 = new Camera( 0,0,-200, 0,0,0, -1,0,0, 1); g.add(new q3d_Cuboid(-200,-200,400, 100,100,100, 1)); g.add(new q3d_Cuboid(0,0,0, 100,100,100, 1)); g.add(new q3d_Cuboid(-200,0,200, 100,100,100, 1)); g.add(new q3d_Cuboid(0,-200,200, 100,100,100, 1)); g.add(new q3d_Cuboid(200,-200,0, 100,100,100, 1)); g.add(new q3d_Cuboid(-200,200,0, 100,100,100, 1)); g.add(new q3d_Cuboid(200,0,-200, 100,100,100, 1)); g.add(new q3d_Cuboid(0,200,-200, 100,100,100, 1)); g.add(new q3d_Cuboid(200,200,-400, 100,100,100, 1)); m.add(c0); m.add(new Camera(200,0,0, 0,0,0, 0,1,0, 0.2)); m.add(new Camera(-200,0,0, 0,0,0, 0,1,0, 1)); m.add(new Camera(-200,0,0, 0,0,0, 0,0,1, 0.5)); m.add(c1); q3d_cleanup(); q3d_loadIdentity(); c0.apply(); g.put(); var l = g.length, i; for (i = 0; i < l; ++i) g[i].genUV1(3,200,200). genUV1(4,200,200). genUV1(5,200,200); q3d_cleanup(); q3d_loadIdentity(); c1.apply(); g.put(); for (i = 0; i < l; ++i) g[i].genUV1(0,200,200). genUV1(1,200,200). genUV1(2,200,200); Cache.stairs = { group: g, motion: m }; })(); // pillars (function() { var p0 = new q3d_Group; var p1 = new q3d_Group; var p2 = new q3d_Group; var p3 = new q3d_Group; var p4 = new q3d_Group; var p5 = new q3d_Group; var x0,x1,x2,z0,z1,z2, l, i, m, r = 90; for (i = 0; i < 360; i += 48) { x0 = Math.cos(i * q3d_TO_RADIAN) * r; x1 = Math.cos((i + 48) * q3d_TO_RADIAN) * r; z0 = Math.sin(i * q3d_TO_RADIAN) * r; z1 = Math.sin((i + 48) * q3d_TO_RADIAN) * r; if (i < 180) { p0.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p3.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p4.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); } else { p1.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p2.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); p5.add(new q3d_Patch(x0,-300,z0, x0,300,z0, x1,-300,z1)); } } x0 = -100; z0 = 200; x1 = 0; z1 = 0; x2 = 200; z2 = 200; q3d_cleanup(); q3d_loadIdentity(); q3d_loadIdentity(); q3d_translate(x0, 0, z0); p0.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x1, 0, z1); p3.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x2, 0, z2); p4.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x0, 0, z0); q3d_rotateY(180); p1.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x1, 0, z1); q3d_rotateY(180); p2.put().genUV(200,200); q3d_loadIdentity(); q3d_translate(x2, 0, z2); q3d_rotateY(180); p5.put().genUV(200,200); Cache.pillars = { p0: p0, p1: p1, p2: p2, p3: p3, p4: p4, p5: p5, x0: x0, x1: x1, x2: x2, z0: z0, z1: z1, z2: z2 }; })(); // board (function() { var f = new q3d_Group, b = new q3d_Group, x = f; var h = 400, c0 = 0, c1 = 1; for (var i = 0; i < 2; ++i) { x.add(new q3d_Patch(-300,-h, 0, -200,-h, 0, -300, h, 0).culling(c0, c1)). add(new q3d_Patch(-250,-h,-100, -150,-h,-100, -250, h,-100).culling(c0, c1)). add(new q3d_Patch(-150,-h, 100, -50,-h, 100, -150, h, 100).culling(c0, c1)). add(new q3d_Patch(-150,-h,-200, -50,-h,-200, -150, h,-200).culling(c0, c1)). add(new q3d_Patch( 100,-h, 200, 200,-h, 200, 100, h, 200).culling(c0, c1)). add(new q3d_Patch(-100,-h,-300, 0,-h,-300, -100, h,-300).culling(c0, c1)). add(new q3d_Patch( 150,-h, 0, 250,-h, 0, 150, h, 0).culling(c0, c1)); x = b; c0 = 1; c1 = 0; } var m = new Motion; c0 = new Camera(0,0,200, 0,0,0, 0,1,0, 1); c1 = new Camera(0,0,-50, 0,0,0, 0,1,0, 1); m.add(c0); m.add(new Camera(100,100,-50, 0,0,0, 0,1,0, 0.4)); m.add(new Camera(0,0,-50, 0,0,0, 0,1,0, 0.4)); m.add(c1); q3d_cleanup(); q3d_loadIdentity(); c0.apply(); f.put(); f.genUV(200,200); q3d_cleanup(); q3d_loadIdentity(); c1.apply(); b.put(); b.genUV(200,200); Cache.board = { front: f, back: b, motion: m }; })(); /* ------------------------------------------------ */ /* transitions */ var Transitions = function() { this.img0 = this.img1 = null; this.frames = this.count = 0; this.callback = function(){}; this.handler = function(){}; this.first = true; }; q3d_extend(Transitions.prototype, { begin: function(img0, img1, frames, easing, reverse, callback, handler, data) { this.img0 = img0; this.img1 = img1; this.frames = frames; this.count = 0; this.easing = Easing.select(easing); this.reverse = reverse; this.callback = callback; this.handler = handler; this.data = data; this.apply(); }, apply: function() { var t = this.easing(this.count++ / this.frames); this.handler(t, 1 - t, this.data); if (this.count <= this.frames) { t = this; setTimeout(function() { t.apply(); }, 1000 / FPS); } else { this.callback(); } }, select: function(img0, img1, frames, easing, reverse, callback) { if (this.first) { this.first = false; this.dissolve(img0, img1, frames, easing, reverse, callback); return; } switch (Math.floor(Math.random() * 4)) { case 0: this.stairs(img0, img1, frames, easing, reverse, callback); break; case 1: this.pillars(img0, img1, frames, easing, reverse, callback); break; case 2: this.board(img0, img1, frames, easing, reverse, callback); break; case 3: this.cube(img0, img1, frames, easing, reverse, callback); break; } }, cube: function(img0, img1, frames, easing, reverse, callback) { var g = Cache.cube.group; for (var l = g.length, i = 0; i < l; ++i) { g[i].reset(); if (img0) g[i].cube. setTexture1(3, img0). setTexture1(4, img0). setTexture1(5, img0); if (img1) g[i].cube. setTexture1(0, img1). setTexture1(1, img1). setTexture1(2, img1); } g = Cache.cube.group2; if (img0) g[0].setTexture(img0); if (img1) g[1].setTexture(img1); this.begin(img0, img1, frames * 3, 'swing', reverse, callback, this._cube, Cache.cube); }, _cube: function(t, s, data) { q3d_cleanup(); q3d_loadIdentity(); var g = data.group, l = g.length, i; for (i = 0; i < l; ++i) data.group[i].update(t).put(); q3d_translate(-125,-125,-500); q3d_rotateX(t * 180); data.group2.put(); q3d_updateCanvas(); }, stairs: function(img0, img1, frames, easing, reverse, callback) { var g = Cache.stairs.group, i, l = g.length; if (img0) { for (i = 0; i < l; ++i) g[i].setTexture1(3, img0). setTexture1(4, img0). setTexture1(5, img0); } if (img1) { for (i = 0; i < l; ++i) g[i].setTexture1(0, img1). setTexture1(1, img1). setTexture1(2, img1); } Cache.stairs.motion.begin(frames * 6, 'linear'); this.begin(img0, img1, frames * 6, easing, reverse, callback, this._stairs, Cache.stairs); }, _stairs: function(t, s, data) { q3d_cleanup(); q3d_loadIdentity(); data.motion.apply(); data.group.put(); q3d_updateCanvas(); }, pillars: function(img0, img1, frames, easing, reverse, callback) { var p = Cache.pillars; if (img0) { p.p0.setTexture(img0); p.p2.setTexture(img0); p.p4.setTexture(img0); } if (img1) { p.p1.setTexture(img1); p.p3.setTexture(img1); p.p5.setTexture(img1); } this.begin(img0, img1, frames * 2, easing, reverse, callback, this._pillars, p); }, _pillars: function(t, s, data) { var v = 2 * t * t - 2 * t + 1; q3d_cleanup(); q3d_loadIdentity(); q3d_translate(data.x0, 0, data.z0); q3d_rotateY(t * 180); q3d_scale(v, v, v); data.p0.put(); data.p1.put(); q3d_loadIdentity(); q3d_translate(data.x1, 0, data.z1); q3d_rotateY(s * 180); q3d_scale(v, v, v); data.p2.put(); data.p3.put(); q3d_loadIdentity(); q3d_translate(data.x2, 0, data.z2); q3d_rotateY(t * 180); q3d_scale(v, v, v); data.p4.put(); data.p5.put(); q3d_updateCanvas(); }, board: function(img0, img1, frames, easing, reverse, callback) { var f = Cache.board.front; var b = Cache.board.back; if (img0) f.setTexture(img0); if (img1) b.setTexture(img1); Cache.board.motion.begin(frames * 4, 'swing'); this.begin(img0, img1, frames * 4, easing, reverse, callback, this._board, Cache.board); }, _board: function(t, s, data) { q3d_cleanup(); q3d_loadIdentity(); data.motion.apply(); data.front.put(); data.back.put(); q3d_updateCanvas(); }, dissolve: function(img0, img1, frames, easing, reverse, callback) { this.begin(img0, img1, frames, easing, reverse, callback, this._dissolve); }, _dissolve: function(t, s) { var cx = q3d_CONTEXT; cx.save(); cx.globalAlpha = s; if (this.img0) cx.drawImage(this.img0, 0, 0); cx.globalAlpha = t; if (this.img1) cx.drawImage(this.img1, 0, 0); cx.restore(); } }); /* ------------------------------------------------ */ /* main */ var MAIN = new ImageList; var TRAN = new Transitions; var PAGE = q3d_element('page'); var INFO = q3d_element('info'); var PREV = q3d_element('prev'); var NEXT = q3d_element('next'); var TAGS = q3d_element('tags'); var MSG = q3d_element('msg'); var LOCK = []; function lock(msg) { LOCK.push(msg); MSG.textContent = LOCK.join(' > '); } function unlock() { LOCK.pop(); MSG.textContent = LOCK.join(' > '); } function isLocked() { return LOCK.length > 0; } function img2canvas(img) { var w = img.width, h = img.height; var cv = document.createElement('CANVAS'); var cx = cv.getContext('2d'); var d = Math.min(1, Math.max(SIZE / w, SIZE / h)); var dw = w * d, dh = h * d; cv.width = cv.height = SIZE; cx.fillStyle = '#000'; cx.fillRect(0, 0, SIZE, SIZE); q3d_drawImage(cx, img, 0, 0, w, h, (SIZE - dw) / 2, (SIZE - dh) / 2, dw, dh); return cv; } function initialize() { PREV.addEventListener('click', function(ev) { prevImage(); ev.preventDefault(); }, false); NEXT.addEventListener('click', function(ev) { nextImage(); ev.preventDefault(); }, false); q3d_bindCanvas('canvas'); q3d_resizeCanvas(SIZE, SIZE); changeTag('kamakura'); } function changeTag(tag) { PAGE.textContent = ''; INFO.textContent = ''; TAGS.textContent = ''; PREV.style.display = 'none'; NEXT.style.display = 'none'; MAIN = new ImageList; lock('load from flickr.com with tag:' + tag); MAIN.addFromFlickr(tag, 50, function() { unlock(); loadImage(); }); } function loadImage() { PAGE.textContent = ''; INFO.textContent = ''; TAGS.textContent = ''; PREV.style.display = 'none'; NEXT.style.display = 'none'; lock('loading image #' + MAIN.position); MAIN.getContent(plotImage); } function plotImage(img, w, h, item) { if (img == null) { unlock(); INFO.textContent = 'image not found.'; return; } var cv = img2canvas(img); TRAN.select(TRAN.img1, cv, FPS, 'swing', false, function() { q3d_CONTEXT.save(); q3d_CONTEXT.setTransform(1,0, 0,1, 0,0); q3d_CONTEXT.drawImage(cv, 0, 0); q3d_CONTEXT.restore(); PAGE.textContent = MAIN.pagination(); INFO.textContent = item.formatted; TAGS.textContent = ''; PREV.style.display = MAIN.isFirst() ? 'none' : 'block'; NEXT.style.display = MAIN.isLast() ? 'none' : 'block'; var e, c = item.category, l = c.length, i; for (i = 0; i < l; ++i) { e = document.createElement('SPAN'); e.textContent = c[i]; e.addEventListener('click', (function(tag) { return function(ev) { changeTag(tag); }; })(c[i]), false); TAGS.appendChild(e); } unlock(); }); } function prevImage() { if (!isLocked() && MAIN.prev()) loadImage(); } function nextImage() { if (!isLocked() && MAIN.next()) loadImage(); } /* ------------------------------------------------ */ /* start ! */ google.load('feeds', '1'); google.setOnLoadCallback(initialize); <script src="http://www.google.com/jsapi?key=ABQIAAAAv7CFgLxkvXPvX2wsDe8U7RTgesIKiW70LgsG7i-NXW8R52TaOBR8U55UVRx4tOOPzns9Z3etYprOww" type="text/javascript"></script> <pre id="page"></pre> <pre id="info"></pre> <canvas id="canvas" width="400" height="400"></canvas> <ul id="nav"> <li id="prev"><</li> <li id="next">></li> </ul> <pre id="tags"></pre> <pre id="msg"></pre> BODY { color:#0f0; overflow:hidden; background:#000; } PRE { margin:0; padding:0; position:absolute; font-size:12px; } #page { left:5px;top:1px; } #info { right:5px;top:1px; text-align:right; } #canvas { position:absolute; left:50%;top:50%; margin:-200px 0 0 -200px; } #nav > LI { list-style:none; position:absolute; display:block; top:50%; width:24px;height:30px; line-height:30px; margin-top:-15px; text-align:center; cursor:pointer; } #nav > LI:hover { background:#0f0; color:#000; } #nav > #prev { left:0; display:none; } #prev:hover { -moz-border-radius-topright:10px; -moz-border-radius-bottomright:10px; -webkit-border-top-right-radius:10px; -webkit-border-bottom-right-radius:10px; border-top-right-radius:10px; border-bottom-right-radius:10px; } #next { right:0; } #next:hover { -moz-border-radius-topleft:10px; -moz-border-radius-bottomleft:10px; -webkit-border-top-left-radius:10px; -webkit-border-bottom-left-radius:10px; border-top-left-radius:10px; border-bottom-left-radius:10px; } #tags { left:5px;bottom:5px; } #tags > SPAN { margin-right:0.5em; padding:0 0.2em; color:#000; background:#0f0; -webkit-border-radius:3px; -moz-border-radius:3px; border-radius:3px; cursor:pointer; } #msg { right:5px;bottom:5px; color:#f00; } use an iframe compat browser, deer Play on jsdo.it games Share Embed QR Tag Download Complete! Description どんなゲームですか? Control Device スマートフォンコントローラー jsdo.it WebSocket Controller» マウス キーボード タッチデバイス Fullscreen 有効 無効 jsdo.it games から削除する Submit Tweet style Design view Code view code <script type="text/javascript" src="http://jsdo.it/blogparts/iO9K/js?view=design"></script><p class="ttlBpJsdoit" style="width: 465px; margin: 0; text-align: right; font-size: 11px;"><a href="http://jsdo.it/gct256/iO9K" title="MediaRSS Viewer with *crazy* transition">MediaRSS Viewer with *crazy* transition - jsdo.it - share JavaScript, HTML5 and CSS</a></p> 3d animation canvas javascript Tweet twitter Tags 3d animation block canvas javascript viewer Favorite by smallwind191.. shamotron m1m0r1 h6k mitsuruwk rettuce tkinjo fingaholic 9re canvastag demouth termat nanlow kleinschmidt.. narutohyper clockmaker chomeconic paq: *crazy* mash: crazy ww y3i12: woot! O_O yasigani-ni: 3Dviewer凄すぎる・・・ tetsuwo: 3danimationblockcanvasviewerすげぇ! Forked sort new page view favorite forked forked: MediaRSS Viewer with *.. Hooker.Kuzya.. 00 17views 941/11/90 3d animation canvas javascript forked: MediaRSS Viewer with *.. fhonde 00 32views 941/11/90 3d animation canvas javascript forked from: MediaRSS Viewer w.. alt 00 119views 941/11/90 forked from: MediaRSS Viewer w.. hellojane96 00 210views 941/11/90