POPSブログ

CreateJS FlickrAPI photos.search メソッドのキーワード検索画像表示

332

  Category:  javascript2014/12/08 pops 

キーワード検索により、FlickrAPIのデータをjQuery.getJSONで読み込み、サムネール画像をCreateJSで表示し「ドラッグ」可能にします。サムネール「クリック」で大きな画像を表示します。
「キーワード入力画面」付きですので、条件を変えて再検索の操作が出来ます。
easeljs-0.7.1 でのテストです。

 

CreateJS FlickrAPI photos.search メソッドのキーワード検索画像表示テスト

JSは基本的に「前ページ」のものを改造しただけです。
但し、クロスドメイン画像の為通常の方法では「ドラッグ」出来ないために工夫をしています。クロスドメイン画像があらゆるイベントに影響するので困る。(エライコッチャ、エライコッチャ、ホイホイホイ)
「ドラッグ」形式のビューアーは以前作っていますので、それと組み合わせました。


重要、easeljs-0.8用について

2014/12/13/にeaseljs-0.8がリリースされましたが、クロスドメイン画像の取得が困難になっています。このページ下記デモJSは、easeljs-0.7.1用でありバージョン違いでは動きません。
よって、easeljs-0.8用に作り直しましたので、下記記事を参照ください。機能、レイアウトなどはまったく同じです。


【参照】当方の記事: CreateJS FlickrAPI「タグ入力画面」付きのタグ検索とImage()クロスドメイン画像表示

【参照】当方の記事: CreateJS FlickrAPI「キーワード入力画面」付きのワード検索とImage()クロスドメイン画像表示

 

 

 

DEMO (jQuery.getJSON処理)


CreateJS FlickrAPI photos.search メソッドのキーワード検索画像表示デモ

このページはHTML5では有りませんので、デモページでご覧ください。「IE7.8」ではご覧いただけません。
/// 注意、ブラウザ、マシン性能により描画品質などに大きな差が有ります事了承下さい ///


easeljs-0.7.1用デモ


Chrome Opera Firefox Safari(Win) IE9-11で動作確認済み。 Safari(Mac)、は未確認です。


 

HTML JS CSS


使用するライブラリ

easeljs preloadjs tweenjs

配布元 : CreateJS createjs.com


ライブラリの読み込み

ダウンロードしたJSを使用する場合。記述は一例です。(バージョン 0.7.1 使用)


<script type="text/javascript" src="js/easeljs-0.7.1.min.js"></script>
<script type="text/javascript" src="js/preloadjs-0.4.1.min.js"></script>
<script type="text/javascript" src="js/tweenjs-0.5.1.min.js"></script>

重要、バージョン違いでは動かない場合が有りますので必ず合わせて下さい。


jQuery処理用に、事前にjQuery1.8以上を読み込んでおくことが必要です。


HTML (HTML5)



<div id="demo-wrap">
	<div id="image-box" class="radius">
		<canvas id="mainCanvas" width="640" height="640"></canvas>
	<div id="searchPanel" class="">
		KEY <input type="text" id="searchBox" />
		表示数<select name="select">
		<option value="10">10</option>
		<option value="20">20</option>
		<option value="30">30</option>
		<option value="40">40</option>
		</select>
		<button id="searchButton">検索</button>
		<button id="cancelButton">中止</button>
	</div><div class="clear"></div>
	</div>
</div>

JS

createJS115.js、JS名は任意に変更可。注意、easeljs-0.7.1用です。


//日本語
//createJS115.js
//Flickrサムネールドラッグ、キーワード入力形式
//拡大表示とオーナーページにリンクテスト
//easeljs-0.7.1 デモ用

//------------------------------------------------------
//初期設定

var tags_v="日本航空 Airlines";
var tagmode_v="any";//checked未使用

var speed=1000;//移動FADE、アニメ速度
var delay_speed=2000;//1000-5000最初の遅延用に使用
var slide_time;//未使用

//canvasの大きさ/全てこの値を使用
var canvasWidth=640;
var canvasHeight=640;

//サムネールbtnの使用 useのこと
var thumbbtn_use="use";
//クリック専用ボタン
var hitbtn=true;//true false
//OWNER-LINKボタン
var ownerlink=true;//true false

//Loading AUTOの文字を表示するかuse
var text_use="use";
//Flickr画像のタイトル文字を表示するかuse
var titletext_use="use";

//表示スケール
var image_scale=1;//原則1未使用
//Flickr読み込み画像数、最大40位まで
var loadImage_len=10;//10-40

//サムネール
var btnR=5;//角丸半径 2-5

//画像manifestリスト空白
var manifest=[];

//最初の画像0のこと
var image_no=0;
//画像数
var image_max;

//------------------------------------------------------

//ステージ
var stage;
//Loader
var loader;
//コンテナ
var container,loadingcontainer,progresscontainer;
var titlecontainer;
var btncontainer;
//画像
var welcomeImage,mainImage,backImage,topImage;
//Loading関連
var loadingShape,progressbar,progtext,bar_v;
//TEXT
var viewtext;
var titletext;
var ownertext;
//ROLLOVER-ACTION-LAY
var actionlay;

//読み込み画像の大きさcanvasと同じ
var imageW=canvasWidth;
var imageH=canvasHeight;

//読み込み画像result保存容器
var assets=[];
var thumb_assets=[];
//読み込みイメージローダー
var imgloader;

//変数
var globalflag=false;
//loading変数
var loading=false;

//shadowフィルター
var shadow=new createjs.Shadow("#000000",0,0,4);
var once=true;//未使用
//サムネールボタン
var myBtn=[];
//OWNER-LINKボタン
var linkBtn;
var closeBtn;
var openBtn;
//ドラッグ判別
dragflag=false;

