- 投稿日:2020-06-02T23:53:35+09:00
お絵かきできるSNSを作りたい!9
お絵かきできるSNSを作りたい後半戦、下のメニューを作っていきます。
まずはPNGで保存機能。
function saveCanvas(){ var src1_img = new Image(); var src2_img = new Image(); src1_img.src = $("#canvas")[0].toDataURL(); src1_img.addEventListener('load', function() { src2_img.src = $("#canvas2")[0].toDataURL(); src2_img.addEventListener('load', function() { var dst_canvas = document.createElement('canvas'); dst_canvas.width = 800; dst_canvas.height = 600; dst_canvas.getContext("2d").drawImage(src1_img, 0, 0, 800, 600); dst_canvas.getContext("2d").drawImage(src2_img, 0, 0, 800, 600); var imageType = "image/png"; var fileName = "download.png"; // base64エンコードされたデータを取得 「data:image/png;base64,iVBORw0k~」 var base64 = dst_canvas.toDataURL(imageType); // base64データをblobに変換 var blob = Base64toBlob(base64); // blobデータをa要素を使ってダウンロード saveBlob(blob, fileName); }, false); }, false); } // Base64データをBlobデータに変換 function Base64toBlob(base64){ // カンマで分割して以下のようにデータを分ける // tmp[0] : データ形式(data:image/png;base64) // tmp[1] : base64データ(iVBORw0k~) var tmp = base64.split(','); // base64データの文字列をデコード var data = atob(tmp[1]); // tmp[0]の文字列(data:image/png;base64)からコンテンツタイプ(image/png)部分を取得 var mime = tmp[0].split(':')[1].split(';')[0]; // 1文字ごとにUTF-16コードを表す 0から65535 の整数を取得 var buf = new Uint8Array(data.length); for (var i = 0; i < data.length; i++) { buf[i] = data.charCodeAt(i); } // blobデータを作成 var blob = new Blob([buf], { type: mime }); return blob; } // 画像のダウンロード function saveBlob(blob, fileName){ var url = (window.URL || window.webkitURL); // ダウンロード用のURL作成 var dataUrl = url.createObjectURL(blob); // イベント作成 var event = document.createEvent("MouseEvents"); event.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); // a要素を作成 var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a"); // ダウンロード用のURLセット a.href = dataUrl; // ファイル名セット a.download = fileName; // イベントの発火 a.dispatchEvent(event); }無駄に関数が増えました。
レイヤーが2枚あるので1枚にがっちゃんこしてます。
・[github]修正内容はこちら次はフルスクリーンボタンの実装です。
var blFullscreen = true; function doFullscreen(){ var elem = document.getElementById("screen"); if (blFullscreen){ if (elem.requestFullscreen) { elem.requestFullscreen(); } else if (elem.webkitRequestFullScreen) { elem.webkitRequestFullScreen(); } else if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); } else if (elem.msRequestFullscreen) { elem.msRequestFullscreen(); } blFullscreen = false; } else { if (document.webkitCancelFullScreen) { document.webkitCancelFullScreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } else if(document.cancelFullScreen) { document.cancelFullScreen(); } else if(document.exitFullscreen) { document.exitFullscreen(); } blFullscreen = true; } }フルスクリーン状態の判定をJSで行おうとするとブラウザによって挙動が怪しくなり悩むくらいならとグローバルおじさんになりました。
あと細かい修正もしたので詳しくは↓こちらを。
・[github]修正内容はこちらそして、左右反転。
これがちょっと手間で、左右反転するとレイヤー1とレイヤー2のX座標も反転させています。
メインの関数は↓こちら。var blReflect = true; function doReflect(){ if (blReflect){ $("#canvas").css('transform', 'scale(-1, 1)'); $("#canvas2").css('transform', 'scale(-1, 1)'); blReflect = false; } else { $("#canvas").css('transform', 'scale(1, 1)'); $("#canvas2").css('transform', 'scale(1, 1)'); blReflect = true; } }あとは、押したとき、動かしている時、離したときに左右反転状態かを判定してX座標を左右逆になるようにしました。
if (blReflect) { ox=event.clientX-event.target.getBoundingClientRect().left; } else { ox=$("#canvas").width() + (parseInt($("body").css('padding-left')) * 2) - event.clientX-event.target.getBoundingClientRect().left; }今回最後は最初から書き直すの実装です。
これはページリロードでいいんじゃ・・?とも思いましたが、折角なのでちゃんと実装しました。function doClear(){ if(confirm('本当にいいんですね?')){ ct.clearRect(0, 0, $("#canvas").width(), $("#canvas").height()); ct2.clearRect(0, 0, $("#canvas2").width(), $("#canvas2").height()); } }ちゃんとアラートで消すことを確認する新設設計。
レイヤー1とレイヤー2をクリアしています。次回、Ctrl+Zをしたい。お楽しみに。
- 投稿日:2020-06-02T23:52:56+09:00
lightbox2の使い方とカスタマイズについて(メモ)
この投稿について
作業進捗の備忘録、学習効果の向上を目的として記録していきます。
学習しながら作業を進めておりますので、情報が間違っている場合も多々あると思います。
正しい情報は公式ドキュメントを参考にしてください。開発環境
- macOS High Sierra 10.13.6
- Anaconda 3
- Python 3.7.7
- Djnago 3.0.6
- VisualStudioCode
※記事内のHTMLコードやフォルダ構成についてはアプリ開発途中のものを使用していますので、あらかじめご了承ください。
lightbox2とは
公式サイト
https://lokeshdhakar.com/projects/lightbox2/Webサイト上でいい感じに写真を閲覧できるようにするためのJavaScriptライブラリです。
lightbox2でやりたいこと
ページをめくる感じに写真を次々閲覧したい。
なんかいい感じに写真を見せたい。導入してみる
lightbox.js
を公式のGithub(https://github.com/lokesh/lightbox2/releases)からダウンロードし、それぞれアプリ内のstaticフォルダ内に設置します。
今回は少しカスタマイズして使用したいので、jsはminファイルではなく、オリジナルのものを使いました。app/static/js/lightbox.jslightbox.cssはダウンロードせずに、
内で読み込んで使用することにしました。HTMLの記述
head内にそれぞれ必要なファイルを読み込むための記述をします。jQueryも使うみたいなのでついでに読み込みます。
base.html<head> ...... <link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/css/lightbox.css" rel="stylesheet"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="{% static 'js/lightbox.js' %}"></script> </head>次に、写真を表示するページです。
index.html{% extends 'base.html' %} {% block bodyblock %} <div class="row pb-5"> {% for pic in obj %} <div class="col-md-3 mt-5"> <a href="{{ pic.picture.url }}" data-lightbox="group"> <img src="{{pic.pic_thumbnail.url}}" class='rounded' width="250" height="250"> </a> </div> {% endfor %} </div> {% endblock %}写真DBからクエリセットを取得してobjに読み込んでいます。
for文でサムネイルを並べるよう記述しています。imgタグを内包しているaタグに
data-lightbox="group"
の属性をつけることで、ページめくりの対象となる画像であることが認識されます。動作確認
写真のサムネイルを並べているページにアクセスし、写真をクリックすると、ポップアップウインドウが表示され、写真の左右にある矢印をクリックすると、隣の画像が表示されます。
(公式サイトサンプルのような動作が確認できると思います。)カスタマイズしてみる
画像を表示させるだけだと少し物足りなく感じたので、写真情報編集用のボタン(公開非公開、編集、削除など)を表示させることを試みました。
情報を探していると、写真が表示されるウインドウにキャプションを入れられるようで、方法は、先ほどdata-lightbox="group"
の属性を追加したタグに、data-title="キャプションしたい文字列"
の属性と属性値を追加すれば良いとのこと。以下のようにhtmlを編集すれば、タイトルのキャプションをつけるのは簡単そうです。※モデルにtitleフィールドがある場合。
index.html{% extends 'base.html' %} {% block bodyblock %} <div class="row pb-5"> {% for pic in obj %} <div class="col-md-3 mt-5"> <a href="{{ pic.picture.url }}" data-lightbox="group" data-title="{{ pic.title }}"> <img src="{{pic.pic_thumbnail.url}}" class='rounded' width="250" height="250"> </a> </div> {% endfor %} </div> {% endblock %}今回は編集用のボタンをキャプション部分に表示してみます。
lightbox.jsを編集してみる
lightbox.js(114行目)// Github issue: https://github.com/lokesh/lightbox2/issues/663 $('<div id="lightboxOverlay" tabindex="-1" class="lightboxOverlay"></div><div id="lightbox" tabindex="-1" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt=""/><div class="lb-nav"><a class="lb-prev" aria-label="Previous image" href="" ></a><a class="lb-next" aria-label="Next image" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo($('body'));ここで、画像を表示するポップアップウインドウのHTMLを発行しているようです。このあたりを編集することでレイアウト等をカスタマイズできそうです。
編集後・・・・・<span class="lb-caption"></span><div class="lightbox-buttons"><a class="update" href="#"></a></div><span class="lb-number"></span>・・・・・既存のタグは改変したくなかったので、captionを表示するためのタグの後ろに、ボタンを格納するための
<div class="lightbox-buttons"><a class="update btn btn-primary" href="#">Update</a></div>
を追記しました。次に、index.htmlを以下のように編集します。
index.html{% extends 'base.html' %} {% block bodyblock %} <div class="row pb-5"> {% for pic in obj %} <div class="col-md-3 mt-5"> <a href="{{ pic.picture.url }}" data-lightbox="group" update_url="{% url 'update' %}"> <img src="{{pic.pic_thumbnail.url}}" class='rounded' width="250" height="250"> </a> </div> {% endfor %} </div> {% endblock %}lightbox.js(220~226行目)function addToAlbum($link) { self.album.push({ alt: $link.attr('data-alt'), link: $link.attr('href'), title: $link.attr('data-title') || $link.attr('title') }); }この辺りのコードで、index.htmlのaタグ内に記載したdata-title属性の属性値を取得しているようです。
なので、以下のように編集します。
編集後function addToAlbum($link) { self.album.push({ alt: $link.attr('data-alt'), link: $link.attr('href'), update: $link.attr('update_url'), }); }これにより、index.htmlのupdare_urlの属性値(
{% url 'update' %}
)が読み取られ、albumのupdateに格納されます。lightbox.js(468~483行目)// Display caption, image number, and closing button. Lightbox.prototype.updateDetails = function() { var self = this; // Enable anchor clicks in the injected caption html. // Thanks Nate Wright for the fix. @https://github.com/NateWr if (typeof this.album[this.currentImageIndex].title !== 'undefined' && this.album[this.currentImageIndex].title !== '') { var $caption = this.$lightbox.find('.lb-caption'); if (this.options.sanitizeTitle) { $caption.text(this.album[this.currentImageIndex].title); } else { $caption.html(this.album[this.currentImageIndex].title); } $caption.fadeIn('fast'); }このコードで、220~226行で作成したalbumのtitleと紐づいている値の存在を確認して、データがあるようであれば114行目で生成した
<span class="lb-caption"></span>
にHTMLなりテキストなりを入力する処理をしています。なので、以下のように編集します。
468~483行目// Display caption, image number, and closing button. Lightbox.prototype.updateDetails = function() { var self = this; // Enable anchor clicks in the injected caption html. // Thanks Nate Wright for the fix. @https://github.com/NateWr //update url injection. if (typeof this.album[this.currentImageIndex].update !== 'undefined' && this.album[this.currentImageIndex].update !== '') { var $caption = this.$lightbox.find('.update'); $caption.attr('href',this.album[this.currentImageIndex].update); $caption.fadeIn('fast'); }これにより、albumのupdateと紐づいている値の存在を確認して、データがあるようであれば114行目で生成した`'のhref値を指定したurlに書き換えることができます。
これでlightboxのキャプション部分にリンクを設定することができました。その他
285行目this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();上記に独自に追加した属性を追記しないと、意図しないところでボタンが表示されたままになってしまったりするので、記載しておいた方が良い。
編集後this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption, .update').hide();
- 投稿日:2020-06-02T23:23:12+09:00
2020/06/02 プログラミング(WEBデザイン)学習3日目 メモ
本日の学習範囲
ドットインストール
・はじめてのCSS #05〜#07
(学習時間:1時間)CSS学習メモ
background-colorプロパティ
背景色を指定する
ボックス
要素によって生成される領域
内から順に、content・padding・border・marginで成り立っているcontent
widthプロパティとheightプロパティで指定する領域、要素内容が表示される
padding
paddingプロパティで指定する内側余白、背景が適用される
border
borderプロパティで指定する境界線、太さ・線種・色を指定できる
margin
marginプロパティで指定する外側余白
marginプロパティ
{margin-top: 幅;
margin-right: 幅;
margin-bottom: 幅;
margin-left: 幅;}
ボックスのマージンの幅を指定する
{margin: 上の幅 右の幅 下の幅 左の幅;}
と記述することも可能
全て同じ値の場合は、{margin: 幅;}
と記述できるdivタグ(HTML)
<div></div>
ひとかたまりの範囲として定義するclass属性(HTML)
<div class="class名">
要素に分類名を指定するclassセレクタ
.クラス名 {}
特定のclass名がつけられた要素にスタイルを適用するauto
ユーザーエージェントによって自動的に算出される値
autoが適用されたプロパティ毎に効果は異なる
marginプロパティにおけるautoは、ブラウザが適切なマージンを選択する
{margin-right: auto;
margin-left: auto;
の場合、左右中央揃えになるユーザーエージェント
サイトにアクセスした際に送る、OSやブラウザ、機種などの情報
- 投稿日:2020-06-02T22:34:54+09:00
HTMLでローカルにある画像を表示する
- 投稿日:2020-06-02T05:24:57+09:00
初心者によるプログラミング学習ログ 332日目
100日チャレンジの332日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
332日目は、
おはようございます
— ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) June 1, 2020
332日目 2h
・ポートフォリオ作成#早起きチャレンジ#駆け出しエンジニアと繋がりたい#100DaysOfCode