[スクリプトの概要]
本をめくるようにして画像を表示します。
左右のボタンを押すと、フェードしながら画像が切り替わります。
「1ページ送り」「5ページ送り」「先頭・末尾送り」が可能です。
タッチしているところの拡大表示ができます。マウス以外にタップでも見やすいように拡大する基準の位置を変更できます。

[ファイル、フォルダの構成]
[File] GkBookScript.jsスクリプト本体
[File] GkBookScript.css描画CANVAS部分のスタイル定義
[File] index.html表示部分の本体
[Folder] itemsボタン用の画像が保存されています。
[Folder] pages表示したい画像を見開きを1枚にして保存しておきます。
ファイル名は p001.jpg を先頭にして通し番号を振っておきます。
※ダウンロードは下の方にあります

ファイル GkBookScript.js


//=============================================================================
//
//  GkBookScript.js   JAVAScript ページめくり
//            Programmed by G.K.2018
//
//=============================================================================

//変数の宣言===================================================================
var canvas;				//キャンバスオブジェクト
var ctx;				//描画コンテキスト

var cur_page = 1;			//現在のページ番号
var old_page = 1;			//切替前のページ番号
var last_page = 79;			//最後のページ番号
var FOLDER_PAGES = "./pages/p";		//ページ画像があるパス

var winWidth = 1200;			//CANVASの横幅
var winHeight = 800;			//CANVASの高さ

var cx = 0;				//クリック(タッチ)位置X
var cy = 0;				//クリック(タッチ)位置Y
var px = 2.2;				//タッチ位置-画像位置の変換倍率X
var py = 2.2;				//				
var bton = 0;				//タッチしたボタンの番号
var direct = 0;				//ページめくり方向

var page_chg_step = 0;			//画面切り替え用変数
var page_chg_offset = 0;
var page_chg_int = 0;
var timer_proc;				//タイマー処理

var BSIZE = 64;				//ボタンサイズ
var BSEP  = 10;				//ボタン間隔
var BOOK_TITLE = "目で見る志知 道ばたの歴史";

var img_filename = new Array("index","back1","back2","back3","next1","next2","next3","setting");
var img_over = new Array();		//マウスオーバーフラグ
var img_btn = new Array();		//画像オブジェクト(ボタン)
var img_page  = new Image();		//画像オブジェクト(ページ)
var img_page_old  = new Image();	//画像オブジェクト(ページ、切替前)

var flg_zoom = 0;			//拡大表示ON
var zoomPos = 0;			//拡大基準

var debug_flg = false;			//デバッグモード
var debug_mes = "";			//デバッグメッセージ


//関数の宣言========================================================================

//最初に実行------------------------------------------
function main(){
    init();
    draw();
}


//クリック(タップ)時のイベント----------------------
function onDown(e) {
    //ページ切替中は処理しない
    if(page_chg_step > 0) {
        return;
    }

    var rect = e.target.getBoundingClientRect();
    cx = parseInt(e.clientX - rect.left);
    cy = parseInt(e.clientY - rect.top);

    if(bton == 0 && page_chg_step == 0) {
        checkButtonOn();
    }

    draw();
}


//タップ時のイベント----------------------
function onDown2(e) {
    e.preventDefault();
    //ページ切替中は処理しない
    if(page_chg_step > 0) {
        return;
    }

    var rect = e.target.getBoundingClientRect();
    var touchObject = e.changedTouches[0];
    cx = parseInt(touchObject.clientX - rect.left);
    cy = parseInt(touchObject.clientY - rect.top);

    if(bton == 0 && page_chg_step == 0) {
        checkButtonOn();
    }

    draw();
}


//離したときのイベント--------------------------------
function onUp(e) {
    Proc_OnUp(e);
}


//離したときのイベント--------------------------------
function onUp2(e) {
    e.preventDefault();
    Proc_OnUp(e);
}


function Proc_OnUp(e) {
    //ページ切替中は処理しない
    if(page_chg_step > 0) {
        return;
    }

    flg_zoom = 0;
    draw();
}


//マウスを動かしたときのイベント----------------------
function onMove(e) {
    //ページ切替中は処理しない
    if(page_chg_step > 0) {
        return;
    }

    var rect = e.target.getBoundingClientRect();
    cx = parseInt(e.clientX - rect.left);
    cy = parseInt(e.clientY - rect.top);

    if(bton == 0 && page_chg_step == 0) {
        checkButtonOver();
    }

    draw();
}


function onMove2(e) {
    //ページ切替中は処理しない
    if(page_chg_step > 0) {
        return;
    }

    e.preventDefault();

    var rect = e.target.getBoundingClientRect();
    var touchObject = e.changedTouches[0];
    cx = parseInt(touchObject.clientX - rect.left);
    cy = parseInt(touchObject.clientY - rect.top);
    draw();
}