//移動Globalポジションデータ
var gpoint_x;
var gpoint_y;
var gangle;//角度
var gscale;//スケール

//jQuery
var search_panel;
var search_box;
var search_button;
var cancel_button;

//flickr
var flickrthumbs=[];
var flickrImages=[];
var flickrLinks=[];
var flickrTitles=[];
var flickrOwners=[];

var flickr=false;
var flickrW=[];//小
var flickrH=[];
var flickrbigW=[];//大
var flickrbigH=[];
var loadItem=0;

//ロード数保存
var keep_len=loadImage_len;

//---------------------------------------------------------------------------------------------

//ステージ周りセット
function init() {

	//インスタンス化
	search_panel=$("#searchPanel");
	search_box=$("#searchBox");
	search_button=$("#searchButton");
	cancel_button=$("#cancelButton");

	//検索ボタンclickイベント
	search_button.click(function(){search_start();});
	//キャンセルボタンclickイベント
	cancel_button.click(function(){search_cancel();});
	//value初期値代入
	search_box.val(tags_v);
	//非表示
	search_panel.addClass("hidden");

	//ステージ
	stage=new createjs.Stage('mainCanvas');
	//MouseOver重要
	stage.enableMouseOver(20);
	//ステージ2無し

	//バックRect/最下位色背景層、無くとも良い
	var backrect=new createjs.Shape();
	backrect.graphics.beginFill("#000000").drawRect(0,0,canvasWidth,canvasHeight);
	stage.addChild(backrect);

	//welcome画像層画像表示
	welcomeImage=new createjs.Bitmap("/main/images/flickr_back.jpg");//640x640
	stage.addChild(welcomeImage);

	//ステージサムネールコンテナ、あとで作る
	btncontainer=new createjs.Container();
	btncontainer.x=0;
	btncontainer.y=0;
	//サムネールコンテナをステージにaddChild
	stage.addChild(btncontainer);
	btncontainer.visible=false;//非表示
	
	//コンテナに上下画像層配置/中央補正
	container=new createjs.Container();
	container.x=canvasWidth/2;
	container.y=canvasHeight/2;
	//下、透過黒バック挿入
	backImage=new createjs.Bitmap(createColorCanvas (canvasWidth,canvasHeight,'rgba(0,0,0,0.7)'));
	backImage.regX=canvasWidth/2;
	backImage.regY=canvasHeight/2;
	//上、空
	topImage=new createjs.Bitmap();
	container.addChild(backImage,topImage);
	stage.addChild(container);
	container.visible=false;

	//loadingコンテナを作る
	loadingcontainer=new createjs.Container();
	stage.addChild(loadingcontainer);
	//LOADINGを作る
	loadingShape=loadingIndicator3();//透過形
	loadingShape.x=canvasWidth/2;
	loadingShape.y=canvasHeight/2;
	//tickを設定
	loadingShape.tick=function (){
		if(loading) {
			loadingShape.rotation +=5;
		}
	}
	//loading addEventListenerを設定
	createjs.Ticker.addEventListener('tick',loadingShape.tick);
	//コンテナに貼り付け
	loadingcontainer.addChild(loadingShape);
	loadingcontainer.visible=false;
	loading=false;//loading表示判定

	//ProgressBar
	progresscontainer=new createjs.Container();
	progressbar=new createjs.Shape();
	progtext=new createjs.Text("0","12px Arial","#FFFFFF");
	progtext.x=0;
	progtext.y=15;
	progtext.maxWidth=80;
	progtext.textAlign="center";
	progtext.shadow=shadow;//shadow
	//alpha
	progressbar.alpha=0.5;

	//bar_v判定tickを設定(butt round)
	//90度是正-Math.PI/2
	progressbar.tick=function (){
		if(bar_v > 0) {
			progressbar.graphics.clear();
			progressbar.graphics.setStrokeStyle(8,"butt").beginStroke("#FF69B4");
			progressbar.graphics.arc(0,0,40,-Math.PI/2,Math.PI*2*bar_v-Math.PI/2);
			progtext.text=Math.floor(bar_v*100);
			stage.update();
		}
	}
	//addChild
	progresscontainer.x=canvasWidth/2;
	progresscontainer.y=canvasHeight/2;
	progresscontainer.addChild(progressbar,progtext);
	stage.addChild(progresscontainer);
	progresscontainer.visible=false;//非表示

	//レーヤー
	titlecontainer=new createjs.Container();
	//Overlayを作るを作る
	var overLay=new createjs.Shape();
	overLay.graphics.beginFill('rgba(0,0,0,0.5)').drawRect(0,0,canvasWidth,50);
	//簡易TITLE-TEXT
	//文字、サイズ、フォント、色、X、Y、maxWidth、lineHeight、Align、Baseline、name、陰影
	titletext=createText("","12px","Arial","#FFFFFF",20,20,canvasWidth-40,20,"left","bottom","text",true);
	//簡易OWNER-TEXT
	ownertext=createText("","12px","Arial","#FFFFFF",20,40,canvasWidth-40,20,"left","bottom","text",true);
	//
	titlecontainer.addChild(overLay,titletext,ownertext);
	titlecontainer.y=canvasHeight-50
	stage.addChild(titlecontainer);
	titlecontainer.visible=false;

	//アクションレーヤー
	actionlay=new createjs.Shape();
	actionlay.graphics.beginFill('rgba(0,0,0,0.01)').drawRect(0,0,canvasWidth,canvasHeight);//透過
	stage.addChild(actionlay);

	//アクション変更/ステージアクション少しへんだ
	actionlay.addEventListener('rollover',function(){
		titlecontainer.visible=true;
	});
	actionlay.addEventListener('rollout',function(){
		titlecontainer.visible=false;
	});
	//アクションレーヤー非表示
	actionlay.visible=false;

	//クローズボタン
	//X、Y、幅、高さ、角丸半径、背景色、ラベル、番号
	closeBtn=createTextbtn2 (0,0,50,20,5,"#AAAAAA","CLOSE",0);
	closeBtn.x=canvasWidth-30;
	closeBtn.y=15;
	closeBtn.cursor="pointer";
	stage.addChild(closeBtn);
	//クリックアクション設定
	closeBtn.addEventListener("click",closeBtnhandle);
	closeBtn.visible=false;

	//INPUT-OPENボタン
	//X、Y、幅、高さ、角丸半径、背景色、ラベル、番号
	openBtn=createTextbtn2 (0,0,50,20,5,"#AAAAAA","INPUT",0);
	openBtn.x=canvasWidth-30;
	openBtn.y=15;
	openBtn.cursor="pointer";
	stage.addChild(openBtn);
	//クリックアクション設定
	openBtn.addEventListener("click",openInputhandle);
	openBtn.visible=false;

	//簡易TEXT
	viewtext=createText("Flickr","12px","Arial","#FFFFFF",20,15,canvasWidth-40,20,"left","bottom","text",true);
	stage.addChild(viewtext);

	//データ件数表示
	if(flickr) {set_text(" Flickr読み込みデータ件数: "+loadItem);}
	stage.update();

	//Ticker設定
	createjs.Ticker.setFPS(30);
	createjs.Ticker.addEventListener('tick',tick);

	//調整
	setTimeout(function() {

		//スタート
		set_text("");
		//検索窓表示
		set_input();

	},1000);//1000-3000

}

