SQLの窓

2018年02月12日


自サイト(logical error を含む)で使用している SyntaxHighlighter のツールバーの問題点をごっそり自前で修正・カスタマイズしました。( その2 / ソースをクリップボードにコピー )

関連する記事

自サイト(logical error を含む)で使用している SyntaxHighlighter のツールバーの問題点をごっそり自前で修正・カスタマイズしました。( その1 / ソースの表示 )



SyntaxHighlighter でソースコードをクリップボードへコピーしていたのは、元々は Flash でした。現在はHTML のボタンに差し替えていますが、昔は object 要素が埋め込まれていました。なので、差し替え方法としては object のあった場所に button を作成する事になります。

元々、innerHTML の中に文字列をセットしていただけなので、特別な問題無く差し替える事ができています。問題は、クリップボードの処理をどのように実装するかというところが重要ですが、これは clipboard.js というライブラリを使用する事によって、IE11 という面倒なブラウザの対応も容易になっています。

以下のサンプルでは、innerHTML 以外の方法として、jQuery と document.write による実装を行っています。パターンが4つあるのは、JavaScript 内で日本語記述をしないようにコード化を行っています。HTMLエンティティのほうは、ブラウザに表示される時に日本語表現となります。unicode 文字列は、JavaScript が文字列として読み込んだ瞬間に日本語表現になります。
( ※ SyntaxHighlighter 内の既存ソース内へ追加する為、日本語を使用しないようにしています。 )

この場合どちらも結果は同じですが、JavaScript では 後者が重要です。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.12/clipboard.js"></script>
<script>
$(function () {

	// jQuery でボタン作成
	$(html1).appendTo(document.body);
	$(html2).appendTo(document.body);

	// クリップボード用のトリガーとなる要素が持つクラスを決定する
	// ( ボタンにこのクラスをセットしておく )
	var clipboard = new Clipboard('.my_clipboard');

	// ボタンのイベントで、クリップボード転送用のエリアへデータを送る
	// ( ボタンに data-clipboard-target で、エリアの id をセットしておく )
	$(".my_clipboard").on("click", function(){
		var time = (new Date()).getTime();
		console.log(time);
		$("#target_clipboard").text(time);
	});

	// それに対するクリップボードへコピー後の処理( 無くてもいい )
	clipboard.on('success', function(e) {
		e.clearSelection();
		alert("クリップボードにコピーしました");
	});

});

var html1 = "<button style='vertical-align:top;border-radius:4px;height:16px;line-height:8px;' class=\"my_clipboard\" data-clipboard-target=\"#target_clipboard\" title=\"&#12463;&#12522;&#12483;&#12503;&#12508;&#12540;&#12489;&#12408;&#12467;&#12500;&#12540;&#12375;&#12414;&#12377;\">copy1</button>"

var html2 = "<button style='vertical-align:top;border-radius:4px;height:16px;line-height:8px;' class=\"my_clipboard\" data-clipboard-target=\"#target_clipboard\" title=\"\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3078\u30b3\u30d4\u30fc\u3057\u307e\u3059\">copy2</button>"

var html3 = "<button style='vertical-align:top;border-radius:4px;height:16px;line-height:8px;' class=\"my_clipboard\" data-clipboard-target=\"#target_clipboard\" title=\"&#12463;&#12522;&#12483;&#12503;&#12508;&#12540;&#12489;&#12408;&#12467;&#12500;&#12540;&#12375;&#12414;&#12377;\">copy3</button>"

var html4 = "<button style='vertical-align:top;border-radius:4px;height:16px;line-height:8px;' class=\"my_clipboard\" data-clipboard-target=\"#target_clipboard\" title=\"\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u3078\u30b3\u30d4\u30fc\u3057\u307e\u3059\">copy4</button>"

// ボタンを文字列として出力して作成
document.write(html3);
document.write(html4);

</script>

<div id="target_clipboard" style='position:absolute;left:-1000px;width:900px;white-space:pre-wrap;word-wrap:break-word;'></div>
※ ボタンは、copy3 copy4 copy1 copy2 という順序で作成されます。

jQuery の $(function(){}) は、ページがロードされた後に実行されるので、まず copy3 と copy4 が作成されます。その後、$(function(){}) の最初にある記述で、copy1 と copy2 が作成されます。そして、それぞれに対してクリップボードのオブジェクトと、クリックイベントを関係付けています。



posted by lightbox at 2018-02-12 19:41 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2018年02月02日


自サイト(logical error を含む)で使用している SyntaxHighlighter のツールバーの問題点をごっそり自前で修正・カスタマイズしました。( その1 / ソースの表示 )

2018/02 : 更新
1) 行番号部分をクリックするとソースを選択するようにしました。
2) 表示時にテキストエリアにフォーカスを移すようにしました。
3) コピー操作をしやすいように、テキストエリア内に padding-left を入れました。
4) ツールバーの不透明度を 0.5 => 0.8 に変更しました。
5) ツールバーに対する border の CSS を変更して見えやすくしました。
そもそも、SyntaxHighlighter を配布していたサイトが GitHub に移った上、バージョン4 になってるけれど、いろいろ一般的には面倒な事になってるので、古いバージョンを一生懸命使って来た... というのが現実でした。 しかし、ここに来て行単位を取り出す『ソースの表示』がしょぼい事や、クリップボードへコピーするのが Flash だったとか、印刷表示ができていない(理由は解ったので対応済み)とか、about のリンク先が終わってるとか、ロクでも無い現状を打破しました。 これらは、オリジナルの処理を書き換えるという方法で行ってます。マイナーバージョンが上がった際にあった shLegacy.js というスクリプトで実装できます。解る人はこのサイトのソースを見てもらってコピーすれば使えます。但し、ウチのバージョンは 2.0.296 なんで、世の中的には難しいでしょうけれど。
ありがたいことに、WEB アーカイブからダウンロードできました。

※ 他のバージョンも可能です。
※ ライセンスは GNU Lesser General Public License
ソースの表示 行番号対応しました。これは、JQuery Lined TextArea plugin というプラグイン使ってます。行番号だけあれば十分なので、既に開発も終わってる古いソフトですが、 MIT License だしソースは短いし、自分でどうにでもアップグレードできそうなので使う事にしました。 ▼ ウインドウを最大化した時に行番号を表示するという処理を、jquery-linedtextarea.js の中に追加しています( ソースはこれです )

			$(window).resize( function(){
				var domTextArea	= textarea[0];
				var scrollTop 		= domTextArea.scrollTop;
				var clientHeight 	= domTextArea.clientHeight;
				codeLinesDiv.css( {'margin-top': (-1*scrollTop) + "px"} );
				lineNo = fillOutLines( codeLinesDiv, scrollTop + clientHeight, lineNo );
			});
ただ、textarea を使うので、ウインドウを最大化した時の幅や高さの調整は自分で外から追加する必要がありました。



