loads of changes, methods are now mostly assigned to the prototype (for better or worse), the constructer accepts an array of options, in fitWidth mode the comic will scale on window resize

This commit is contained in:
Bala Clark 2010-07-07 16:57:47 +01:00
parent f3ec23e060
commit 2f1739743f

View file

@ -1,5 +1,5 @@
var book;
var book
window.onload = function() {
@ -13,13 +13,30 @@ window.onload = function() {
"http://dev.justforcomics.com/get/image/?f=comics/extracted/oni_whiteout_melt_1/06.jpg"
];
book = new ComicBook();
book.draw("comic", pages);
var options = {
displayMode: "double",
zoomMode: "fitWidth"
}
book = new ComicBook("comic", pages, options);
book.draw();
}
function ComicBook() {
window.onresize = function() {
book.draw();
}
function ComicBook(id, srcs, opts) {
this.id = id;
this.srcs = srcs;
var defaults = {
displayMode: "double", // single / double
zoomMode: "fitWidth" // manual / fitWidth
}
var options = merge(defaults, opts);
var srcs = [];
var pages = [];
var canvas;
var context;
@ -29,25 +46,24 @@ function ComicBook() {
var loaded = 0;
var scale = 1;
var displayMode = "double" // single / double
var zoomMode = "fitWidth"; // manual / fitWidth
/*
* @param {String} id The canvas ID to draw the comic on.
* @param {Object} srcs An array of all the comic page srcs, in order
* @see #preload
*/
this.draw = function(id, srcs) {
ComicBook.prototype.draw = function() {
// setup canvas
canvas = document.getElementById(id);
canvas = document.getElementById(this.id);
context = canvas.getContext("2d");
// preload images
preload(srcs);
// preload images if needed
if (pages.length != this.srcs.length) this.preload(this.srcs);
else this.drawPage();
// add page controls
canvas.addEventListener("click", navigation, false);
canvas.addEventListener("click", ComicBook.prototype.navigation, false);
}
/*
@ -55,10 +71,10 @@ function ComicBook() {
*
* @param new_scale {Number} Scale the canvas to this ratio
*/
this.zoom = function(new_scale) {
zoomMode = "manual";
ComicBook.prototype.zoom = function(new_scale) {
options.zoomMode = "manual";
scale = new_scale;
drawPage();
this.drawPage();
}
/**
@ -67,7 +83,7 @@ function ComicBook() {
* @param srcs {Object} srcs
* @see #drawPage
*/
function preload(srcs) {
ComicBook.prototype.preload = function(srcs) {
if (srcs.length < buffer) buffer = srcs.length; // don't get stuck if the buffer level is higher than the number of pages
@ -78,9 +94,8 @@ function ComicBook() {
page.src = src;
page.onload = function() {
pages[i] = this; loaded++;
if (loaded == buffer) drawPage();
pages[i] = this;loaded++;
if (loaded == buffer) ComicBook.prototype.drawPage();
}
});
}
@ -91,34 +106,30 @@ function ComicBook() {
* TODO: break this down into drawSinglePage() & drawDoublePage()
* TODO: if the current browser doesn't have canvas support, use img tags
*/
function drawPage() {
ComicBook.prototype.drawPage = function() {
var zoom_scale;
var page = pages[pointer];
var page2 = pages[pointer + 1];
if (typeof page != "object") throw "invalid page";
var width = page.width;
var height = page.height;
if (displayMode == "double") {
if (options.displayMode == "double") {
// for double page spreads, factor in the width of both pages, set the height to the tallest page
if (typeof page2 == "object") {
width += page2.width;
if (page2.height > page.height) height = page2.height;
}
// for double page spreads, factor in the width of both pages
if (typeof page2 == "object") width += page2.width;
// if this is the last page and there is no page2, still keep the canvas wide
else width += width;
}
// update the page scale if a non manual mode has been chosen
switch(zoomMode) {
switch(options.zoomMode) {
case "manual":
zoom_scale = (displayMode == "double") ? scale * 2 : scale;
zoom_scale = (options.displayMode == "double") ? scale * 2 : scale;
break;
case "fitWidth":
@ -127,22 +138,22 @@ function ComicBook() {
: window.innerWidth / width; // scale down if the window is narrower than the page
break;
default: throw "invalid zoomMode";
default:throw "invalid zoomMode";
}
var canvas_width = page.width * zoom_scale;
var canvas_height = page.height * zoom_scale;
var page_width = (zoomMode == "manual") ? page.width * scale : canvas_width;
var page_height = (zoomMode == "manual") ? page.height * scale : canvas_height;
var page_width = (options.zoomMode == "manual") ? page.width * scale : canvas_width;
var page_height = (options.zoomMode == "manual") ? page.height * scale : canvas_height;
// make sure the canvas is always at least full screen, even if the page is more narrow than the screen
canvas.width = (canvas_width < window.innerWidth) ? window.innerWidth : canvas_width;
canvas.height = (canvas_height < window.innerHeight) ? window.innerHeight : canvas_height;
// draw the page(s)
context.drawImage(page, 0, 0, page_width, page_height);
if (displayMode == "double" && typeof page2 == "object") context.drawImage(page2, page_width, 0, page_width, page_height);
if (options.displayMode == "double" && typeof page2 == "object") context.drawImage(page2, page_width, 0, page_width, page_height);
}
@ -151,10 +162,10 @@ function ComicBook() {
*
* @see #drawPage
*/
function drawNextPage() {
ComicBook.prototype.drawNextPage = function() {
if (pointer + 1 < pages.length) {
pointer++;
drawPage();
this.drawPage();
}
}
@ -163,21 +174,21 @@ function ComicBook() {
*
* @see #drawPage
*/
function drawPrevPage() {
ComicBook.prototype.drawPrevPage = function() {
if (pointer > 0) {
pointer--;
drawPage();
this.drawPage();
}
}
function navigation(e) {
ComicBook.prototype.navigation = function(e) {
switch (e.type) {
case "click":
switch (getCursorPosition(e)) {
case "left": drawPrevPage(); break;
case "right": drawNextPage(); break;
case "left": ComicBook.prototype.drawPrevPage(); break;
case "right": ComicBook.prototype.drawNextPage(); break;
}
break;
@ -191,19 +202,38 @@ function ComicBook() {
* Thanks to: Mark Pilgrim & http://diveintohtml5.org/canvas.html
*/
function getCursorPosition(e) {
var x;
// check if page relative positions exist
if (e.pageX) x = e.pageX;
// if not figure them out
else x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
// make the position relative to the canvas
x -= canvas.offsetLeft;
// check if the user clicked on the left or right side
return (x <= canvas.width / 2) ? 'left' : 'right';
}
}
/**
* Merge two arrays. Any properties in b will replace the same properties in
* a. New properties from b will be added to a.
*
* @param a {Object}
* @param b {Object}
*/
function merge(a, b) {
if (typeof b == "undefined") b = {};
for (prop in a) {
if (prop in b) continue;
b[prop] = a[prop];
}
return b;
}
}