//INPUT
function set_input() {

	//タグ名が旨く行かない場合あり
	set_text("キーワードを入力して「検索」ボタンを押してください。複数は半角スペースを入れる。");
	//set_text("タグ名を入力して「検索」ボタンを押してください。表示数選択可(10-40)");
	//表示
	search_panel.removeClass("hidden");
}
//INPUT-handle
function openInputhandle () {

	//OPEN-BTN
	openBtn.visible=false;
	set_input();

}
//searchキャンセル
function search_cancel () {

	set_text("");
	//非表示
	search_panel.addClass("hidden");
	//INPUT-OPENボタン
	openBtn.visible=true;
}

//searchスタート
function search_start() {

	//非表示
	search_panel.addClass("hidden");

	//ロード数補正
	loadImage_len=keep_len;

	//flickrクリア
	flickrthumbs=[];
	flickrImages=[];
	flickrLinks=[];
	flickrTitles=[];
	flickrOwners=[];

	flickr=false;
	flickrW=[];//小
	flickrH=[];
	flickrbigW=[];//大
	flickrbigH=[];
	loadItem=0;

	//jQuery value値取得
	//load数変更
	var len=$("select[name='select']").val()*1;
	if(loadImage_len !=len) {loadImage_len=len;}

	//入力キーワード取得
	tags_v=search_box.val();//TEXTで検索
	set_text("Flickr検索中 [ " + tags_v + " ]");

	//Flickr検索実行
	getFlickrData();//Flickr

}
//FlickrDataのセット
function set_flickrSearchData() {

	//INPUT-OPENボタン
	openBtn.visible=true;
	//読み込み画像result保存容器配列などクリア
	assets=[];
	thumb_assets=[];
	myBtn=[];
	//サムネール階層クリア
	btncontainer.removeAllChildren();

	//flickrFeed読み込み成功、画像ロードに進む
	if(flickr) {

		viewtext.x=20;
		viewtext.y=15;

		//flickrのmanifestリスト作成
		manifest=[];
		for (var i=0; i < flickrthumbs.length; i++) {
			var src=flickrthumbs[i];
			var id="PHOTO";
			manifest.push({
				src:src,
				id:id
			});
		}

		set_text("Loading Now!");
		bulkload();
	}
	//失敗
	if(!flickr) {
		viewtext.x=100;
		viewtext.y=canvasHeight/2;
		var mass="Flickrの読み込み失敗、表示出来ませんので停止します!";
		if(loadImage_len == 0) {mass="Tag検索結果が有りません、表示出来ませんので停止します!";}
		set_text(mass);
	}

	//openBtn表示
	openBtn.visible=true;

}

//progressBar
function progress(event) {

	//loadedのみ効く
	bar_v=event.loaded;
}

//bulk-load、画像一括ロード
function bulkload() {

	set_text("Loading Now!")
	//Ticker.Listener設定
	createjs.Ticker.addEventListener('tick',progressbar.tick);

	//Loading
	loadingcontainer.visible=true;
	loading=true;//loading表示判定
	//ProgressBar
	bar_v=0;
	progresscontainer.visible=true;//表示

	//Loaderを作る
	loader=new createjs.LoadQueue(false);
	//全体、progressがあれば先に設定
	loader.addEventListener("progress",progress);

	//loader EventListener設定
	loader.addEventListener("fileload",fileload);
	loader.addEventListener("complete",complete);
	//Manifestを使用、manifest読み込み開始
	loader.loadManifest(manifest);

}