▼ 組み込んだ内容
SyntaxHighlighter.toolbar.items.viewSource = function(highlighter)
{
	this.create = function()
	{
		return "\u884c\u756a\u53f7\u4ed8\u304d\u30c6\u30ad\u30b9\u30c8\u30a8\u30ea\u30a2\u3067\u30bd\u30fc\u30b9\u3092\u8868\u793a\u3057\u307e\u3059";
	};
	
	this.execute = function(sender, event, args)
	{
		var wnd = SyntaxHighlighter.utils.popup('', '_blank', 750, 400, 'location=0, resizable=1, menubar=0, scrollbars=1')
			;
		
		var code = SyntaxHighlighter.utils.unindent(
			SyntaxHighlighter.utils.fixForBlogger(highlighter.originalCode)
				.replace(/&lt;/g, '<')
				.replace(/&gt;/g, '>')
				.replace(/&amp;/g, '&')
				.replace(/\n/g, '\n')
			);
		code = SyntaxHighlighter.utils.unindent(code);
		
var str="";
str+="<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> ";
str+="<"+"script src=\"https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js\"></"+"script> \n";
str+="<"+"script src=\"https://lightbox.sakura.ne.jp/homepage/jquery/plugins/jquery-linedtextarea.js\"></"+"script> \n";
str+="<link id=\"link\" rel=\"stylesheet\" href=\"https://lightbox.sakura.ne.jp/homepage/jquery/plugins/jquery-linedtextarea.css\"> \n";
		wnd.document.write(str);

		wnd.document.write('<t'+ 'extarea readonly style="width:100%;height:350px">' + code + '</' + 'textarea>');

str="";
str+="<"+"script> \n";
str+="$(function() { \n";
str+="	$(\"textarea\").linedtextarea(); \n";
str+="	$(\".linedwrap\").css({\"width\":\"calc(100% - 20px\"}); \n";
str+="	$(\".lines\").css({\"height\":\"calc(100% - 20px)\"}); \n";
str+="	$(\"textarea\").css({\"width\":\"calc(100% - 80px)\", \"padding-left\":\"10px\"}); \n";
str+="	$(\"textarea\").css({\"height\":\"calc(100% - 20px)\"}); \n";
str+="	$(\"head\").append($(\"<title>\").text(\"\u30bd\u30fc\u30b9\u306e\u8868\u793a\")); \n";
str+="	$(\".codelines\").on(\"click\", function(){ $(\"textarea\").select() } ); \n";
str+="	$(\"textarea\").focus(); \n";
str+="}); \n";
str+="</"+"script> ";
		wnd.document.write(str);
		wnd.document.close();
	};
};

何も無いところに動的にいろいろやる必要があるので、document.write は仕方無いので使っています。
 document.write だけに関して言えば、将来性はそのへん疑問はありますが、当面しばらく大丈夫だと思ってます。

内容としては、動的に jQuery を書き出して、さらに jQuery のコードも書き出す事になってます。

高さと幅の調整は jQuery の部分の、本体とその親要素に対して calc を使って 100% から補正するというテクニックでやっています。

▼ 補正部分のみ取り出すとこうなります
<script> 
$(function() { 
	$("textarea").linedtextarea(); 
	$(".linedwrap").css({"width":"calc(100% - 20px"}); 
	$(".lines").css({"height":"calc(100% - 20px)"}); 
	$("textarea").css({"width":"calc(100% - 80px)"}); 
	$("textarea").css({"height":"calc(100% - 20px)"}); 
	$("head").append($("<title>").text("ソースの表示")); 
	$(".codelines").on("click", function(){ $("textarea").select() } ); 
	$("textarea").focus(); 
}); 
</script>

次は、クリップボードのお話です

自サイト(logical error を含む)で使用している SyntaxHighlighter のツールバーの問題点をごっそり自前で修正・カスタマイズしました。( その2 / ソースをクリップボードにコピー )


以下は、一般的なコードサンプルになります
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>

$(function(){

	$("#open_window").on("click", function(){

		code = $("#code").val();

		var wnd = win_open("","_blank",750, 400, "location=0,resizable=1,menubar=0,scrollbars=1");

var str="";
str+="<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"> ";
str+="<"+"script src=\"https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js\"></"+"script> \n";
str+="<"+"script src=\"https://lightbox.sakura.ne.jp/homepage/jquery/plugins/jquery-linedtextarea.js\"></"+"script> \n";
str+="<link id=\"link\" rel=\"stylesheet\" href=\"https://lightbox.sakura.ne.jp/homepage/jquery/plugins/jquery-linedtextarea.css\"> \n";
		wnd.document.write(str);

		wnd.document.write('<t'+ 'extarea readonly style="width:100%;height:350px">' + code + '</' + 'textarea>');

str="";
str+="<"+"script> \n";
str+="$(function() { \n";
str+="	$(\"textarea\").linedtextarea(); \n";
str+="	$(\".linedwrap\").css({\"width\":\"calc(100% - 20px\"}); \n";
str+="	$(\".lines\").css({\"height\":\"calc(100% - 20px)\"}); \n";
str+="	$(\"textarea\").css({\"width\":\"calc(100% - 80px)\", \"padding-left\":\"10px\"}); \n";
str+="	$(\"textarea\").css({\"height\":\"calc(100% - 20px)\"}); \n";
str+="	$(\"head\").append($(\"<title>\").text(\"\u30bd\u30fc\u30b9\u306e\u8868\u793a\")); \n";
str+="	$(\".codelines\").on(\"click\", function(){ $(\"textarea\").select() } ); \n";
str+="	$(\"textarea\").focus(); \n";
str+="	$(\"body\").css({\"overflow-y\":\"y:hidden\"}); \n";
str+="}); \n";
str+="</"+"script> ";
		wnd.document.write(str);
		wnd.document.close();

	});

});

function win_open(url, name, width, height, options)	{
	var x = (screen.width - width) / 2;
	var y = (screen.height - height) / 2;
	options +=
		', left=' + x + 
		', top=' + y +
		', width=' + width +
		', height=' + height
	;
	// 先頭のカンマを取り除く
	options = options.replace(/^,/, '');

	var win = window.open(url, name, options);
	win.focus();
	return win;
}
</script>
<input id="open_window" type="button" value="window を開く">
<br>
<textarea id="code" style='width:400px;height:300px'></textarea>




posted by lightbox at 2018-02-02 14:31 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2018年01月29日


JavaScript の内部コード文字列を SHIFT_JIS としてダウンロードさせる方法

SyntaxHighlighter カスタマイズ

SyntaxHighlighter のツールバーの右端のアイコンでファイルをダウンロードさせると、テキストのキャラクタセットは UTF-8 になります。通常はそれでもいいのですが、VBScript をダウンロードしてもらう場合は SHIFT_JIS である必要があるので、なんとかならないかと調べてみてすぐ見つけたのが

javascriptで文字コード変換