//初期化処理-------------------------------------------
function init() {

    //描画コンテキストの取得
    canvas = document.getElementById("mainCanvas");
    if ( ! canvas || ! canvas.getContext ) { return false; }
    ctx = canvas.getContext('2d');
 
    //イベントの追加
    canvas.addEventListener('mousedown', onDown, false);
    canvas.addEventListener('mouseup', onUp, false);
    canvas.addEventListener('mousemove', onMove, false);

    canvas.addEventListener('touchstart', onDown2, false);
    canvas.addEventListener('touchend', onUp2, false);
    canvas.addEventListener('touchmove', onMove2, false);

    //画像のロード
    for (var i=0; i<8; i++) {
        img_btn[i] = new Image();
        img_btn[i].src = "./items/button_" + img_filename[i] + ".png";
        img_over[i] = 0;
    }

    //最初のページを表示する
    bton = 13;
    img_page.src =  FOLDER_PAGES + ('000' + cur_page).slice(-3) + ".jpg";
    img_page_old.src = FOLDER_PAGES + ('000' + cur_page).slice(-3) + ".jpg";
}


//画面描画処理----------------------------------------
function draw() {
    proc_jump();
    draw_pages(ctx);
    draw_buttons(ctx, 0.5);
    draw_status(ctx);
}


//操作ボタンの表示------------------------------------
function draw_buttons(ctx, aplha) {
  
    var xr = winWidth - BSEP - BSIZE;
    var y2 = (winHeight / 2) - (BSIZE / 2);
    var y1 = y2 - BSEP - BSIZE;
    var y3 = y2 + BSEP + BSIZE;

    var val_alpha = 0.40;

    ctx.globalAlpha = val_alpha;
    ctx.drawImage(img_btn[0], xr, BSEP, BSIZE, BSIZE);
    //ctx.drawImage(img_btn[7], xr, BSEP*2 + BSIZE, BSIZE, BSIZE);

    if(img_over[1] == 1) {
        ctx.globalAlpha = 1.0;
    }
    ctx.drawImage(img_btn[1], xr, y1, BSIZE, BSIZE);
    ctx.globalAlpha = val_alpha;

    if(img_over[2] == 1) {
        ctx.globalAlpha = 1.0;

    }
    ctx.drawImage(img_btn[2], xr, y2, BSIZE, BSIZE);
    ctx.globalAlpha = val_alpha;

    if(img_over[3] == 1) {
        ctx.globalAlpha = 1.0;
    }
    ctx.drawImage(img_btn[3], xr, y3, BSIZE, BSIZE);
    ctx.globalAlpha = val_alpha;

    if(img_over[4] == 1) {
        ctx.globalAlpha = 1.0;
    }
    ctx.drawImage(img_btn[4], 10, y1, BSIZE, BSIZE);
    ctx.globalAlpha = val_alpha;

    if(img_over[5] == 1) {
        ctx.globalAlpha = 1.0;
    }
    ctx.drawImage(img_btn[5], 10, y2, BSIZE, BSIZE);
    ctx.globalAlpha = val_alpha;

    if(img_over[6] == 1) {
        ctx.globalAlpha = 1.0;
    }
    ctx.drawImage(img_btn[6], 10, y3, BSIZE, BSIZE);
    //ctx.globalAlpha = val_alpha;

    ctx.globalAlpha = 1.0;
}


//ページを進める処理--------------------------------
function proc_jump() {

    if(bton == 0) {
       return;
    }

    var jump_ok = 0;

    if(bton == 11) {   jump_ok = jump_page(-1);  direct = 0; }
    if(bton == 12) {   jump_ok = jump_page(-5);  direct = 0; }
    if(bton == 13) {   jump_ok = jump_page(last_page * -1);   direct = 0;  }

    if(bton == 21) {   jump_ok = jump_page(1);    direct = 1; }
    if(bton == 22) {   jump_ok = jump_page(5);    direct = 1; }
    if(bton == 23) {   jump_ok = jump_page(last_page);     direct = 1; }

  bton = 0;

    if(jump_ok == 0) {
        return;
    }

    img_page.onLoad = proc_jump_start();
    img_page_old.src =  FOLDER_PAGES + ('000' + old_page).slice(-3) + ".jpg";
    img_page.src =  FOLDER_PAGES + ('000' + cur_page).slice(-3) + ".jpg";
}


//ページ切替のアニメーションを開始
function proc_jump_start() {

    page_chg_step = 10;

    if(direct == 0) {
        page_chg_offset = 20;
        page_chg_int   = -2;
    }

    if(direct == 1) {
        page_chg_offset = -20;
        page_chg_int   = 2;
    }

    timer_proc = setInterval("change_page_anime()", 20);
}


//ページジャンプ --------------------------------
function jump_page(num) {

    if(cur_page == 1 && num < 0) {
        return 0;
    }

    old_page = cur_page;

    cur_page += num;

    if (cur_page < 1) {
        cur_page = 1;
    }
    
    if (cur_page > last_page) {
        cur_page = last_page;
    }

    return 1;
}