//各画像読み込み完了
function fileload (event) {

	var id=event.item.id;
	//画像選別
	if (id == 'PHOTO') {
		//エラー無しの画像をassets容器に保存
		assets.push(event.result);
		thumb_assets.push(event.result);
	}
}
//全ての画像読み込み完了
function complete (event) {

	//画像数確認、再計算
	image_max=assets.length;
	//簡易TEXT
	set_text("Loading End!")
	//loader Listener削除
	loader.removeEventListener("fileload",fileload);
	loader.removeEventListener("complete",complete);
	//loading EventListenerは削除しない
	//非表示
	loadingcontainer.visible=false;
	loading=false;//loading表示判定

	//OWNER-LINKボタン
	if(ownerlink) {
		//X、Y、幅、高さ、角丸半径、背景色、ラベル、番号
		linkBtn=createTextbtn2 (0,0,90,20,5,"#AAAAAA","OWNER-LINK",0);
		linkBtn.x=canvasWidth-50;
		linkBtn.y=canvasHeight-15;
		linkBtn.cursor="pointer";
		stage.addChild(linkBtn);
		//クリックアクション設定
		linkBtn.addEventListener("click",ownerlinkhandle);
		linkBtn.visible=false;

	}

	//set_text(" " + image_max + "件の検索結果を表示します。");
	set_text(" [検索結果DATA数]/ " + loadItem + " [表示数] " + loadImage_len + "件の検索結果を表示します。");

	//画像があれば
	if (image_max) {

		//早すぎるので調整
		setTimeout(function() {

			//progress非表示
			progresscontainer.visible=false;

			//簡易TEXTクリア
			set_text("");
			//thumbBtnのセット
			set_thumbBtn();//停止

		},delay_speed);
	}

}

//thumbBtnのセット
function set_thumbBtn() {

	//サムネールボタンを作る
	for (var i=0; i < image_max; i++) {

		var bmp=new createjs.Bitmap(assets[i]);
		//大きさ取得保存
		flickrW.push(bmp.getBounds().width);
		flickrH.push(bmp.getBounds().height);

		//サムネールの大きさ
		var btnW=flickrW[i];
		var btnH=flickrH[i];
		//番号受け渡し
		var no=i;

		//アクションつきサムネール
		//X、Y、幅、高さ、角丸半径、色、HitBTN、HitBT色、画像、番号
		myBtn[i]=createDragThumbCenterbtn(0,0,btnW,btnH,btnR,"#FF0000",hitbtn,'rgba(0,0,0,0.01)',assets[i],no);//透過0.01

		//ランダム配置
		if(image_max > 1) {
			myBtn[i].x=Math.floor(Math.random()*(canvasWidth-btnW))+btnW/2;
			myBtn[i].y=Math.floor(Math.random()*(canvasHeight-btnH))+btnH/2;
		} else {
			//1つ場合中央に補正
			if(image_max == 1) {myBtn[i].x=canvasWidth/2;myBtn[i].y=canvasHeight/2;}
		}

		//傾ける/6以下は0に補正
		var angl=Math.floor(Math.random()*120)-60;
		if(Math.abs(angl) < 6) {angl=0;}
		myBtn[i].rotation=angl;

		//ボタン判別用のidを書き込む、未使用
		myBtn[i].id=i;
		//myBtn addChild
		btncontainer.addChild(myBtn[i]);

	}

	//FadeIn
	btncontainer.alpha=0;
	btncontainer.visible=true;//表示
	//TWEENの実行
	var tw=createjs.Tween.get(btncontainer)
	.to({alpha:1},1000);

}

//DRAW、アニメ
function draw() {

	globalflag=true;

	//MODE 0-1
	var mode=Math.floor(Math.random()*2);

	//imgloader画像をそのまま使用
	mainImage=imgloader;
	topImage.image=new createjs.Bitmap(mainImage).image;

	//上画像更新画像Bitmap挿入、中央補正なし回転は出来ない
	topImage.regX=flickrbigW[image_no]/2;
	topImage.regY=flickrbigH[image_no]/2;

	//スケール計算
	gscale=flickrW[image_no]/flickrbigW[image_no];

	//サムネールインスタンス位置角度で補正
	//移動位置Global-Point
	topImage.x=gpoint_x;
	topImage.y=gpoint_y;
	topImage.rotation=gangle;
	topImage.scaleX=topImage.scaleY=gscale;
	topImage.alpha=0;

	//TWEENの実行
	var tw=createjs.Tween.get(topImage)
	.to({x:0,y:0,scaleX:1,scaleY:1,rotation:0,alpha:1},speed)
	.wait(200)
	.call(finshtween);

}

//フェードアニメ完了
function finshtween () {

	closeBtn.visible=true;
	//アニメ作業中である
	globalflag=false;

	//少し遅延させる
	setTimeout(function() {

		//FlickrTitle
		set_titletext("TITLE: "+flickrTitles[image_no]);
		set_ownertext("OWNER: " + flickrOwners[image_no]);
		//パーツオープン
		partsCtrl(true);


	},500);

}

//tickステージ
function tick() {
	stage.update();
}

//VIEWTEXT
function set_text(t) {
	if (text_use == 'use') {
		viewtext.text=t;
	}
}
//TITLETEXT
function set_titletext(tt) {
	if (titletext_use == 'use') {
		titletext.text=tt;
	}
}
function set_ownertext(tt) {
	if (titletext_use == 'use') {
		ownertext.text=tt;
	}
}

//BtnClick/on/parent
function handleclick (event,no) {

	//ドラッグmoveしたときはアニメしない
	if (dragflag) {return}

	//OPEN-BTN
	openBtn.visible=false;
	//on
	var hit_no=no;

	//親インスタンス位置角度取得
	var instance=event.target.parent;
	//Point/btncontainerコンテナ基準Globalを修正保存
	//btncontainer原点左上
	var point=btncontainer.localToGlobal(instance.x,instance.y);
	//Global-Point/修正
	gpoint_x=point.x-canvasWidth/2;
	gpoint_y=point.y-canvasHeight/2;
	//角度取得
	gangle=instance.rotation;

	//指定番号の画像LOAD
	imageLoad(flickrImages[hit_no],hit_no);

}
//ジャンプボタン
function ownerlinkhandle (event) {
	//open
	window.open(flickrLinks[image_no],null);//blank
	//location.href=flickrLinks[image_no];//使い難い
	return false;
}