という Qiita の記事でした。その中で紹介されている ecl.js は、自分も以前使った事があったのですが、バイナリデータとして変換する目的では無いと記憶していました。ですが、一応記事の冒頭にあるコードでテストしてみましたがうまく行かず、Encoding.js のほうを使用して目的を達成しました。

Encoding.js

元々、バイナリの配列にデータを格納して変換しているので、文字列からの変換処理さえあればすぐ使えます。その関数は、Qiita の記事に既に紹介されていたのでとても簡単に実装する事ができました。

実装では、改行コードの扱いに留意して下さい。

サンプルコード
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>
<script src="https://lightbox.sakura.ne.jp/homepage/js/encoding.js"></script>

<script>
var str2array = function(str) {
    var array = [],i,il=str.length;
    for(i=0;i<il;i++) array.push(str.charCodeAt(i));
    return array;
};
var str   = "あいうえお";
var array = str2array( str );
var sjis_array = Encoding.convert(array, "SJIS", "UNICODE");
var sjis_data = new Uint8Array(sjis_array);

saveAs(
	new Blob(
		[sjis_data]
		, {type: "text/csv;charset=shift_jis"}
	)
	, "shift_jis.txt"
);

</script>
※ テストはこちらから行えます(ここで copy してリンク先で貼り付けて実行して下さい)

関連する記事

ブラウザ上のテキストデータを名前を付けて保存できる FileSaver.js を使って、テーブルのデータを Excel で開ける事を想定した CSV にして PC に保存

ファイルを JavaScript から保存する FileSaver.js

FileSaver.js は saveAs メソッドを提供します。ダウンロードする必要は無く、cdnjs でホスティング されています。

Uint8Array


posted by lightbox at 2018-01-29 14:10 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

ブラウザ上のテキストデータを名前を付けて保存できる FileSaver.js を使って、テーブルのデータを Excel で開ける事を想定した CSV にして PC に保存

デモページ



ダウンロードは必要ありません。cdnjs でホスティングされています。ただ、使い方がイマイチ解りにくいのが難点でした。GitHub の demo.js を読んで初めて使い方が解ります。

FileSaver.js は saveAs メソッドを提供します

テキストデータをダウンロードするには、ブラウザが一般的に提供する Blob クラスを使う必要があります。そのインスタンスを saveAs メソッドに引き渡して目的が達成されます。( canvas を使って画像も保存できますが、話がややこしくなるのでここでは触れていません / ※ canvas-toBlob.js が必要です )


ソースコード
$(function() {

	$("#getcsv").on( "click", function(){

		var csv = "";

		$("table").find("th").each(function( index ){
			if ( index != 0 ) {
				csv += ",";
			}
			csv += '"' + $(this).text() + '"';
		});
		csv += "\n";

		var cnt = 0;
		$("table").find("tr").each( function(){

			// TH の最初の一行は処理しない )
			if ( cnt > 0 ) {

				$(this).find("td").each(function( col_cnt ){
					if ( col_cnt != 0 ) {
						csv += ",";
					}

					if ( col_cnt == 0 ) {
					// Excel で文字列をそのまま取り込めるように( 例. 0001 を文字列として扱う )
						csv += "=\"" + $(this).text() + "\"";
					}
					else {
						csv += "\"" + $(this).text() + "\"";
					}
				});
				csv += "\n";
			}

			cnt++;

		} );

		// UTF-8 の CSV を化けずに Excel で開く為
		var bom = new Uint8Array([0xEF, 0xBB, 0xBF]);
		saveAs(
			new Blob(
				[bom,csv]
				, {type: "text/csv;charset=" + document.characterSet}
			)
			, "syain.csv"
		);

	} );

});

Excel で正しく表示する為に

ブラウザ上のデータは UTF-8 を想定しています。なのでそのまま単純に保存してしまうと、Excel が SHIFT_JIS を想定して読み込むので化けてしまいます。そこで、テキストの先頭に BOM をセットして、UTF-8 である事を Excel に知らせてやる必要があります。
2014-11-29 バージョンでは、自分で BOM を設定する必要がありましたが、2016-06-16 バージョンでは内部に auto_bom という処理があり、XML か text のタイプで キャラクタセットが utf-8 の場合は自動で BOM を追加してくれます。

BOM が必要ない場合は、第三引数(ファイル名の次)に true を指定するといいようになっています。
その他、"0001" という文字列をそのまま使えるように、="0001" という形で CSV のフィールドにセットしています。こうした状態で Excel に読み込むと、式の値が文字列であるようになります。Excel としてはかなり特殊な扱いのデータになりますが、Excel として保存してからあらためて .CSV として保存するとフィールドの値は単純な 0001 となります。 Uint8Array
posted by lightbox at 2018-01-29 14:08 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

JavaScript のみで、SHIFT_JIS や EUC-JP を UrlEncode に近い Escapeする Escape Codec Library

オリジナルはVector からダウンロードできる事を確認しました。しかし、実際は ecl.js と Sleipnir の相性が悪い件について という記事があり、そちらで新しいものが配布されています。

とりあえずこちらにも用意しました。
ecl_new.txt

内容は単純に変換関数がグローバルに追加されます。
EscapeSJIS
UnescapeSJIS
EscapeEUCJP
UnescapeEUCJP
EscapeJIS7
UnescapeJIS7
EscapeJIS8
UnescapeJIS8
EscapeUnicode
UnescapeUnicode
EscapeUTF7
UnescapeUTF7
EscapeUTF8
UnescapeUTF8
EscapeUTF16LE
UnescapeUTF16LE

一つだけタイプを取得する関数が以下です。
GetEscapeCodeType
戻される文字列の種類

SJIS
EUCJP
JIS7
JIS8
Unicode
UTF8
UTF16LE

※ ソースコードを見た限りでは、UTF7はありませんでした

UrlEncode にするには、これをさらに、
1) * から %24 に変換
2) + から %2B に変換
3) / から %2F に変換
してやる必要があります
※ 正確には、%20 を + に戻す必要がありますが、このままでもサーバでは正しく変換されます

関連する記事

javascriptで文字コード変換
( ここの情報は有益ですが、バイナリデータとしての変換は、ecl.js では出来ず、Encoding.js を使用します )