//ページの表示--------------------------------------
function draw_pages(ctx) {

    if(img_page.complete == false) {
        ctx.font = "22px 'MS Pゴシック'";
        ctx.fillText("画像読み込み待ち...", 10, 30);
        setTimeout(draw, 300);
        return;
    }

    if(img_page_old.complete == false) {
        ctx.font = "22px 'MS Pゴシック'";
        ctx.fillText("画像読み込み待ち...", 10, 30);
        setTimeout(draw, 300);
        return;
    }

    //通常表示
    if(page_chg_step == 0) {
        ctx.drawImage(img_page, 0, 0, winWidth, winHeight);

        //拡大表示
        if(flg_zoom == 1) {
            var xo = 0;
            var yo = 0;
            var xx = 0;
            var yy = 0;

            switch(zoomPos) {
            //中央
            case 0:
                xx = (cx - 150);
                yy = (cy - 150);
                xo = 300;
                yo = 300;
                break;

            //右端
            case 1:
                xx = (cx - 300);
                yy = (cy - 150);
                xo = 600;
                yo = 300;
                break;

            //左端
            case 2:
                xx = (cx - 0);
                yy = (cy - 150);
                xo = 0;
                yo = 300;
                break;
            }

            if(xx < 0) { xx = 0; }
            if(yy < 0) { yy = 0; }

            ctx.fillStyle = "rgb(255, 255, 0)";
            ctx.globalAlpha = 0.5;

            ctx.fillRect(cx - (xo + 3), cy - (yo + 3), 606, 606);

            ctx.strokeStyle = "rgb(0, 0, 0)";
            ctx.globalAlpha = 1.0;

            ctx.drawImage(img_page, xx * px, yy * py, 300, 300, cx - xo, cy - yo, 600, 600);
        }
    }

    //切替中
    if(page_chg_step > 0) {
        ctx.globalAlpha = 0.1 * page_chg_step;
        ctx.drawImage(img_page_old, 0, 0, winWidth, winHeight);

        ctx.globalAlpha = 1.0 - (0.1 * page_chg_step);
        ctx.drawImage(img_page, page_chg_offset, 0, winWidth, winHeight);

        ctx.globalAlpha = 1.0;
    }

    //両端のページ演出
    var left_page = last_page - cur_page;
    var right_page = cur_page;

    for(var i=0; i BSEP && cx < BSEP + BSIZE) {
      if(cy > y1  && cy < y1 + BSIZE) {   bton = 21;  return; }
      if(cy > y2  && cy < y2 + BSIZE) {   bton = 22;  return; }
      if(cy > y3  && cy < y3 + BSIZE) {   bton = 23;  return; }
    }

    if(cx < BSEP * 3) {
        bton = 21;  return; 
    }

    //BACK側ボタン
    if(cx > winWidth - BSEP - BSIZE && cx < winWidth - BSEP) {
      if(cy > y1  && cy < y1 + BSIZE) {   bton = 11;  return; }
      if(cy > y2  && cy < y2 + BSIZE) {   bton = 12;  return; }
      if(cy > y3  && cy < y3 + BSIZE) {   bton = 13;  return; }
    }

    if(cx > winWidth - BSEP * 3) {
        bton = 11;  return; 
    }

    //ボタンを押していない場合は拡大表示する
    flg_zoom = 1;
    //拡大基準を得る
    zoomPos = document.form1.zoomPos.selectedIndex;
}


//ボタンの上にマウスカーソルが来ているか調べる---------
function checkButtonOver() {
    var xr = winWidth - BSEP - BSIZE;
    var y2 = (winHeight / 2) - (BSIZE / 2);
    var y1 = y2 - BSEP - BSIZE;
    var y3 = y2 + BSEP + BSIZE;

    for(var i=0; i<8; i++) {
        img_over[i] = 0;
    }

    //NEXT側ボタン
    if(cx > BSEP && cx < BSEP + BSIZE) {
      if(cy > y1  && cy < y1 + BSIZE) {   img_over[4] = 1;  return; }
      if(cy > y2  && cy < y2 + BSIZE) {   img_over[5] = 1;  return; }
      if(cy > y3  && cy < y3 + BSIZE) {   img_over[6] = 1;  return; }
    }

    //BACK側ボタン
    if(cx > winWidth - BSEP - BSIZE && cx < winWidth - BSEP) {
      if(cy > y1  && cy < y1 + BSIZE) {   img_over[1] = 1;  return; }
      if(cy > y2  && cy < y2 + BSIZE) {   img_over[2] = 1;  return; }
      if(cy > y3  && cy < y3 + BSIZE) {   img_over[3] = 1;  return; }
    }
}


//ページ切替アニメーション
function change_page_anime() {

    if(img_page.complete == false) {
        return;
    }

    if(img_page_old.complete == false) {
        return;
    }

    page_chg_step --;
    page_chg_offset += page_chg_int;

    draw();

    //終了
    if(page_chg_step < 1){
        clearInterval(timer_proc);
	page_chg_step = 0;
    }
}

ファイル GkBookScript.css

canvas {
    box-shadow:5px 5px 10px;
    background-color:#FFF;
    border: 1px solid #999;
}


[ファイルのダウンロード]
GkBookScript.zip

サンプルを表示
ウィンドウを閉じる
トップに戻る