//ドラッグListener/アクション専用層に設定した
function press(event) {
	var instance=event.target.parent;
	//ドラッグ開始
	dragflag=false;//move判定
	mousePoint=instance.globalToLocal(event.stageX,event.stageY);
	//直接eventでは無くinstanceに
	instance.addEventListener("pressup",stopdrag);
	instance.addEventListener("pressmove",drag);
	//重ね順を一番上にする
	btncontainer.setChildIndex(instance,image_max-1);
}
function stopdrag(event) {
	var instance=event.target.parent;
	instance.removeEventListener("pressup",stopdrag);
	instance.removeEventListener("pressmove",drag);
}
function drag(event) {
	dragflag=true;//動いた時のみtrue
	var instance=event.target.parent;
	var offset=instance.localToGlobal(mousePoint.x,mousePoint.y);
	instance.x +=event.stageX-offset.x;
	instance.y +=event.stageY-offset.y;
	stage.update();
}

//クローズクリックアクション
//BtnClick/on
function closeBtnhandle (event) {

	partsCtrl(false);

	//TWEENの実行/先のGlobalポイントに戻る
	var tw=createjs.Tween.get(topImage)
	.to({x:gpoint_x,y:gpoint_y,scaleX:gscale,scaleY:gscale,rotation:gangle,alpha:0},speed*0.75)
	.wait(500)
	.call(function() {
		//画像コンテナ非表示
		container.visible=false;
		//OPEN-BTN
		openBtn.visible=true;
	});
}

//パーツ表示切り替え、open=trueで表示
function partsCtrl (open) {

	//ボタン
	closeBtn.visible=open;
	//OWNER-LINK
	if (ownerlink) {
		linkBtn.visible=open;
	}
	//アクションレーヤー
	actionlay.visible=open;

}



//imageLoader/1枚Load
function imageLoad(imgurl,no) {

	loadingcontainer.visible=true;
	loading=true;
	viewtext.text="Loading Now";

	imgloader=new Image();
	imgloader.onload=function() {
		//読み込みOK
		image_no=no;
		viewtext.text="";
		loadingcontainer.visible=false;
		loading=false;
		//WH
		flickrbigW[image_no]=imgloader.width;
		flickrbigH[image_no]=imgloader.height;

		//画像コンテナ表示
		container.visible=true;
		//画像表示
		setTimeout(function() {
			draw();
		},500)
	}
	imgloader.onerror=function() {
		//NG
		viewtext.text="ERROR";
		loadingcontainer.visible=false;
		loading=false;
	}
	imgloader.src=imgurl;
}

//文字center/middle
//文字、サイズ、フォント、色、X、Y、maxWidth、lineHeight、Align、Baseline、name、陰影
function createText (text,size,font,color,x,y,maxw,lineh,align,bline,txname,shadowf) {

	//TEXT
	var font_v=size + " " + font;
	var tx=new createjs.Text(text,font_v,color);
	tx.x=x;
	tx.y=y;
	tx.maxWidth=maxw;
	tx,lineHeight=lineh;
	tx.textAlign=align;
	tx.textBaseline=bline;
	tx.name=txname;//name挿入
	//shadow
	if(shadowf) {
		tx.shadow=new createjs.Shadow("#000000",0,0,4);
	}

	return tx;
}

//create-サムネールドラッグボタン
//X、Y、幅、高さ、角丸半径、色、HitBTN、HitBT色、画像、番号
function createDragThumbCenterbtn (x,y,w,h,r,acolor,btn_make,btncolor,img,no) {

	//BTNコンテナ
	var btn=new createjs.Container();
	btn.x=x;
	btn.y=y;
	var s=new createjs.Shape();
	//角丸画像挿入
	s.graphics.beginBitmapFill(img).drawRoundRect(x,y,w,h,r);//画像はクリック無効
	s.name="graphic";//name挿入
	//原点移動、グラフイックを容易にするため
	s.regX=w/2;
	s.regY=h/2;

	//アクション専用層
	var hits=new createjs.Shape();
	hits.graphics.beginFill(btncolor).drawRoundRect(x,y,w,h,r);//透過ボタン
	hits.name="click";//name挿入
	hits.regX=w/2;
	hits.regY=h/2;
	hits.cursor="pointer";
	//クリックアクション
	hits.on("click",handleclick,null,false,no);
	//ドラッグアクション/アクション専用層に
	hits.addEventListener("mousedown",press);
	btn.addChild(s,hits);
	btn.shadow=shadow;

	return btn;
}

//文字ボタン
//X、Y、幅、高さ、角丸半径、背景色、ラベル、番号
function createTextbtn2 (x,y,w,h,r,color,label,no) {

	//BTNコンテナ
	var btn=new createjs.Container();
	btn.x=x;
	btn.y=y;
	l=new createjs.Text(label,"12px Arial","#FFFFFF");
	l.maxWidth=w;
	l.textAlign="center";
	l.textBaseline="middle";
	l.name="text";//name挿入
	var s=new createjs.Shape();
	s.graphics.beginFill(color).drawRoundRect(x,y,w,h,r);
	s.name="back";//name挿入
	s.regX=w/2;
	s.regY=h/2;
	btn.addChild(s,l);
	btn.shadow=shadow;

	return btn;
}

//幅、高さ、画像
function createImgCanvas(w,h,patternimg) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.drawImage(patternimg,0,0,w,h);

	return canvas;
}

//色付きcanvasを作る
function createColorCanvas (w,h,c) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=c;
	ctx.fillRect(0,0,w,h);
	return canvas;
}