<script type="text/javascript" src="http://lightbox.on.coocan.jp/ecl_new.js" ></script>
<script type="text/javascript">
var str = EscapeUTF8(" !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")
str = str.replace(/\//g,'%2F');
str = str.replace(/\*/g,'%24');
str = str.replace(/\+/g,'%2B');
str = str.replace(/%20/g,'+');
alert(str)
</script>

※ テストはこちらから行えます



posted by lightbox at 2018-01-29 13:30 | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2018年01月26日


JavaScript でクリップボードに文字列をコピーする Clipboard.js の使用方法と注意事項

世の中の一般的な使用方法は、オリジナルサイトの概要と大差無いようですが、実際本当に使いたい環境を持っている人にとっては説明不十分です。

バージョン 1.5.4 までと 1.5.5 からでは仕様がすこし違う

問題は、element.focus(); ですが、これですと環境によってはコピー対象となるエレメントの位置までスクロールしてしまうので(実際このブログではしてしまった)ので、良く解らずに 1.5.4 以前を使用している場合は、バージョンアップしないほうがいいです。また、以下のソースコードからも解るように、focus() が実行されるのは、INPUT か TEXTAREA か その他の要素で contenteditable 属性を持っている場合だけなので、普通に DIV ならば focus() が実行される事はありません。
/*!
 * clipboard.js v1.5.12
 * https://zenorocha.github.io/clipboard.js
 *
 * Licensed MIT c Zeno Rocha
 */
    if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
        element.focus();
        element.setSelectionRange(0, element.value.length);

        selectedText = element.value;
    }
    else {
        if (element.hasAttribute('contenteditable')) {
            element.focus();
        }

        var selection = window.getSelection();
        var range = document.createRange();

        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);

        selectedText = selection.toString();
    }

    return selectedText;
この SyntaxHighlighter の右上のツールバーにある copy ボタンは、Clipboard.js を組み込んで実装しました。

実装

このような事をふまえて一般的な実装は以下のようになります
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.12/clipboard.min.js"></script>
<script>
$(function(){
	var clipboard = new Clipboard('.clipboard_element');
	clipboard.on('success', function(e) {
	    alert("クリップボードにコピーしました");
	});
	$(".action_btn").on("click", function(){
		var work = prompt("入力値をクリップボードにセット")
		$("#clipboard").text( work );
	})
});
</script>
<div class="clipboard_element" data-clipboard-target="#clipboard">
	<button type="button" class="action_btn">実行</button>
</div>

<div id="clipboard" style='position:absolute;left:-1000px;width:900px;white-space:pre-wrap;word-wrap:break-word;'></div>
new Clipboard で作成されるオブジェクトは、クリック対象の clipboard_element クラスを持つ要素を対象として作成されます。ここでは、clipboard_element は、DIV に対して設定されており、その DIV の中にアクションのトリガとなるボタンを配置しています。ボタンがクリックされると、まずそのイベントで必要なデータが画面外の要素に転送され、クリップボードにそのデータが送られます。要素間の関連性は、ボタンの親要素である DIV に data-clipboard-target="#clipboard" で設定されています
このソースコードには、いくつか重要な部分が存在します。 注意事項 1) ページにひとつだけ、クリップボード転送用の要素を DIV で作成する (body 要素直下でいいと思います) 2) DIV 内に改行やスペースを反映させる為に white-space:pre を設定する 3) ページ上から隠す為に、position:absolute;left:-1000px を設定する (クリップボートへコピーする為に選択する必要があるので、非表示では動作しません) 転送したテキストがこちら側へ表示しないように width:900px と word-wrap:break-word を指定する 4) クリックイベントは、ボタンである必要は無く、どのような要素でも良い 5) ボタンをクリックした時に必要な文字列を DIV に転送した後、DIV のクリックイベントが発生 実際の Clipboard.js のイベントは、ページ上のクリックイベントが全て終了してから発生するので、この順序である必要は無いのですが、仕様変更等あった場合にそなえてこの順序が良いと思います。 追記 ここで行っているような転送用のエリアを作成した処理を半自動でやるのがどうやら Advanced Options のあたりのようなのですが、ソース読むといろいろ scroll とかやってるので、環境によってはやはり問題がでるかもしれません。 Google、ChromeでのFlashブロックをさらに推進、12月にHTML5をデフォルトに 関連する記事 clipboard.js のコピーさせるテキストを自由にダイナミックに渡す方法は、Advanced Usage の text です。
posted by lightbox at 2018-01-26 18:57 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2016年10月09日


Lightbox2 ライブラリの今時の使い方

2015年の7月の中旬以降のバージョンでは、lightbox.js は、ページの最後で読み込むようになっていました(WEBアーカイブ調べ)
Include the Javascript at the bottom of your page before the closing </body> tag:
( 画像より後に読み込むといいようです。また css を読み込んでから js です ) バージョン v2.04 のころは、prototype.js と scriptaculous.js が使われていたのですが、2.6(2014/03/20) では、jQuery が使用されていました( バージョンは 1.10.2 ) です。 今時では jQuery は Google がホスティングしてくれるのでそれを使うのが簡単です。あと、Lightbox2 のファイルが lightbox.min.js と lightbox.css(又はlightbox.min.css) と 画像ファイルがいくつか必要になります。 ここでは、関係するファイルを一箇所にまとめるために、lightbox.css(又はlightbox.min.css) 内の画像のパスを変更しています( 例えばここでは url(../img/close.png) を url(close.png) にしています )
body:after {
  content: url(close.png) url(loading.gif) url(prev.png) url(next.png);
  display: none;
}
それらを使用して Lightbox2 を使う場合以下のようになります
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://lightbox.sakura.ne.jp/demo/lightbox2/lightbox2/lightbox.min.css">
<a href="http://goo.gl/nC01x4" data-lightbox="daz3d"><img src="http://goo.gl/AgJ1QU"></a>
<a href="http://goo.gl/ibgyRW" data-lightbox="daz3d"><img src="http://goo.gl/ulC3Hs"></a>

<script type="text/javascript" src="https://lightbox.sakura.ne.jp/demo/lightbox2/lightbox2/lightbox.min.js"></script>


この画像は、Picasa に登録してあるのでやたらと URL が長いので Google の URL 短縮機能を使って画像の URL を短くしています。

また、Lightbox の現在の最新仕様として data-lightbox 要素が使用されていますが、古くからの rel を使った方法も動作します。( rel="lightbox[group_string]" )

data-lightbox="daz3d"daz3d は、画像のグループで、表示後に直接画像間の表示を切り替える事ができるようになります。

※ 他のライブラリやCSSの影響で、Lightbox の実行時の背景を暗くできない場合がある場合は、そのページに以下の CSS を設定するといいと思います。
<style type="text/css">
#lightboxOverlay {
	opacity: 0.8!important;
}
</style> 

その他のオプション

リンク( アンカー要素 ) に title 属性を指定すると、その内容が画像の左下に表示されます。
2.7.1 では、data-title="タイトル文字列" が使用できます。


タイトルの中には、HTML の表現も可能ですが、以下のような記述に変換する必要があります。( 実際には、一部分でいいのですが、全て変換しています )