//FlickrCanvas
function createFlickrCanvas(w,h,img,img_w,img_h,scale_v,backcolor) {

	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=backcolor;
	ctx.fillRect(0,0,w,h);
	ctx.translate(w/2,h/2);
	ctx.drawImage(img,-(img_w*scale_v)/2,-(img_h*scale_v)/2,img_w*scale_v,img_h*scale_v);

	return canvas;
}

//簡単なLOADING3
function loadingIndicator3 () {

	//graphicのスタイル
	var graphics=new createjs.Graphics();
	graphics.setStrokeStyle(2,"round");//round

	//描画データ
	var alpha_v=1;//透明度
	var alphaback;

	var cx,cy;
	var numNeedles=12;
	var innerR=15;
	var outerR=10;
	var cAngle=-Math.PI/2;
	var nAngle;

	//ライン描画
	nAngle=Math.PI*2/numNeedles;
	for (var i=0; i < numNeedles; i++){

		//回転補正
		rotateflag=cAngle -=nAngle;
		//透明度を描画毎に変更
		if (i > 0) {alpha_v -=0.05;}

		//#CCCCCC
		alphaback=createjs.Graphics.getRGB(204,204,204,alpha_v);
		cx=Math.cos(cAngle)*innerR;
		cy=Math.sin(cAngle)*innerR;
		graphics.beginStroke(alphaback).moveTo(cx,cy);
		cx=Math.cos(cAngle)*outerR;
		cy=Math.sin(cAngle)*outerR;
		graphics.lineTo(cx,cy);

	}
	//Shapeに格納
	var s=new createjs.Shape(graphics);
	return s;
}

//jQuery-getJSON
function getFlickrData(){

	//https重要
	var FlickrAPI="https://api.flickr.com/services/rest/?jsoncallback=?";

	$.getJSON(FlickrAPI,{

		method:"flickr.photos.search",
		api_key:"32dbd23f3f7e6d0ae494b99eebb57c93",
		per_page:100,
		extras:"owner_name",
		text:tags_v,
		format:"json"
	})
	.done(function(data){

		//var json_text=JSON.stringify(data);
		//$("#logtext").text(json_text);

		flickr=false;
		var photos=data.photos.photo;
		//検索item数エラー処理
		var item_len=photos.length || 0;
		loadItem=item_len;//データ数保存
		//補正
		if(item_len < loadImage_len){loadImage_len=item_len;}

		//DATAがあれば
		if(item_len > 0) {

			//シャッフル配列に数字を入れるphotos.length
			var arr_no=[];
			for(var i=0; i < photos.length; i++){
				arr_no.push(i);
			}
			//配列をシャッフル/0はエラー
			arr_no.sort(function() {return Math.random()-0.5;});

			for(var i=0; i < photos.length; i++){

				var no=arr_no[i];

				var farmId=photos[no].farm;
				var serverId=photos[no].server;
				var id=photos[no].id;
				var secret=photos[no].secret;
				var title=photos[no].title;
				var owner=photos[no].owner;
				var ownername=photos[no].ownername;

				var thumb_url="https://farm" + farmId + ".staticflickr.com/"+ serverId +"/" + id + "_"+ secret +"_t.jpg";
				var img_url="https://farm" + farmId + ".staticflickr.com/"+ serverId +"/" + id + "_"+ secret +"_z.jpg";
				var link_url="https://www.flickr.com/photos/" + owner +"/" + id;

				//画像保存
				flickrthumbs.push(thumb_url);
				flickrImages.push(img_url);
				flickrTitles.push(title);
				flickrLinks.push(link_url);
				flickrOwners.push(ownername);
				//定量break
				if(i == loadImage_len-1){break;}

			}
			flickr=true;

		} else {
			flickr=false;
			loadImage_len=0;
		}

		set_flickrSearchData();

	})
	.fail(function(){
		flickr=false;
		set_flickrSearchData();
	});
}

//---------------------------------------------------------------------------------------------

//START
window.onload=function() {
	init();

}

注釈文を削除すれば、幾分早くなります。未使用の関数なども含みます。
画像使用の場合、登録画像パスは当方の例です。使用の際は環境に合わせて下さい。


CSS

createJS115.css、CSS名は任意に変更可


/*日本語 createJS115.css*/

#demo-wrap {
position:relative;
width:auto;
height:720px;
text-align:center;
}

#image-box {
/*position:absolute;*/
position:relative;
top:0;left:0;
width:640px;
height:640px;
padding:0;
margin:0 auto;
box-shadow:0 0 10px #000;
-moz-box-shadow:0 0 10px #000;
-webkit-box-shadow:0 0 10px #000;
-o-box-shadow:0 0 10px #000;
-ms-box-shadow:0 0 10px #000;
background-color:#000000;
}

#image-box #mainCanvas {
border-radius:10px;
}
.radius {
border-radius:10px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
-o-box-border-radius:10px;
-ms-border-radius:10px;
}

#searchPanel{
position:absolute;
left:10px;
top:25px;
display:block;
width:auto;
height:25px;
padding:2px 5px 0 5px;
text-align:left;
font-size:12px;
color:#FFFFFF;
background-color:#555555;
float:left;
}
#image-box .hidden {
display:none;
}
#searchBox{
width:180px;
}

当方のサンプルの例です。


 

簡単な説明


[説明図]

 

photos.search メソッドのキーワード検索ビューアー


flickrAPIの photos.search メソッド を利用し、キーワード検索します。原則、JSON形式のデータを得ます。


1. photos.search メソッドですから「FlickrAPIキー」が必要になります。
2. Canvas表示のために問題がおき易い。(通常のHtml表示の方が何かと簡単です)
3. 問題点などは、下記「前ページ」などを参照ください。
4.「Touch」には対応していませんので、自己解決ください。


基本的には、下記「前ページ」のJSを改造したものです。

【参照】当方の記事: CreateJS FlickrAPI jQuery.getJSON画像表示とオーナーページにリンク

photos.search メソッド利用のjQuery.getJSON画像表示に関しては下記ページに詳細が有ります。

【参照】当方の記事: CreateJS FlickrAPI photos.search メソッド利用のjQuery.getJSON画像表示


構造

構造的には、下図の様になり「入力画面」が増えただけになります。

 

1. サムネールはボタンをステージに移動して利用しています。
2. 拡大画像は、透過背景と共にコンテナに収容しています。透過背景は大型画像表示中に下層のサムネールのアクションを遮断します。
3. タイトルをステージHOVERで表示するに、クロスドメイン大型画像の為ステージにアクション設定出来ず、上層にアクションレーを配置してそこにアクション設定しています。
4. 入力画面はHTMLで作り、jQueryで操作しています。


ドラッグとクリックアクション

クロスドメイン画像、または、その画像を含む「インスタンス」に「クリック」など設定してもセキュリティの関係で無効になる。そのため下図の様に構造を変えて対処している。(1つの「Shapeインスタンス」ではダメなので、2重になっている)


クロスドメイン画像のために、サムネール全体の「ドラッグ」と「クリック」が反応しません。
そのために、サムネールShape() の上にイベント処理専用の Shape() を重ねて、この層に「イベント」を設定しました。当然「ドラッグ」もこの層に設定しています。

また、「ドラッグ」の pressup の際に「クリック」イベントが反応するために、変数dragflagで状況を判断して処理しています。dragflag=trueならドラッグ、dragflag=falseならクリックの判定です。

「クリック」はゆっくり操作します。慌てると「ドラッグ」になってしまいます。


● サムネールドラッグボタンのアクション設定

通常ならば、myBtn[i] にアクション設定をするが、クロスドメイン画像を含むために、設定しても機能しない。
アクションによっては機能するものもあるが、一旦設定してみて、機能しないなら別の方法を取る。(面倒だ)


//thumbBtnのセット
function set_thumbBtn() {

	//サムネールボタンを作る
	for (var i=0; i < image_max; i++) {

		略す

		//アクションつきサムネール
		//X、Y、幅、高さ、角丸半径、色、HitBTN、HitBT色、画像、番号
		myBtn[i]=createDragThumbCenterbtn(0,0,btnW,btnH,btnR,"#FF0000",hitbtn,'rgba(0,0,0,0.01)',assets[i],no);//透過0.01
		//これは機能しない
		myBtn[i].on("click",handleclick,null,false,i);

		略す

	}

	略す

}

そこで下記では、Shapeである hits にアクションを設定する。これはクロスドメイン画像を含ま無いので機能する。
但し、下層に画像層がある為に、着色を透明度 0.01 にしてある。透明度0.01以下ではアクションが効かない。(理想的には 0 にしたいのだが.....、画像は見た目変わらない)
つまりは苦し紛れの「ゴマカシ」である。


//create-サムネールドラッグボタン
//X、Y、幅、高さ、角丸半径、色、HitBTN、HitBT色、画像、番号
function createDragThumbCenterbtn (x,y,w,h,r,acolor,btn_make,btncolor,img,no) {

	//BTNコンテナ
	var btn=new createjs.Container();

	略す

	//アクション専用層
	var hits=new createjs.Shape();
	hits.graphics.beginFill(btncolor).drawRoundRect(x,y,w,h,r);//透過ボタン
	hits.name="click";//name挿入
	hits.regX=w/2;
	hits.regY=h/2;
	hits.cursor="pointer";
	//クリックアクション
	hits.on("click",handleclick,null,false,no);
	//ドラッグアクション/アクション専用層に
	hits.addEventListener("mousedown",press);
	btn.addChild(s,hits);
	btn.shadow=shadow;

	return btn;
}

● ドラッグListener

ドラッグListenerは、下記「HTML5テクニカルノート」さんのものを修正使用しました。一番信頼性があると思います。

【参考】HTML5テクニカルノートの記事: EaselJS 0.7.0でインスタンスをドラッグドロップする



var dragflag=false;

--------------------------------------------------------------

//ドラッグListener/アクション専用層に設定した
function press(event) {
	var instance=event.target.parent;
	//ドラッグ開始
	dragflag=false;//move判定
	mousePoint=instance.globalToLocal(event.stageX,event.stageY);
	//直接eventでは無くinstanceに
	instance.addEventListener("pressup",stopdrag);
	instance.addEventListener("pressmove",drag);
	//重ね順を一番上にする
	btncontainer.setChildIndex(instance,image_max-1);
}
function stopdrag(event) {
	var instance=event.target.parent;
	instance.removeEventListener("pressup",stopdrag);
	instance.removeEventListener("pressmove",drag);
}
function drag(event) {
	dragflag=true;//動いた時のみtrue
	var instance=event.target.parent;
	var offset=instance.localToGlobal(mousePoint.x,mousePoint.y);
	instance.x +=event.stageX-offset.x;
	instance.y +=event.stageY-offset.y;
	stage.update();
}

● クリックListener

1つの層に2つのListener設定のため、以下の様に、クリックアクションの補正をしています。


//BtnClick/on/parent
function handleclick (event,no) {

	//ドラッグmoveしたときはアニメしない
	if (dragflag) {return}

	略す

}

他にも方法はあると思いますが、考えると頭が胃痛、腸ねん転になるので止めとく。
尚、サムネール画像は小さなもの(100サイズ)を取得して、スケール変更は行っていません。


大きな画像は、new Image() で読み込み処理

サムネール画像はLoadQueue()で一括世に込み、大きな画像はjavascriptの、new Image() で其の都度読み込み処理しています。そのため Loading も其の都度「表示、非表示」処理した。