※ リンクを試したのですが、クリックしても動作しませんでした。
2.7.1 ではリンクも動作しました。
但し、アプリで操作しているからなのか、target="_blank" が動作しなかったのと、IFRAME 内ではリンクが動作しませんでした。
<a href="http://goo.gl/UUjQaE" data-lightbox="daz3d" data-title="&#9660;&#12522;&#12531;&#12463;&#12391;&#12377;&#12290;&#12463;&#12522;&#12483;&#12463;&#12391;&#12365;&#12414;&#12377;&#60;&#98;&#114;&#62;&#60;&#97;&#32;&#104;&#114;&#101;&#102;&#61;&#34;&#104;&#116;&#116;&#112;&#115;&#58;&#47;&#47;&#116;&#119;&#105;&#116;&#116;&#101;&#114;&#46;&#99;&#111;&#109;&#47;&#115;&#119;&#111;&#114;&#99;&#34;&#62;&#60;&#105;&#109;&#103;&#32;&#115;&#114;&#99;&#61;&#34;&#104;&#116;&#116;&#112;&#115;&#58;&#47;&#47;&#108;&#104;&#53;&#46;&#103;&#111;&#111;&#103;&#108;&#101;&#117;&#115;&#101;&#114;&#99;&#111;&#110;&#116;&#101;&#110;&#116;&#46;&#99;&#111;&#109;&#47;&#45;&#107;&#67;&#89;&#84;&#83;&#109;&#84;&#114;&#74;&#88;&#115;&#47;&#85;&#82;&#118;&#77;&#81;&#121;&#57;&#67;&#108;&#113;&#73;&#47;&#65;&#65;&#65;&#65;&#65;&#65;&#65;&#65;&#82;&#117;&#119;&#47;&#53;&#66;&#84;&#75;&#84;&#107;&#50;&#99;&#95;&#115;&#119;&#47;&#115;&#49;&#48;&#48;&#47;&#95;&#105;&#109;&#103;&#46;&#112;&#110;&#103;&#34;&#62;&#60;&#47;&#97;&#62;"><img src="http://goo.gl/9n0KCM"></a>
変換用の簡単なプログラム

▼ 以下に表示されます

関連する記事

JavaScript : 入力文字列を htmlentity に変換する



posted by lightbox at 2016-10-09 03:14 | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2016年08月12日


clipboard.js のコピーさせるテキストを自由にダイナミックに渡す方法は、Advanced Usage の text です。

Google Chrome の Flash 完全排除に対応 : JavaScript でクリップボードに文字列をコピーする Clipboard.js の使用方法と注意事項 では、具体的にその方法を自分で用意して使用しています。その方法のほうが、メンテナンスし易いと思う場合はそちらを使えばいいと思いますが、簡単に実装したいのならばこちらの方法です。

実装コード
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.12/clipboard.min.js"></script>
<script>
var clipbpardText = "";

$(function(){
	var clipboard = 
	new Clipboard('.clipboard_btn' , {
		text: function(trigger) {
        		return clipbpardText;
		}
	});

	clipboard.on('success', function(e) {
	    alert("クリップボードにコピーしました");
	});

	$("#button1").on("click", function(){
		var work = prompt("入力値をクリップボードにセット")
		clipbpardText = work;
	})
});
</script>
<button type="button" class="clipboard_btn" id="button1">実行</button>

clipboard.on は特に必要ではありませんが、テストする場合は解り易くなると思います。

まず、イベントの開始となるクリックイベントでコピーさせたい文字列をグローバル変数である clipbpardTextにセットします。

その後、new Clipboard で定義した text に対するファンクションが起動されて、コピーさせたい文字列(ここでは clipbpardText)を return するだけで実装完了です。


この処理は内部のソースコードを読むとたぶん以下の部分だと思われます
ClipboardAction.prototype.selectFake = function selectFake() {
            var _this = this;

            var isRTL = document.documentElement.getAttribute('dir') == 'rtl';

            this.removeFake();

            this.fakeHandlerCallback = function () {
                return _this.removeFake();
            };
            this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true;

            this.fakeElem = document.createElement('textarea');
            // Prevent zooming on iOS
            this.fakeElem.style.fontSize = '12pt';
            // Reset box model
            this.fakeElem.style.border = '0';
            this.fakeElem.style.padding = '0';
            this.fakeElem.style.margin = '0';
            // Move element out of screen horizontally
            this.fakeElem.style.position = 'absolute';
            this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
            // Move element to the same position vertically
            this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
            this.fakeElem.setAttribute('readonly', '');
            this.fakeElem.value = this.text;

            document.body.appendChild(this.fakeElem);

            this.selectedText = (0, _select2.default)(this.fakeElem);
            this.copyText();
        };
textarea を作成して、-9999px で画面から隠しているようです。




posted by lightbox at 2016-08-12 20:20 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2016年06月14日


Google Visualization API って apikey いらなくなった? / ライブラリロード方法が変わってました

簡単にグラフが作成できるのですが、なんか本当に人気が無いように思います。

Quick Start

先に DataTable を作っていろいろ UI や グラフ のタイプを変えるのですが、やはり、使い勝手のいい 円グラフが Quick Start で紹介されています。

そのサンプルはそれとして、以前より使用しているサンプルにフォント設定を追加したのが以下になります。

fontName や fontSize をはじめとするオプションのリファレンスはこちらです。

ソースコード
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

<script type="text/javascript">

function drawChart() {

	var data = new google.visualization.DataTable();
	data.addColumn('string', '対象');
	data.addColumn('number', '件数');
	data.addRows(3);

	data.setValue(0, 0, '対象A');
	data.setValue(0, 1, 2000);
	data.setValue(1, 0, '対象B');
	data.setValue(1, 1, 3000);
	data.setValue(2, 0, '対象C');
	data.setValue(2, 1, 1500);

	var chart = new google.visualization.PieChart(document.getElementById('chart_div'));

	chart.draw(
		data, {
			fontSize: 16,
			fontName: 'Arial, Helvetica, Verdana, "ヒラギノ角ゴPro W3", "Hiragino Kaku Gothic Pro", Osaka, "メイリオ", Meiryo, "MS Pゴシック", sans-serif',
			width: 400,
			height: 300,
			is3D: true,
			title: '円グラフのタイトル'
		}
	);

}

</script>

<script type="text/javascript">
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
</script>

昔は google.load ってのを使ってました。ライブラリも apikey 付きで、www.google.com/jsapi です。(今でも動きます)
key が無いとこんな文句言われてました
Warning: You need your own API key in order to use the Google Loader.  Without your own key, examples won't work. 
・・・・とは言うものの6年前の話です。そもそも、日本語で書かれた新しい情報が皆無なので apikey に関する流れは確認できません。いらないんだから、どっちでもいいですけれど、Google と長く付き合うと良くある事ではあります。
タグ:google
posted by lightbox at 2016-06-14 20:26 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2016年06月11日


Lightbox2 で data-title にボタンを埋め込んで、クリックしたら 画像のファイル名を取り出して Lightbox2 を閉じるギャラリーのデモ

デモページ


画像ひとつぶんの記述
<a href='575be6f335da1_artwork_image_8667.jpg' data-lightbox='gallery' data-title='<input type="button" value="選択" onclick="select_img(this)" data-src="575be6f335da1_artwork_image_8667.jpg">'><img src='s/575be6f335da1_artwork_image_8667.jpg'></a>
lightbox2 は、v2.8.2 です。なので、ライブラリの読み込みは ページの最後です。

data-title にボタンの HTML をセットして、onclick イベントで select_img 関数を呼び出し、ボタンのインスタンスを引数で渡します。

ボタンには、data-src 属性を追加して、画像ファイル名をセットしていますので、select_img 関数 でこの値を取り出します。

select_img 関数
function select_img(data) {

	var src = $(data).data("src");

	alert( src );

	$(".lb-close").trigger("click");

}


Lightbox2 をどうやって閉じようかと、普通に試したら $(".lb-close").trigger("click") で閉じる事ができました。jQuery で普通にイベント登録している事が推測されますね。

関連する記事

Lightbox2 ライブラリの今時の使い方

▼ Lightbox2 の必要なファイル


※ .css の中の画像のパスは画像ファイル名のみになっています



posted by lightbox at 2016-06-11 20:06 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2016年05月03日


EASELJS を使用した画像の分割と分割されたエリア毎のアニメーション / createjs.Ticker の reset と init はうまく動きませんでした



createjs.Ticker でアニメーション用のループを作成するので、一旦実行すると CPU 負荷が少しかかった状態になります。そのリセットとかしたかったですけれど、createjs.Ticker の reset と init はうまく動きませんでした。

4分割固定で処理していますが、何分割でもできるようなパラメータ設定になっています。配列の数と、分割の割り算のところを引数にすればいいですね。

EASELJS で作成した Bitmap を TWEENJS でサンプルどおりに動かしてみました
※ 回転はあとから追加です。同時に元の座標に戻しています

<script>
if ( typeof createjs === 'undefined' ) {
	document.write("<"+"script src=\"https://code.createjs.com/easeljs-0.8.2.min.js\"></"+"script>");
	document.write("<"+"script src=\"https://code.createjs.com/tweenjs-0.6.2.min.js\"></"+"script>");
}
</script>

<script>
var bitmap = Array(),bitmap_all,rect = Array();
var tick = false;

$(function(){

	$("#tm_action_05103").on("click", function(){

		if ( !tick ) {
			// アニメーション開始
			createjs.Ticker.addEventListener("tick", stage1);
			tick = true;
		}

		for( i = 0; i < 4; i++ ) {
			bitmap[i].rotation = 0;
			createjs.Tween.get(bitmap[i], {loop: false})
				.to({x: 400}, 1000, createjs.Ease.getPowInOut(4))
				.to({alpha: 0, y: 75}, 500, createjs.Ease.getPowInOut(2))
				.to({alpha: 0, y: 125}, 100)
				.to({alpha: 1, y: 100}, 500, createjs.Ease.getPowInOut(2))
				.to({x: (i%2)*(bitmap_all.image.width/2), y: (parseInt((i/2)))*(bitmap_all.image.height/2), rotation:360 },
					800, createjs.Ease.getPowInOut(2))
				.call(function(){
					console.log("アニメーション終了(一応)");
				});
		}

	});

});
</script>
<input type="button" value="アニメーション" id="tm_action_05103">
<br>
<canvas id="load_area1" width="600" height="450" style='border:1px solid #000000'></canvas>
<script>
var stage1 = new createjs.Stage("load_area1");


img = new Image()
img.onload = function() {

	bitmap_all = new createjs.Bitmap(this);

	// トリミング用 bitmap
	for( i = 0; i < 4; i++ ) {
		bitmap[i] = new createjs.Bitmap(this);

		rect[i] = new createjs.Rectangle(
			(i%2)*(bitmap_all.image.width/2), 
			(parseInt((i/2)))*(bitmap_all.image.height/2), 
			bitmap_all.image.width/2, 
			bitmap_all.image.height/2
		);
		bitmap[i].sourceRect = rect[i];
		bitmap[i].x = (i%2)*(bitmap_all.image.width/2);
		bitmap[i].y = (parseInt((i/2)))*(bitmap_all.image.height/2);

		stage1.addChild(bitmap[i]);
	}

	// 最初の表示
	stage1.update();

}
img.src = "https://lh3.googleusercontent.com/-A5QW2HTze84/VyNZEIwxh4I/AAAAAAAAeRE/-rCcFQmsKawDMRrV6logONKz0i6LVhtYACCo/s600/wing_elf.jpg";

</script>


posted by lightbox at 2016-05-03 21:14 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2016年05月01日


EASELJS を使用した画像の縮小とトリミングと角丸マスク / 画像は new Image でイベント処理して画像サイズを取得します

当然ではありますが、ブラウザが画像をロードし終わらないと、JavaScript でサイズを知る事ができません。EASELJS の createjs.Bitmap の引数は、文字列の URL では無く Image オブジェクトを使用しています。

画像サイズが解ったら、そのサイズを使って計算し、scaleX と scaleY で縮小します。

トリミングは createjs.Rectangle で四角形を作成して、Bitmap の sourceRect プロパティに設定します。表示位置は、x プロパティと y プロパティStage の中の位置を設定します。

画像を角丸にする為、Shape オブジェクトで画像に合った角丸の形状を作成して、Bitmap の mask プロパティに設定します。




実際の画像 1200x900
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script>
if ( typeof createjs === 'undefined' ) {
	document.write("<"+"script src=\"https://code.createjs.com/easeljs-0.8.2.min.js\"></"+"script>");
}
</script>
<script>
$(function(){
	$("#tm_action").on("click", function(){

		// トリミング
		var rect = new createjs.Rectangle(700, 300, 200, 200);
		bitmap.sourceRect = rect;
		bitmap.x = 10;
		bitmap.y = 10;

		stage1.update();

	});

	$("#mask_action").on("click", function(){

		shape.graphics.drawRoundRect(10, 10, 200, 200, 16, 16);
		bitmap.mask = shape;

		stage1.update();
	});

	$("#clear_action").on("click", function(){

		bitmap.mask = null;
		stage1.clear();

	});

});
</script>
<input type="button" value="トリミング" id="tm_action">
<input type="button" value="角丸マスク" id="mask_action">
<input type="button" value="クリア" id="clear_action">
<br>
<canvas id="load_area1" width="400" height="220" style='border:1px solid #000000'></canvas><br><canvas id="load_area2" width="400" height="300" style='border:1px solid #000000'></canvas>
<script>
var stage1 = new createjs.Stage("load_area1");
var stage2 = new createjs.Stage("load_area2");
var bitmap,shape;

img = new Image()
img.onload = function() {

	// トリミング用 bitmap
	bitmap = new createjs.Bitmap(this);
	stage1.addChild(bitmap);

	// マスク用 shape
	shape = new createjs.Shape();

	var bitmap_all = new createjs.Bitmap(this);
	bitmap_all.scaleX = 400/bitmap_all.image.width;
	bitmap_all.scaleY = 300/bitmap_all.image.height;

	stage2.addChild(bitmap_all);
	stage2.update();

}
img.src = "https://lh3.googleusercontent.com/-A5QW2HTze84/VyNZEIwxh4I/AAAAAAAAeRE/-rCcFQmsKawDMRrV6logONKz0i6LVhtYACCo/s1200/wing_elf.jpg";