キーワード検索

キーワード検索にしろ、タグ検索にしろ、情報が少なくイマイチ判らないことが多い。一応、下記の様にjQueryで「返ってきたjsonデータ」を表示して確認を取りながら作業を進めた。(コンソールに表示する事も出来ると思いますが....)
検索の条件が悪ければ当然表示しませんし。検索数が少なければヒットしない確率が大きい。
Flickrからの返り値はオブジェクトだから、JSON.stringify()で変換すれば表示出来る。


● キーワード入力

この辺、当方でも「アヤフヤ」ですので、試してください。表示出来なければ、条件を変えればよいのですが....

検索出来ない場合は、入力値を変更して再度実行して下さい。


複数設定は難しいので1つ設定

北陸新幹線
---------------------------------------
2つ設定、一応OK

北陸新幹線 東北新幹線
---------------------------------------
なぜかNGに成るとき有り、不安定

北陸新幹線 東北新幹線 新幹線
---------------------------------------
なぜかOK、外国の場合Shinkansenと書いているせいかな

北陸新幹線 東北新幹線 Shinkansen

● 検索戻り数の指定

getJSONの設定で「検索数」を指定出来ますが、少ない場合は「検索条件」を変えても余り変化がありません。
(ドラッグの関係で重くなるため、余り多くは表示したくは無いのが本音)
検索数が少なければ、処理が早くなるし、検索数を多くしてシャッフルすれば、表示に多少は変化を付けることが出来るようです。

デモJSの場合は検索数100にして、シャッフルして、指定の表示数で処理しました。



検索数を指定(デモJSの場合)
per_page:100,

検索数を表示数で指定(変更可能)
per_page:loadImage_len,

per_pageを省略すれば100の指定と同じ

● jQueryでのデータの表示確認

返り値はオブジェクトなので下記の様に変換してやる。
検索できない場合などの出力が見れるので、処理するに当たり確認は重要である。


html側

<div id="logtext" style="word-wrap:break-word;"></div>

-------------------------------------------------------------------------
JS側

	.done(function(data){

		var json_text=JSON.stringify(data);
		$("#logtext").text(json_text);

		略す

	}
------------------------------------------------------------------------
表示例

{"photos":{"page":1,"pages":198,"perpage":10,"total":"1971","photo":[{.......}]},"stat":"ok"}

● コンソールでのデータの表示確認

返り値はオブジェクトなので下記の様に変換してやる。(IEは全部見れない)



JS側

	.done(function(data){

		var json_text=JSON.stringify(data);
		console.log(json_text);

		略す

	}
------------------------------------------------------------------------
コンソール表示例

{"photos":{"page":1,"pages":198,"perpage":10,"total":"1971","photo":[{.......}]},"stat":"ok"}

入力キーワードの処理

入力キーワードは一旦、tags_v に取り込んでから処理していますが、セキュリティ上からは直接取り込んだ方が良いかも知れません。私この辺詳しくは有りませんが...


事前にjQueryオブジェクト化
search_box=$("#searchBox");

//入力キーワード取得
tags_v=search_box.val();//TEXTで検索

//getJSON処理
$.getJSON(FlickrAPI,{

	略す

	text:tags_v,
	format:"json"
})

-----------------------------------------------------------------------

直接取り込込む

$.getJSON(FlickrAPI,{

	略す

	text:search_box.val(),
	format:"json"
})

● タグ検索への変更

この「デモ」では「キーワード検索」ですが「タグ検索」に変更は簡単です。
タグモードおよびタグモード切り替えradioボタンを追加して、Flickerに「タグ検索」でアクセスするだけです。


HTMLタグモード切り替えボタン
<input type="radio" name="radio" value="any" checked="checked"> OR <input type="radio" name="radio" value="all"> AND

JS tagmode_vは未使用ですでにある
var tagmode_v="any";
直接指定するなら
tag_mode:tagmode_v

jQueryのオブジェクトで代入するなら

$.getJSON(FlickrAPI,{

	略す

	tags:search_box.val(),
	tag_mode:$("input[name='radio']:checked").val(),
	format:"json"
})

次回、次のページで実際に作りテストしてみます。


サムネールドラッグボタンの注意

サムネールの画像は、graphics.beginBitmapFill() で処理していますので、Matrixでスケール変更しないで下さい。
Chromeで陰影が壊れます。(エレメントでスケール処理すれば、防げる)


	var s=new createjs.Shape();
	//角丸画像挿入
	s.graphics.beginBitmapFill(img).drawRoundRect(x,y,w,h,r);//画像はクリック無効

複雑怪奇

色々な機能を加えました為、また、クロスドメイン画像の影響の為に事の外判り難くなっています。
「複雑怪奇」は顔だけにして、少し見通しの良いようにしたいが「其のうち」にしておきます。所詮、分類学上「恥さらしスクリプト」です。


これでは、クロスドメイン画像Canvas表示のコンテンツなど作りたくない。「イヤヨ、イヤイヤ」、これは本音である。


photos.search メソッド利用の類似記事です。下記を参照ください。

【参照】当方の記事: CreateJS FlickrAPI jQuery.getJSON画像表示とオーナーページにリンク

【参照】当方の記事: CreateJS FlickrAPI photos.search メソッド利用のjQuery.getJSON画像表示



一応、完動しますが全てテストです。効率化のため、予告無くJSなど修正する場合がありますので了承下さい。

CreateJSは結構「仕様」が変わりますので特に注意が必要です。


 

アタマが「変態性高気圧」で覆われ、北からは「冬将軍」がやって来ました。間で雷雲が発生して混乱しています。そんなアリキタリな日常で有ります。
以上です。

 


[ この記事のURL ]


 

ブログ記事一覧

年別アーカイブ一覧



[1]