</script>
easeljs のロードは、ブログの記事に書き込む事を想定して、そのページで一度きりのロードです。


posted by lightbox at 2016-05-01 19:06 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2015年12月12日


Three.js r73 での Canvas で平面を飛翔させる為の詳細デモ

デモページ

アニメーション開始は右上のボタン
※ リロードするとアニメーション前の初期状態に戻ります

▼ 飛翔画像


以前、v57 頃の時に作成した平面の『蝶』の画像を飛翔させるデモです。バージョンがかなり変わって前のままでは動作しなくなったものを少し修正してさらに使いやすくかつ解りやすくしました。『飛翔』そのもののコードは、Three.js 内で今も使われているもので昔から全く変わっていません。この部分は、boid.js として外部ファイルとして取り出してあります。

ただ、Canvas のレンダリング部分(CanvasRenderer.js)は v73 では外部ファイルとなって Three.js 本体からは外されていました。また、さらに実行の為に Projector.js というファイルも必要になっていました。

HTML 部分
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="shortcut icon" href="http://winofsql.jp/WinOfSql.ico">

<script src="three.min73.js"></script>
<script src="CanvasRenderer.js"></script>
<script src="Projector.js"></script>
<script src="boid.js"></script>

</head>
<body style="margin:0">
<div style="position:absolute;width:98%">
<input
	type="button"
	value="アニメーション開始"
	style="position:relative;float:right;"
	onclick="window.animate();this.style.display='none'"
	title="ページをリロード(再表示)するとアニメーションは止まります">
</div>
<div id="container"></div>

<script src="birds73.js"></script>

</body>
</html>


Three.js 実行環境部分(birds73.js)
// *************************************************
// Three.js の環境設定
// *************************************************
var SCREEN_WIDTH		= window.innerWidth * 0.98;
var SCREEN_HEIGHT		= window.innerHeight * 0.98;
var SCREEN_WIDTH_HALF	= SCREEN_WIDTH  / 2;
var SCREEN_HEIGHT_HALF	= SCREEN_HEIGHT / 2;

var camera, scene, renderer,
birds, bird;

var boid, boids;

var stats;

// お決まりの初期処理とアニメーション開始
init();
// animate 内の render が実行されても、init の処理が完了していないと描画されません
// なので、アニメーション無しの1回限りの描画は、setTimeout か、画像の最終イベント内で実行します
//animate();

function init() {

	camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
	camera.position.z = 450;

	scene = new THREE.Scene();

	birds = [];
	boids = [];

	// 背景画像・人物画像用ラッパー
	var parent = new THREE.Object3D();

	// *************************************************
	// 背景画像の読み込み
	// *************************************************
	var image = new Image()
	image.onload = function () {

		var texture = new THREE.Texture( this );
		texture.needsUpdate = true;
		var material = new THREE.MeshBasicMaterial({map: texture, overdraw: true});

		// 平面
		var mesh = new THREE.Mesh(new THREE.PlaneGeometry(1200, 1200, 1, 1), material);

		// 画面奥
		mesh.position.z = -400;

		// 大きさ調整
		mesh.scale.x = 1.5;
		mesh.scale.y = 1.5;

		// 回転
		mesh.rotation.x = 0;
		mesh.rotation.y = 0;

		// ラッパーに平面追加
		parent.add( mesh );

		// *************************************************
		// 人物画像の読み込み
		// *************************************************
		var image = new Image()
		image.onload = function () {

			var texture = new THREE.Texture( this );
			texture.needsUpdate = true;
			var material = new THREE.MeshBasicMaterial({map: texture, overdraw: true});

			// 平面
			var mesh = new THREE.Mesh(new THREE.PlaneGeometry(778, 623, 1, 1), material);

			// 画面前
			mesh.position.z = 300;

			// 表示位置調整
			mesh.position.x = 80;
			mesh.position.y = -42;

			// 大きさ調整
			mesh.scale.x = 0.3;
			mesh.scale.y = 0.3;

			// 回転
			mesh.rotation.x = 0;
			mesh.rotation.y = 0;

			// ラッパーに平面追加
			parent.add( mesh );

			// シーンにラッパー(画像2枚)追加
			scene.add(parent);

			// *************************************************
			// 飛翔画像の読み込み
			// *************************************************
			var image = new Image()
			image.onload = function () {

				texture = new THREE.Texture( this );
				texture.needsUpdate = true;
				material = new THREE.MeshBasicMaterial({map: texture, overdraw: true});
				material.side = 2

				// 200の飛翔物体
				for ( var i = 0; i < 200; i ++ ) {

					boid = boids[ i ] = new Boid();
					boid.position.x = Math.random() * 400 - 200;
					boid.position.y = Math.random() * 400 - 200;
					boid.position.z = Math.random() * 400 - 200;
					boid.velocity.x = Math.random() * 2 - 1;
					boid.velocity.y = Math.random() * 2 - 1;
					boid.velocity.z = Math.random() * 2 - 1;
					boid.setAvoidWalls( true );
					boid.setWorldSize( 500, 500, 400 );

					// 飛翔画像を貼り付けたマテリアルを平面に適用
					birds[ i ] = new THREE.Mesh( new THREE.PlaneGeometry(30, 30, 2, 1), material );

					// オリジナルの特殊処理
					bird = birds[ i ]
					bird.phase = Math.floor( Math.random() * 62.83 );

					// 飛翔物体単位でシーンに追加
					scene.add( bird );

				}

				// 初回表示
				render();
			};
			// 飛翔画像
			image.src = "002.png";
			
		};
		// 人物画像
		image.src = "girl.png";

	}
	// 背景画像
	image.src = "moon.jpg";


	renderer = new THREE.CanvasRenderer();
	renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );

	document.addEventListener( 'mousemove', onDocumentMouseMove, false );
	document.body.appendChild( renderer.domElement );

	window.addEventListener( 'resize', onWindowResize, false );

}

function onWindowResize() {

	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();

	renderer.setSize( window.innerWidth * 0.98, window.innerHeight * 0.98 );

	render();

}

// マウスによる、飛翔物体の反応処理
function onDocumentMouseMove( event ) {

	var vector = new THREE.Vector3( event.clientX - SCREEN_WIDTH_HALF, - event.clientY + SCREEN_HEIGHT_HALF, 0 );

	for ( var i = 0, il = boids.length; i < il; i++ ) {

		boid = boids[ i ];

		vector.z = boid.position.z;

		boid.repulse( vector );

	}

}

// Three.js のお決まりの処理
function animate() {

	requestAnimationFrame( animate );

	render();

}

function render() {

	// 飛翔物体の処理
	for ( var i = 0, il = birds.length; i < il; i++ ) {

		boid = boids[ i ];
		boid.run( boids );

		bird = birds[ i ];
		// 旧版では無かった処理
		bird.position.copy( boids[ i ].position );

		// 飛翔物体の飛翔用の傾け処理
		bird.rotation.y = Math.atan2( - boid.velocity.z, boid.velocity.x );
		bird.rotation.z = Math.asin( boid.velocity.y / boid.velocity.length() );

		// 画像を x 軸で90度回転して、横に寝かせる
		bird.rotation.x = (180 * Math.PI / 180)/2;

		// オリジナルの特殊処理
		bird.phase = ( bird.phase + ( Math.max( 0, bird.rotation.z ) + 0.1 )  ) % 62.83;

		// 平面画像のはばたき処理
		bird.geometry.vertices[ 0 ].z = Math.sin( bird.phase ) * 15;
		bird.geometry.vertices[ 2 ].z = Math.sin( bird.phase ) * 15;

		// 0  1  2
		// 3  4  5
		// セグメントが 2x1 なので、0番と 2番を動かすと、羽の先が動きます。
		// 羽全体を動かすのであれば、3番と5番も同時に値を変更してもいいです

	}


	renderer.render( scene, camera );

}



birds73.js も殆どは Three.js のサンプルと変わりませんが、Three.js では鳥に見立てた頂点を持つオブジェクトが使用されています。こちらでは、平面を 2 セグメントに分けて、頂点を6つ持ったオブジェクトの 0 番と 2番を 動かせて『飛翔』させています。
※ 詳細は、ソースコード内のコメントに書かれてあります

画像の配置

画像は全て canvas 内に配置しているので、Google Chrome や Firefox ならばそのまま保存して、その時の画像を取得する事ができます。月画像は奥に、人物画像は手前にありますが、飛翔物体がかなり手前に来た場合は人物を突き抜けるのはご愛嬌です。

画像のロードは 3種類あるので 3段階で行っています。背景 => 前景 => 飛翔画像と、各画像がロードされてから次の画像の処理へと移っています

Window サイズ変更時

全て Canvas 内なので Window サイズにあわせて表示は縮小されますが、アニメーションはそのまま実行されます。もともとは、IFRAME 内で表示する事を想定しており、お好きなサイズでページに埋め込む事ができます。



posted by lightbox at 2015-12-12 21:43 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2015年11月16日


クリスマスに備えて、『雪を降らす snowstorm.js』のカスタマイズ / ダウンロードも何も必要ありません。jQuery も必要ありません

ダウンロードも何も必要ありません。jQuery も必要ありません。ただ、cdnjs より URL をコピーして『ページに埋め込むだけです』

配布サイトのオプションの説明

デモページ


ただ、そのままではあまりにも工夫が無いので、少しオプションを設定しています。
<style>
body {
	background-color:#000000;
}

@-webkit-keyframes snow-rotate {
  0% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(360deg); }
}
@-moz-keyframes snow-rotate {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
@-o-keyframes snow-rotate {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
@keyframes snow-rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
.mysnow {
	color:#e0e0e0!important;
	-webkit-animation: 1.85s snow-rotate steps(8) infinite;
	-moz-animation: 1.85s snow-rotate steps(8) infinite;
	-o-animation: 1.85s snow-rotate steps(8) infinite;
	animation: 1.85s snow-rotate steps(8) infinite;

}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js"></script>
<img src="https://lh3.googleusercontent.com/-Chj58uY2pjs/Vht0XOX3l-I/AAAAAAAAcCs/ijZAwj3NNQY/s1000-Ic42/silver_a2.png">
<script>
snowStorm.excludeMobile = false;
snowStorm.animationInterval = 50;
snowStorm.flakesMax = 64;
snowStorm.className = "mysnow"
snowStorm.flakeWidth = 16;
snowStorm.flakeHeight = 16;
snowStorm.snowCharacter = '&#10052;';
</script>
二つの大きなカスタマイズ

もともとは、小さな点を使っで雪を降らしていますが、キャラクタを自由に変更できるので、もともとある雪の結晶のような "❄" を使用しています。キャラクタのサイズが倍になるので、幅と高さを変更しています。

さらに、CSS のアニメーションを使用して一つ一つの雪の結晶を回転させています。

モバイル対応

モバイルで動作させるには、以下の設定が必要です。厳密な違いは解りませんが、作者は『バッテリーに悪影響あり』とほのめかしておられます。
snowStorm.excludeMobile = false;

CPU にやさしく

以下の設定は不用意に CPU を使わないようになる事が期待できます

snowStorm.animationInterval = 50;
snowStorm.flakesMax = 64;


関連する記事

雪を降らす snowstorm.js の 特定 DIV 内での実装
【改造】雪を降らす snowstorm.js に 風向きを外部から設定できるオプションを追加しました




タグ:javascript cdnjs
posted by lightbox at 2015-11-16 20:40 | Comment(0) | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする

2014年03月29日


JavaScript : 誰でもすぐ使える Google 円グラフ(2) : データを Google ドキュメントから取得する



Ggdoc5
Google ドキュメントを使用して、円グラフ(visualization / piechart )を作成する
Google ドキュメントへのリンク Google ドキュメントは誰にでも使えるオンラインの Excel のようなものですが、WEB 上のデータのホスティングとしても利用する事ができます。
<style>
#chart_div iframe {
	border: solid 1px #000000;
	border-radius: 30px;
}
</style>
<div id="chart_div"></div>

<script charset="utf-8" type="text/javascript" src="http://www.google.com/jsapi"></script> 
<script type="text/javascript">
google.load("visualization", "1", {packages: ["piechart"]});

google.setOnLoadCallback(getGoogleDoc);

var data;

// *********************************************************
// WEB(Google ドキュメント) からデータを取得
// *********************************************************
function getGoogleDoc() {

	// ターゲットとなる WEB 公開 URL
	var target = "http://spreadsheets.google.com/pub?key=";
	target += "0AtJymqpro6gScDZQZmVQZ0RNSkZCb0lqREg1bGNQQ3c&hl=ja&single=true&gid=3&output=html";

	// SQL でデータを取得
	var query = new google.visualization.Query(target);
	query.setQuery("select *");
	// データを取得後に呼び出す関数を指定
	query.send( drawChart );

}

// *********************************************************
// 円グラフ作成
// *********************************************************
function drawChart(response) {

	// エラー処理
	if ( response.isError() ) {
		alert(getDetailedMessage());
		return;
	}

	// テーブル用データ作成
	data = response.getDataTable();

	var chart = new google.visualization.PieChart(document.getElementById('chart_div'));

	chart.draw(data, {width: 600, height: 320, is3D: true, title: '円グラフのタイトル'});
}
</script>

関連する記事

JavaScript : 誰でもすぐ使える Google 円グラフ


タグ:google
posted by lightbox at 2014-03-29 20:37 | JavaScript ライブラリ | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり