Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all 8499 articles
Browse latest View live

社内の忘年会の余興に使う『謎解き Web アプリ~天使 vs 悪魔~』を開発した(アプリ紹介・クライアント編)

$
0
0

概要

この記事は NSSOL Advent Calendar 2019の 13 日目の記事です。
会社のアドベントカレンダーに参加しているので、看板を背負っていることになりますが、
いつも通り自由に書こうと思います。

何をしたの〜?

NSSOL のシステム研究開発センター配属の新入社員 3 人で、 Web アプリを開発しました。
仲の良い 3 人が休日に趣味で勝手に開発した、という理解でお願いいたします。(本当にそうです。)

image.png

こんな感じです。

Bootstrap でフロント作って〜、
Flask でバックエンド作って〜、
EC2 でサーバたてて……

と、やったことが盛りだくさんでした。

今となっては、「技術的に難しいことはしていない」と振り返れてしまうのですが、
2 ヶ月間、予想以上に苦労したので、温かい目で記事を読んでいただけたら幸いです。

どんな記事なの~?

本アプリに関する記事は、全 3 編になる予定です。
アプリのほうがペラペラなので、Qiita の記事は引き伸ばし商法を使っていきます。

① アプリ紹介・クライアント編
② サーバ編
③ 裏話・開発手法編

また、私たち 3 人が理解した技術要素は以下の通りです。

  • CSS、Bootstrap、完全に理解した。
  • Flask、完全に理解した。
  • AWS、EC2、完全に理解した。
  • アジャイル開発、完全に理解した。

何も目新しい技術を使っていないというのに、本っっっっっっっ当に時間がかかりました。
お恥ずかしい限りです。゚(゚´ω`゚)゚。ピー

※アプリの公開について

このアプリは新人の自己紹介などを含めて作成しています。
そのため、プライバシーに関わる情報が内容に含まれており、
現段階では、公開できない状態です。
今後、そのような内容を変更して公開することがあるかもしれません。
(現在 AWS の EC2 を借りているため、金銭的な意味でも少し難しいと思います)

アプリ紹介

開発したアプリについて説明を行います。
本アプリは、全 4 問 +α から成る『謎解き Web アプリ』です。
プレイ時間は約 20 分を想定しています。
ブラウザで見ることが出来ます。 Chrome と Safari で動作確認を行っています。
faviconもいらすとやさんの画像を使って、作りました。

favicon.png

レスポンシブデザインのフレームワークを使っているのに、スマホ推奨です。
Bootstrap を勉強する時間と、各サイズに対応する時間がありませんでした。すみません。

着想、前提条件

まず、今回のアプリ開発を行う上で、必要な要件と、達成したい条件がいくつかありました。

  • 会社の忘年会の 30 分間を使って、出し物を行う。
  • 余興では何かしらの順位をつけ、景品を渡す。
  • 最大 150 人程度の人間が、同時に参加する。
  • 新人に興味を持ってもらえるような要素があると嬉しい。
  • 技術的な要素を見せられると嬉しい。ので新人がアプリ開発をする年も多い。

「景品を渡す」という条件が難しく、少なくとも何かしらの順位がつくものでなければなりません。
また、忘年会というお楽しみの場で、しっかり考えないと解けないものを作っても興ざめでしょう。
という感じで、いくつかの制約のもと、どんなアプリを作るか考えました。

結局、「どうせ作るなら開発者が作りたいものを作ろう」と考え、
3 人の中に謎解き大好きマンが 2 人居たため、今回の謎解きアプリの開発に至りました。

  • 導入と結果発表などを除いた、 20 分以内で解ける謎解きを作る。
  • お酒の場なので「知らないと解けない」「アクロバティックなことをしない」。
  • 故に、解ける問題を始めに置きつつ、最後は順位に差が生まれる問題を作る。
  • スマホでやりたいので、iPhone と Android どちらでも出来るように、Web ページで作成する。
  • そこそこいいサーバーを借りる。

のような、アプリになっています。
また、配布するしおりに新人の自己紹介に謎の答えを含めて、参照させるということもしています。

シナリオ

どうせなら謎解きにシナリオも含めると理想よね、みたいな欲張りな心が生まれてしまい、
シナリオにそって謎解きを行うアプリを開発することにしました。
(というのは建前で、勝手にシナリオを書いた人間がいたので含めました)

ただ、長い文章を読ませて、理解に時間がかかるような難解なシナリオがあっても仕方ないので、

  • 「心の中の天使 vs 心の中の悪魔」~誰もが一度は見たことがあるはず~
  • 「SIer」~愛社精神の塊~

を合わせて、キャッチーなものを作ろうと心がけました。
(結局、シナリオが無くても成立するような内容になりましたw)

というわけで、
「悪魔に心をやられてしまった新人が、自社システムを炎上させるけど、
 天使が残してくれたヒントを手がかりに、他人が鎮火する」

という、謎のシナリオが生まれました。

謎解きは、天使のヒントが画面上部に常に表示され、
「プレイヤーが次に何をすればよいか」が、そのヒントを読めば理解できるようにしています。
なっているはずです! なっていなけりゃ、ごめんなさい。

アプリ外観

本章では、本アプリのデザインとページ構成について、クライアント的な観点のみから説明します。

画面遷移

image.png

こんな感じです。想定された遷移順としては、

① 導入ページ
② page1 で、問題 1 と問題 2 を考えて 1 つの答えを入力
③ page2 で、問題 3 と問題 4 を考えて 1 つの答えを入力
④ page1 で、別の答えを入力
⑤ page2 で、問題 3 と問題 4 と同じ答えを入力
⑥ ゴール

となっています。
Cookie で、今ユーザーがどの問題に正解したかを記録しています。
その情報を用いて、天使のヒント欄で次にどのような誘導をするべきかを判定しています。

画面レイアウト

少し画面レイアウトについて説明します。
基本的に Bootstrap を使用していますが、現在の設定では画面サイズによるレイアウトの変更は行えていません。

導入画面

image.png

はじめひらひらと手紙が落ちてきます。しばらくすると、Tap! という文字が出ます。
タップすると中身がぼわんと表示されるような、演出が入ります。
そこで手紙の内容を読んでもらって、なんとなくシナリオを理解してもらいたいと思ってます。
PC だとレイアウトが大崩壊します(笑)

基本画面

image.png
こんな感じです。特に言うことは無いです。
レスポンシブなレイアウトを想定して要素を組みましたが、うまくはめる時間がありませんでした。

感想

投稿予定の裏話・開発手法編では、
「何をしたか、何が悪かったか、どうするべきだったか」
について、もう少し詳しく語る予定です。ですが、ここでも少しだけ書かせてください。

まず謝辞

関わってくださった、全ての人に感謝します。

テストプレイをしていただいた、たくさんの同期、出身研究室の後輩、高校の同級生。
そして、恐らく本番プレイしていただいたはずの忘年会の参加者の皆様。
コソコソ開発しているのを、温かい目で見逃してくださったデスク周りの皆様。

本当にありがとうございました。以上を持って、謝辞とさせていただきます。

というわけで、感想です。
本音と建前を使い分けろってのは、ビジネス研修で習った一番大切なことですァァーー!!!!!

(建前)

  • うぇぶさーびすをこうせいする、たくさんのぎじゅつをかんぜんにりかいしました。
  • のうきをみすえながら、すぷりんとばっくろぐをさだめ、しっかりあじゃいるかいはつしました。
  • しゅみのかいはつだったので、みんなたのしくできました。しんじんのなかではじっそうがとくいなひとをあつめたので、じっそうじかんがみじかかった。

(本音)

正直、この Web アプリを開発してほんまに良かったと思ってます。その気持ちに嘘はありません。
メンバーには、感謝しかないです。手伝ってくれた友達、ほんまに感謝してます。
でも、その中で僕は、いろんな後悔、してきました。
僕なりに真剣に考えて、考え抜いた結果です。今回の開発で思ったこと全部、包み隠さず話します。

うぇぶさーびすをこうせいする、たくさんのぎじゅつをかんぜんにりかいしました。

「正直、まったく分かりませんでした。僕の理解が追いついてない。最悪です。」

開発に慣れていないフロントの実装に時間がかかりました。
Bootstrap を使用したものの、レスポンシブデザインは達成されていません。
プロトタイプ版からのデザインはかなり向上しましたが、それでも足りないと思っています。
Bootstrap という世間的には別に新しくもないような技術を使って、
詰まりに詰まってるのは普通に辛かったです。

のうきをみすえながら、すぷりんとばっくろぐをさだめ、しっかりあじゃいるかいはつしました。

「正直、間に合いませんでした。忘年会の直前まで、開発やってました。」

レビューなどでもらった意見を反映に時間がかかりました。
レビューのたびにフィードバックをもらって、そのたびに修正しても、
利用者と開発者のプレイ感覚の差は発生し、是正することを繰り返しました。

特に謎解きにおいては、その時のひらめきに依存する部分が多く、解けたり解けなかったりするせいで、
一体このアプリに何が足りていなくて、どれくらいの難易度なのかがわかりませんでした。
どの程度ヒントを出せば良いか、などに非常に迷いながら謎解きの作成を進めました。
その試行錯誤の結果、楽に誘導してくれる存在として生まれたのが「天使のガイド」だったりします。

また開発が長引いた結果として、 Qiita を執筆する時間がありませんでした!!!!!!!!!!!!
僕が担当する記事を2つに分けたのは、そのせいです。まあ内容はまとまったと思います。

しゅみのかいはつだったので、みんなたのしくできました。しんじんのなかではじっそうがとくいなひとをあつめたので、じっそうじかんがみじかかった。

「正直、楽しくないことも多かったです。信じられないくらい時間がかかりました。
 ほんまに、ストレスで肌荒れが MAX になって、思わずヒゲ脱毛に通い始めました」

本当に趣味だけなら、恐らくこれは完成していません……
趣味の開発のはずなのに、どうしてこんなにつらいの!?
みんな普段から実装が大好きで、得意なはずなのにどうしてこんなことになっているのだろう。
なんで、こんなつらい思いをして、開発をしているのだろうか。
そんなことばかり、最後のほうは考えていました。悲しかったです。
でも楽しかったのは本当です。

作りたいものを大きく設定しすぎ、その割に計画性が無かったことが原因だと思っています。

まとめ

今回は、忘年会の余興のために開発した『謎解き Web アプリ』の紹介を行いました。
本日は簡単ですが、ここまでが 1 本目の記事、とさせて頂いて、
明日 14 日に 2 本目の記事が thtitech くんから、
25 日までのどこかで 3 つ目の記事が私(?)から上がると思います。

Appendix.

本番では、謎解きの前に『寸劇』を行い、形だけですが謎解きへの導入を行っています。
寸劇の台本を公開しない代わりに、寸劇の書き言葉版を公開したいと思います。
供養として、ここに置かせてください。

ではみなさん、ここまで読んでいただきありがとうございました。
次の記事で、お会いしましょう。

ポエム

「SIerに入社したばかり彼は、アサインされた案件の厳しさに毎日てんてこ舞いだ。
家に帰れば、仕事での鬱憤を晴らすためにサンバを踊っていた(参考文献)
しかし、サンバだけではストレス解消が追いつかず、何もできない己への無力感が募るばかり。
ついには、心身共に追い詰められてしまい、自殺を考えてしまう。

ある日。
それは彼がいつも通り仕事を終え、やっとこさ疲弊した体を自宅まで持ち帰ったときの話だった。
とりあえずサンバでも踊るかと彼が思い立った時、

『俺は君の心の中の悪魔だよ。心が炎上してるね~』

突然、心の中の邪悪な部分が悪魔となって実体化した。

悪魔は新人に語りかける。
『あのね~、ウイルス手にいれたんだけどさぁ〜、最期にこれバラまいて会社壊そうよ〜』
心が弱ってしまった彼は、悪魔の言う通り、死ぬ前に散々暴れてやるのも良いかもしれないと考えた。

『ダメよ! ウイルスなんて!』
彼の心が闇に堕ちきる寸前、心の中の善良な部分も天使となって実体化した。
『強く生きるのよ! 一緒に悪魔を倒しましょう!!!!』
まさか、自分の中にそのような善良な部分が未だに存在したとは思いもしなかった。
しかし、疑問だ。
「自分は男性なのに、何故心の中の天使は女性なんだろう」
下らない疑問を持つぐらいの余裕はあることに、自分で自分に少し安心した。
天使の言う通り、今まで真面目に生きてきたんだから、ここで馬鹿なことをしても勿体ない。

いや、でも。

「天使に協力して悪魔を倒したところで、別に社会は変わらないのになぁ」
冷静に、本質的な問題点に思考を巡らせた。冷静沈着な自分に安心した。
「まあ、別に一緒に戦うほどでもないか」
と、天使と悪魔の戦いをぼーっと見守ることにした。

そこから、天使と悪魔の不毛な戦いが始まった。
その戦いは、本当に見るに耐えないものだった。
天界的な異能力とか魔法を使うわけではない。
殴り合い掴み合いとか、そんなものでもない。
突然、『ラップバトル』を始めたのだ。

「ナナナナ~ナナナナ~」

謎のステップと謎のラップ。
どこかのお笑い芸人に感化されたのか、二人はゆるいテンポのラップを交互に披露しあっていた。
俺が勝った私が勝った、あーでもないこーでもないと、よくわからない基準で争い合っている。
なんとも形容し難い気の抜けるようなラップに、いかなる基準で優劣が付けられているのか、甚だ疑問であった。

天使と悪魔が判断に揉めた時、勝敗が彼の判断に委ねられることがあった。
そこで適当に感想を言ってみたら、「お前は何にもラップをわかっていない」と二人して貶してきた。
彼は呆れるしかなかった。天使は味方ではなかったのか。

彼の心が追い詰められているのと同じように、天使と悪魔の心もまた追い詰められていたのである。
彼はため息をつき、二人の不毛な戦いを尻目に、その日は眠りにつくことにした。
その戦いは彼が眠りについたあとも、夜通し続いた。

次の朝、悪魔はこう呟いた。
『彼さん、爆散』
勝敗の天秤は悪魔に傾いたのだ。
そのラップを最後に、彼は体のコントロールを悪魔に乗っ取られ、会社にウイルスを撒き散らしてしまった。

天使は実体化を解かれる寸前、最後の力を振り絞り、
ウイルスの解除プログラムを社内に残すことに成功した。
悪魔にバレないように、解除のためのヒントを謎として残し、他の社員に協力を仰いだのだった。゚(゚´ω`゚)゚。ピー


初心者によるプログラミング学習ログ 183日目

$
0
0

100日チャレンジの183日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

183日目は

カンタンなcssの擬似要素+組み合わせ

$
0
0

cssの擬似要素について

どうも、よわよわエンジニアです。
今回はcssの擬似要素についてさらっとまとめます。

サンプルコード

sample.html
<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><metahttp-equiv="X-UA-Compatible"content="ie=edge"><linkrel="stylesheet"href="sample.css">#cssファイルの読み込み
  <title>CSSの擬似要素</title></head><body><divclass="oya"><pclass="child">ひとりめ</p><pclass="child">ふたりめ</p><pclass="child">さんにんめ</p></div></body></html>
sample.css
.oya{width:100%;font-size:16px;}

実行結果
スクリーンショット 2019-12-13 20.30.16.png

擬似要素とは?

擬似要素とは、要素の一部に対してスタイルを適用できる指定方法です。
HTMLの要素を擬似的にCSSで設定するので、コーディングに手を加えることなく装飾を適用することができます。

:first-child,:last-child擬似要素

例えば上記の例を参考に「ひとりめ」だけ文字色を赤くしたい場合。
擬似要素を使わずに書くと、

sample.html
<divclass="oya"><pclass="child1">ひとりめ</p>#クラス名を変更している
    <pclass="child">ふたりめ</p><pclass="child">さんにんめ</p></div>
sample.css
.oya{width:100%;font-size:16px;}.child1{color:red;}

実行結果
スクリーンショット 2019-12-13 20.34.37.png

このように、クラス名を変更しなければいけません。
今はこれでもいいですが、今後マークアップをしていく中で、クラス名をいちいち変更して管理するのが大変になってきます。
そこで登場するのが擬似要素です。

今回の例では:first-child擬似要素がつかえそうです。
:first-childはその要素群の最初の1つを選択し、変更することができます。

sample.css
.oya{width:100%;font-size:16px;}.child:first-child{color:red;}

このようにしてみましょう。
これは.childの1つ目の要素を赤色に変えるという記述です。
そのため、先ほどの実行結果と同じになります。

この反対で、一番最後の要素だけを変更する:last-childというものもあります

sample.html
<divclass="oya"><pclass="child">ひとりめ</p><----これがfirst-child<pclass="child">ふたりめ</p><pclass="child">さんにんめ</p><----これがlast-child</div>
sample.css
.oya{width:100%;font-size:16px;}.child:first-child{color:red;font-size:20px;}.child:last-child{color:green;font-size:30px;border-bottom:1pxsolidgreen;}

実行結果
スクリーンショット 2019-12-13 20.48.03.png

class名は全て.childですが、
擬似要素で

「ひとりめ」=first-child が赤色の20pxの大きさに、

「さんにんめ」=last-child が緑色の30pxの下線付きになりました。

:before,:after擬似要素

次に、:before:afterです。
これは簡単に言うと、その要素の直前、直後に何かを付与するというものです。

先ほどのサンプルコードに追記して確認していきます。

sample.css
.oya{width:100%;font-size:16px;}.child:first-child{color:red;font-size:20px;}.child:last-child{color:green;font-size:30px;border-bottom:1pxsolidgreen;}.child:before{<----これを追加content:"私は";color:black;font-size:12px;}

実行結果
スクリーンショット 2019-12-13 20.59.07.png
一気に文字が増えましたね。
これは、追加した.child:beforeにより、
.childの直前に"私は"という文字を黒色12pxで表示させています。
:afterはその逆で、要素の直後に付け足すことができます。

sample.css
.child:after{content:"だよー";color:black;font-size:12px;}

を追記すると、.childクラスの直後に"だよー"がつくので
スクリーンショット 2019-12-13 21.05.29.png
こうなります。

では、「さんにんめ」が関西人だったらどうしましょう。

擬似要素の組み合わせ

スクリーンショット 2019-12-13 21.08.20.png

擬似要素をつかって、こうしたい場合
.childlast-childをどうにかしたいが、、、、

実はこの擬似要素、組み合わせて使うことができます!

sample.css
.child:last-child:before{content:"ワイは";color:black;font-size:12px;}.child:last-child:after{content:"やでー!";color:black;font-size:12px;}

.childlast-child:before
"ワイは"とつけてやり、
.childlast-child:after
"やでー!"とつけてやると、上記のような実行結果になります。

おしまい

とても簡単なコードで、4つの擬似要素を説明しました。
実際にこのように使うことは少ないですが、各擬似要素の使い方をマスターできれば、
マークアップの幅がぐんと広がります。

ぜひ活用してください。

SVGで文字をなぞるアニメーションの実装

$
0
0

2018/06/27
SVGに詳しくなりたい

社内のSlackでそう呟いた時から、かれこれ1年半ぐらいの時間が経ちました。

「Scalable Vector Graphics」、通称SVG。

あの頃と比べると今では少し仲良くなれてきた気がしますが、仲良くなるたびにその身に潜む深淵がどんどん明るみになりより深さが増していく、ステキな技術だと感じている今日この頃、Qiita初投稿の題材として選ばせていただきました。

初投稿は2MBまでしか画像を使えない仕様をつい数日前に知ったので、この記事はCodePenによる提供多めでお届けします。。

SVGがHTMLに埋め込める形式で助かった。

あらすじ

とある案件で、メインビジュアルに置いたキャッチコピーにアニメーションを付けたい!という相談があったため、SVGで書かれた文字を動かす方法について調べました。

サンプルとして適当なダミー画像を用意しましたが、

See the Pen Snowrobin_stroke_one by m_shinada (@m_shinada) on CodePen.

こんな感じの一筆書きで繋がっている文字や、

See the Pen Snowrobin_stroke_fill by m_shinada (@m_shinada) on CodePen.

こんな感じの筆記体で書かれた文字だとそれっぽく見え(る気がし)ます。

これらのSVG画像に対して、手書き風になぞるようなアニメーションを付けていきます。

前提条件

  • SVG画像はHTMLに インラインで埋め込むこと
    • inline SVG というやつです
    • SVGのパラメータを制御するためには <img>タグなどではアクセスできないため
  • 必ずアウトライン化されている(文字情報が失われている)こと
    • illustratorなどでフォントを元に画像を作る場合に忘れがち
    • パスを用いたアニメーションなので文字情報のままだと動かせません

仕組み

カギとなるのはSVGにおける stroke-dasharraystroke-dashoffsetという2つのプロパティ。
この2つは互いに stroke-dash...つまり 破線に関するプロパティですね。

----------------------------------------------------
↑こういうふうな、等間隔に線とアキが繰り返される線を破線といいます。

それぞれ、

  • stroke-dasharrayは 破線の間隔(長さ)
  • stroke-dashoffsetは 破線の開始位置

を制御するプロパティとなっています。

「いやでもさっきの画像に破線なんてないですやん」という話なのですが、 stroke-dasharrayある値に設定することで先ほどの画像中の線を破線と同じ扱いにすることができます。
この 線と見た目が同じ破線に変換することが、文字をなぞるアニメーションを実装するための第一歩となります。

stroke-dasharray

線と見た目が同じ破線は、stroke-dasharray線の長さと同じ値にすることで実現できます。
破線のひとかけらの長さが線の長さと同じになることで、見た目は同じなのに破線である……つまり破線のひとかけらがバカでかいためにアキの部分が範囲外に押し出された状態になります。
これにより、線の見た目は変わらないまま破線扱いになるため、破線の開始位置を制御する stroke-dashoffsetが意味をなすようになります。

stroke-dashoffset

stroke-dashoffsetの値を変えることで、破線の開始位置を線の流れに沿って動かすことが可能です。
しかし先ほどの設定によって元々の線と同じ長さとなった破線のひとかけらに対して、 stroke-dashoffsetの値を大きくしていくと、まるで線がスルスルっと外側へ巻き戻るように消えていくように見えます
しまいにこちらも 線の長さと同じ値まで辿り着くと、線は完全に見えない状態になってしまいます。
これは、線の長さめいっぱいの破線のひとかけら分と同じだけ位置がズレたことにより、破線のアキの部分のみが表示された(つまり何も見えない)状態になっているのです。

  • 最小……線が表示された状態
  • 増加……線が巻き戻るように消えていく
  • 最大……線が消えた状態

簡単に遷移をまとめるとこのようになりますが、stroke-dashoffsetを徐々に増加させることで、線が巻き戻って消えるように見えるならば、これと逆の動き、つまりstroke-dashoffset最大(線の長さと同じ)から最小(0)へ徐々に戻すことで、まるで一本の線をなぞり書いたような動きを実現することができるのです!

この辺りの挙動の理解については以下のページにあるデモがとても参考になります:bow:
https://jakearchibald.com/2013/animated-line-drawing-svg/

パスの長さ

ところで、「線の長さ」とはSVGにおけるパスの長さになります。
一筆書きの線のみで構成された画像の場合は、パスの始点から終点までの長さすべてがパスの長さになります。
こうした場合は、illustratorでSVGファイルを開き、「ウィンドウ」→「ドキュメント情報」から、右上のメニューで「オブジェクト」を選択することですぐにパスの長さを知ることができます。

ai_info_pathlength.png

1文字ずつバラけた画像の場合は、各文字の一画ごとにパスの長さが異なるので、一つ一つ調べるよりかは、JSで取得する方が楽かもしれません。

実装

一筆書きの場合

See the Pen Snowrobin_strokeAnimation_css by m_shinada (@m_shinada) on CodePen.

CSSの @keyframeanimationを用いて stroke-dashoffsetの値を変動させることで、なぞるような動きを実現できています。
実装もわかりやすくて楽なのですが、欠点として IE11では stroke-dashoffsetをCSSで段階的に変動させることができないため動作しない、そもそも一筆書きでないと使えないという欠点があります。。

1文字ずつの場合

See the Pen Snowrobin_strokeAnimation_vivus by m_shinada (@m_shinada) on CodePen.

文字がバラけている場合、一画ずつにパスの長さが変わるため、パラメータの取得と制御を vivus.jsにお願いしたパターンです。
こちらはJSにより段階的な制御をしているため、IE11でも機能するはず……?
埋め込みの方がうまく動いていない場合は codepenの方だときちんと動いているかと思います。

あらすじで言っていた案件ではこちらの方法を採用しましたが、実はこの実装では文字本体ではなく、文字にかけているマスクデータのパスを制御しています。
文字を覆い隠す太さの線でマスクデータを文字に合わせて一画ずつ作り、徐々にマスクを剥がすようにして文字を表示していくことで、手書きのようなアニメーションに見えているかと思います。

マスクデータの作成や挙動については、こちらのページを参考にさせていただきました:bow:
https://www.willstyle.co.jp/blog/1569/

まとめ

この動かし方を最初に思いついた人はすごい。調べれば調べるほどいろんなことができて面白いですねSVG。

今回は(急ぎめの実装だったのもあって)ライブラリに頼るところも大きかったので、自前のJSで細かく制御などもしてみたい。。

CSSだけで球体!?錯視トリックで世界を騙せ

$
0
0

この記事は CSS Advent Calendar 2019 14日目の記事です。

伝えたいこと

本来、CSSだけでは球体の表現は難しく、グラデーションでそれっぽくするほかありませんでした。
この課題、アニメーションと周辺環境による錯視のトリックで解決します。

深く考えないでね

ここで紹介するテクニックは実務に応用できません。
CSSアニメーションのジョーク記事としてお楽しみください。
タイトルもジョークです...笑

先に完成図

まずはこのサンプルをご覧ください。
お急ぎの方は、このサンプルを見ておしまいです!
Qiita上では少し動作が重いので、サンプル右上のCodePenロゴをクリックしてご覧ください。

See the Pen Only CSS: Particles Following Camera 1 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

小さな球体が大量に、グルグルと旋回しているように見えませんか?
影も落ちてるし。

このトリックを解説します。
読み進めると、何かわかった感じになります。

下準備

まずは簡単に円を描き、グラデーションでそれっぽいテクスチャを与えます。
とても妥協すれば球体に見えなくもないですが、より確実に「球体」と認識できるよう、チューニングします。

See the Pen Camera following: Step1 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

錯視のテクニック

それっぽいテクスチャだけを与えられ、ちょっと嘘っぽい、ただの円。
「3D空間にある球体」として誤認させるため、3DTransformsでアニメーションを与えます。

ただし、このコントロールには少し癖があります。
CSSの場合、ひとつの要素にはひとつのtransformしか与えることができない。
この制約をうまく回避して実装する必要があります。

2つのアプローチ

ポイントは、円のテクスチャを常に正面を向けながら移動すること。
これをコントロールするアニメーションのアプローチとして、2つ考えられます。

1つは、そもそもrotate系を使わない手法。
比較的簡単ですが、円運動など、複雑な立体機動には向きません。

もう1つは、親要素にrotateを指定し、子要素には逆方向のrotateを指定して打ち消す手法。
こちらのアプローチはコントロールが難しいですが、複雑な立体機動が可能です。

今回は、後者のアプローチで実装します。
迷ったときは難しい道を選べって親父が言ってた。

Y軸回転してみよう

まずは回転専用の要素を追加し、rotateY(縦を軸に回転)で回転させます。
円はコインのように、その場でクルクルと回っています。

See the Pen Camera following: Step2 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

当たり前ですが、この時点ではまったく球体に見えません。

Z軸移動してみよう

次に、移動専用の要素を追加し、translateZ(奥行き方向に移動)させます。
円は、大きな旋回の軌道で、手前から奥へと立体的にグルグル廻っています。

See the Pen Camera following: Step3 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

奥行きは感じますが、まだ球体には見えません。

周回軌道を打ち消すY軸回転を追加しよう

本記事のメインです。
回転打ち消し専用の要素を追加し、旋回とは逆方向にrotateYさせます。
旋回はそのままに、円が常に正面を向くようになります。

See the Pen Camera following: Step4 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

おや?
ひょっとして球体に見えなくもない?

X軸回転で傾けてみよう

ここからは、円をとりまく周辺環境も整えます。
傾き専用の要素を追加し、rotateX(横を軸に回転)で傾きをつけます。
やや斜め上から見下ろしているような視点になります。

See the Pen Camera following: Step5 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

残念、球体には見えなくなりました。

傾きを打ち消すX軸回転を追加しよう

傾き打ち消し専用の要素を追加し、傾きとは逆方向にrotateXします。
ふたたび、円が正面を向くようになります。

See the Pen Camera following: Step6 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

傾きでより強い立体感を演出できました。

グラフィックを調整しよう

ボールに影を落としたり、背景にグラデーションを敷いたりして、全体のグラフィックを整えます。
物理や光源処理、素材感、床の反射率など、リアリティに気を配ります。

See the Pen Camera following: Step7 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

これを見た10人中、7〜8人は球体に見えるのでは。

円を増やしてみよう

トドメだ。
円を3つに増やして、それぞれ旋回のアニメーションにディレイを与えます。
円同士が近すぎるとバレやすいので、ギリギリのところで追いかけているように調整します。

See the Pen Camera following: Step8 by Yusuke Nakaya (@YusukeNakaya) on CodePen.

これを見た10人中、9.5人くらいは球体に見えるのでは。

まとめ

擬似的な球体表現を紹介しました。
大切なポイントは2つ。

  • 円を常に正面に向ける(回転を打ち消す)
  • ひとつの動きに、ひとつの要素

うまく活用できれば、本来は難しいはずの球体表現という圧倒的アドバンテージを得られるでしょう。
なるほどこれは、マジックですね。

フォローミー!

楽しんでいただけたら、フォローしてくれると嬉しいです!🤩
また、Meguro.cssというCSS勉強会も運営しているので、よかったら遊びに来てね!

スマホを使っている気分になれるかもしれないCSS3つ

$
0
0

こんにちは。Media Do Advent Calendar 2019 14日目担当の@hrk02です。
今回はフロントエンド初心者の私が、「CSSってこんなことできるのね!」と感動した技術を3つ紹介します。
少なくてすみません・・・・・

(大変申し訳ないことに、超特急で書き上げたメモです....図解や実装例は今後追加していきたいと思います!)

注意書きとなりますが、ブラウザやブラウザバージョンによっては動作しないものももちろんあります。
基本的にはGoogleChromeやSafariで動くものを紹介しております。

スクロール後にピタッと止まる

スクロールスナップ(scroll-snap)というらしいですね!
調べて初めて知りました。

scroll-snap-typeでどの方向にスライドするか、scroll-snap-alignでどこでピタっと止めるかを指定します。
この技術があれば、よくあるランキングなどの横スライドもいい感じにできますね!

.container{scroll-snap-type:x;}.area{scroll-snap-align:start;}

スムーズにスクロール

よくあるはみ出ているバーなどを横にスクロールさせる際に、指でスーッと移動させることができます(語彙力)
これはあとでイメージ図を挿入する必要がありそうですね・・・・

.area{-webkit-overflow-scrolling:touch;}

長い文章(複数行)を3点リーダーで省略

よくある3点リーダーで省略する実装です。
すごーく昔にやったときは面倒だった記憶があったのですが、今はこんなに便利なのかと驚きました。

もはやスマホ関係ないやんって感じですが、結構思い出に残っているので、メモとして残します。

-webkit-line-clampで、何行まで表示したいか指定します。

.text{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;}

この-webkit-line-clamp-webkit-box-orientverticalの場合のみに適用されます。
ただ、私はAngularでこれを使おうとして結構つまりました。
しっかりと-webkit-box-orient: vertical;をつけているのに、なぜか -webkit-box-orientが効かないのです・・・・

どうして・・・・(´;д;`)
と泣いていたところ、こんな記事をみつけました。

https://github.com/angular/angular-cli/issues/14393
https://qiita.com/watanabejunya/items/40b6c915639be5fa943f

WAO!!!!!!!びっくり!!!!
Autoprefixerのせいなのね・・・・!!!

Autoprefixer
必要なベンダプレフィックスを自動で付けてくれる便利なツール

ということで、下記のように書くことで解決。

.text{display:-webkit-box;-webkit-box-orient:vertical;/* autoprefixer: ignore next */-webkit-line-clamp:2;overflow:hidden;}

おわりに

普段フロントエンド開発を行っている方からすると当たり前なことでも、初心者の私にとっては新鮮な出会いばかりです.....
他の人にとっては当たり前でありふれた内容でも、自分の言葉でちゃんと説明できるようにQiita記事などでアウトプットする習慣をつけたいですね。
現場からは、以上です。

【Vue.js】【ESLint】スコープ付きCSSの利用されていないセレクターを検出するESLintプラグイン作った

$
0
0

この記事は、Vue Advent Calendar 2019 #1の14日目の記事です。


こんにちは。社内ではLintおじさんという二つ名を襲名していて、@ota-meshiという冷やかし感満載なアカウントで割と真面目にやってるつもりの者です。

本記事では、社内でこそこそ作っていたVue.jsのスコープ付きCSS用のESLintの拡張ルールの一部を先日npmで公開したので、その紹介とどんな感じで作ったのかを書こうと思います。

まず、公開したものは以下です。

下記リンクからブラウザ上で試すことができます。
https://future-architect.github.io/eslint-plugin-vue-scoped-css/playground/

特徴

Vue.jsの単一ファイルコンポーネントで利用できる、スコープ付CSS関連のLintルールを提供しています。

動機

eslint-plugin-vueという.vueファイルをLintできる素晴らしいESLintプラグインがありますが、これはCSS(<style>ブロック)関連の情報は関知しません。
また、.vueファイルでも利用できるCSSのリンターである、stylelintという素晴らしいツールもありますが、こちらはCSS以外の情報(例えば<template>ブロック)は関知しません。
これらのツールで実現できない、Vue.jsのスコープ付CSS特有の静的検証を行いたかったというのが、このESLintプラグインを作成した動機です。

stylelintプラグインで作成しても良かったんじゃないの?というのはありますが、.vueファイル用の神パーサーであるvue-eslint-parserを使いたかったのもありESLintプラグインで作成しました。)

使用方法

インストール

npmでインストールします。

npm install--save-dev eslint eslint-plugin-vue-scoped-css

設定

詳しくは以下を参照してください。

https://future-architect.github.io/eslint-plugin-vue-scoped-css/user-guide/#usage

このプラグインは設定構成を提供しているので、ESLint - Using the configuration from a pluginにある方法を利用して、(例えば.eslintrc.jsであれば)以下のように設定して利用できます。

.eslintrc.js
module.exports={extends:[// ...// ... 既にあなたの利用している設定// ...// 下記を追加'plugin:vue-scoped-css/recommended'// ルールを自分で個別に設定したい場合は下記を追加// 'plugin:vue-scoped-css/base'],rules:{// 個別にルールを設定する場合は下記のように追加。// 'vue-scoped-css/no-unused-selector': 'error'}}

提供するLintルール

vue-scoped-css/no-unused-selector

このプラグインの目玉機能です。(というかこのルールを作りたくてこのプラグインを作り始めました。)
<style scoped>内のCSSセレクターの内、<template>ブロックで利用されていないCSSセレクターを検出します。

このルールによって、リファクタリングしていくうちに使われなくなったのにウッカリ残してしまって、利用していない無駄なCSSをスッキリ消していくのに役立ちます。

<template><divid="foo"><inputclass="bar"></div></template><stylescoped>/* ✗ BAD */ul,.foo,#bar{}/* ✓ GOOD */div,#foo,.bar{}</style>

vue-scoped-css/no-unused-keyframes

こちらは、利用していない@keyframesを検出します。

たまに勘違いする人がいると思うのですが(自分も勘違いしていました)、<style scoped>内で宣言した@keyframesは、その<style scoped>内でしか利用できません。
なので、<style scoped>内で宣言した@keyframesは、その<style scoped>内で利用すべきです。利用しない場合は、無駄なデッドコードとなります。

<stylescoped>.item{animation-name:slidein;}/* ✗ BAD */@keyframesfadein{}/* ✓ GOOD */@keyframesslidein{}</style>

vue-scoped-css/require-scoped

scopedが付与されていない、<style>タグを検出します。

私のような、スコープ付CSS大好き人間が<style scoped>を強制したい場合に利用できます。
唯一App.vueにだけscoped無しの<style>を許可したいような場合は、.eslintrc.**をうまいこと構成・配置するか、<script>内にeslintの構成コメントを利用して除外するといいと思います。

<!-- ✗ BAD --><style></style><!-- ✓ GOOD --><stylescoped></style>

このルールはESLint v6.7で追加されたSuggestions APIに対応していまして、Suggestionからscoped属性を追加できるようにしています。VSCodeが対応したらクイックフィックスから選択できるようになるかもしれません。

vue-scoped-css/require-selector-used-inside

先に紹介したvue-scoped-css/no-unused-selectorのもっと強制する版です。
<style scoped>内のCSSセレクターの内、<template>ブロックで利用されていないCSSセレクターを検出します。
こちらのルールは定義したCSSセレクターの各セレクター要素が全て<template>ブロックで利用されていない場合、レポートされます。

どういうことかと言いますと、

<template><div><inputclass="foo"></div></template><stylescoped>.theme.foo{}</style>

とあった場合、.theme .foo.fooは利用できる場合があります。
themeクラスをページのルート要素に付与して.fooのスタイルを変更するみたいなことができます。(この使い方が想定されているかどうかは知らないです。)
そのため、vue-scoped-css/no-unused-selectorでは検出しません。
いや、そんな使い方しないよ!やめてよ!という人はvue-scoped-css/require-selector-used-insideを有効にすると、全てのセレクター要素が<template>ブロックで利用されていない場合にエラーになります。

vue-scoped-css/no-parsing-error

CSSのパースエラーを報告します。

パースエラーはstylelintとか使っておけば確認できるので必要ないんですけど、このプラグインのルール達がパースエラーで動作しないとき、「パースエラーだから動かないんだよ」ってことに気がつくためのルールです。通常は不要なルールです。

構文サポート

CSSとSCSSとStylusをサポートしています。
他は要望があればやるかもしれません。lessは全く知らないので誰か助けて。

作り

機能的な紹介は以上です。ここから先は作った時の思い出です。

CSSとセレクターのパース

CSSのパースにはPostCSSを利用しています。
そして、SCSSのパースにはpostcss-scssを使っています。
そして、セレクターのパースにはpostcss-selector-parserを使っています。
PostCSSファミリー万歳です。

あと、Stylusのパースには「VueファイルのStylusをstylelintしたかった話」の時に作った、postcss-stylを使っています。

セレクターのネストの解決

自作しました。車輪の再発明感ハンパないのですが、正しい箇所にエラーをレポートしたかったので、ここは自作に踏み切りました。
CSSの&セレクター・@nest・SCSSのネストに対応しているはずです。一応Stylusのセレクターも一部対応してます。

CSSセレクターと<template>のマッピング

vue-scoped-css/no-unused-selectorとかやるために<template>内のタグを走査します。
これがなかなか大変でした。全部書くと長いので(既に長いですが)class属性についてだけ思い出を残します。

静的class属性のマッピング

これは余裕です。普通のHTML的に探し出すだけです。

<template><divclass="foo"/><!-- そのまま書いてあるので比較的簡単 --></template>

v-bind:classのインライン式のマッピング

ちょっと大変でしたが、神パーサーvue-eslint-parserがいい感じのASTを返してくれるのでまだなんとかなります。

<template><divv-bind:class="['foo', {'bar': true}]" /> <!-- ASTの解析が必要 --></template>

v-bind:classへのプロパティのマッピング

そろそろきついです。Vueオブジェクト探し出して、ASTを走査し、datacomputedのプロパティを探して、return部分を解析して頑張りました。

<template><divv-bind:class="classes1"><!-- dataを見ると`foo`が入る --><divv-bind:class="classes2"/><!-- computedを見ると`bar`が入る --></div></template><script>exportdefault{data(){return{classes1:['foo']}},computed:{classes2(){return[{'bar':true}]}}}</script>

v-bind:classへの文字列結合のマッピング

きついです。テンプレートリテラルや、文字列結合があった場合は、部分一致で検証しています。

<template><divv-bind:class="`foo-${kind}`" /> <!-- `foo-bar`は一致するとみなす --></template><stylescoped>.foo-bar{}</style>

classList.addのマッピング

きついです。classListによるclass操作は$el$refs経由での操作を探し出してマッピングしました。

<template><div><!-- $elには`classList.add('foo')`されることがある --><divref="div1"><!-- ref名`div1`には`classList.add('bar')`されることがある --><div></template><script>exportdefault{mounted(){this.$el.classList.add('foo')},methods:{onClick(){this.$refs.div1.classList.add('bar')}}}</script>

複雑なv-bind:classへのプロパティのマッピング

無理でした。datacomputedのプロパティの、return部分だけで解決できない情報で、さらにeslint-utilsのgetStaticValueで解決できない情報は諦めて、検出対象から除外しています。

<template><divv-bind:class="classes"/><!-- 何が入るかわからないので全てのクラスが一致するとみなす。 --></template><script>importCONSTfrom'./const-data'exportdefault{computed:{classes(){return[{[CONST.CLASS_FOO]:true}]}}}</script>

まとめ

と、色々頑張った結果、概ね未使用CSSセレクターを検出することができたと思います。
結構頑張ったのでスコープ付CSS使っている方はぜひ使ってみて欲しいです。
もし使ってみて良かったらGitHubでStarつけてくれると励みになりますm(_ _)m

あとがき

このESLint拡張ルールですが、台風で流れたVue Fesのランチ(弊社はランチスポンサーする予定でした)で少し紹介する予定でしたが、行き場を失ったのでこの場で紹介させていただきしました。
来年もVue Fesあるといいなー。

あと。そうそう。僕、今年、Vue.jsのメンバーになりました:tada:関わってくださった皆様ありがとうござます!これからもお宜しくお願いします!

Bootstrap 4 のcarouselを使ってWebサイトにスライドショーを作成する

$
0
0

Bootstrap 4 のcarouselで作るスライドショー

WEBサイトにスライドショーを作成したい。でもなかなか難しそうだし、どうやってやるかわからない。。そんな人におすすめなのがBootstrap4のcarouselです。ちなみにcarouselは英語でメリーゴーランドって意味です。

実際どんな感じになるの

イメージはこんな感じ。(Bootstrap4の公式サイトから引用)

スクリーンショット 2019-12-14 08.15.12.png

このスライドショーがなんと、、コピペでできてしまう。あぁBootstrap恐ろしや。

carousel.html
<divid="carouselExampleControls"class="carousel slide"data-ride="carousel"data-interval="2500"data-pause="hover"><divclass="carousel-inner"><divclass="carousel-item active"style="background-color: red;"><imgsrc="..."class="d-block w-100"alt="..."></div><divclass="carousel-item"style="background-color: yellow;"><imgsrc="..."class="d-block w-100"alt="..."></div><divclass="carousel-item"style="background-color: blue;"><imgsrc="..."class="d-block w-100"alt="..."></div></div><aclass="carousel-control-prev"href="#carouselExampleControls"role="button"data-slide="prev"><spanclass="carousel-control-prev-icon"aria-hidden="true"></span><spanclass="sr-only">Previous</span></a><aclass="carousel-control-next"href="#carouselExampleControls"role="button"data-slide="next"><spanclass="carousel-control-next-icon"aria-hidden="true"></span><spanclass="sr-only">Next</span></a></div>

いろんなスライドショーがあるので、興味ある方は公式サイト見て見てね。
https://getbootstrap.com/docs/4.4/components/carousel/

※複数あるclass="carousel-item"のうち、1つはclass="carousel-item active"にしなければならないので注意。

変えられる要素

要素を追加することで、スライドショーをカスタマイズすることができます。

・『interval』で切り替え時間を変える

intervalのdefault設定は5000ミリ秒。
今回は一行目に data-interval="2500"と設定し、2.5秒に1回画面が切り替わるようにしました。

・『pause』でスライドショーを止める

pauseは何かのactionが行われた時に、スライドを止めるもの。
data-pause="hover"を設定すると、hoverされた時にスライドが止まるのです。
読みたいのにどんどん流れて行っちゃうスライドショーってたまにあるよね笑

・『carousel-fade』でオシャレにスライドする

上記のコードではclass="carousel slide"だけなので普通に画面がスライドしていく感じになります。しかし、class="carousel slide carousel-fade"と記載すると、画面がふわっとfadeしながら変わります(表現下手か)

・『ride』で自動スライドか手動スライドか選ぶ

コード内の
data-ride="carousel" → 自動スライド
data-ride="false" → 手動スライド
になります。

ちなみに、Bootstrapを使用する時はheadタグの中に下記いれないと使えないからご注意を。

getstarted.html
<linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"crossorigin="anonymous">

mediaを使ってNavigation SideMenuを実現する

$
0
0

はじめに

事故マップというサービスを個人開発しています。

このWebアプリでは、画面サイズが小さい場合は自動的にSideMenuを閉じるという動きを入れてレスポンシブなUIを実現しています。

Dec-13-2019 23-58-04.gif

これはCSSのmediaクエリを使えば簡単に実現できるのでその方法を紹介します。

mediaとは

CSS の media を指定すると、一つまたは複数のメディアクエリの結果に基づいて、適用するスタイルシートを変えることができます。

例えば、スクリーンのサイズが 600px 以下の場合に背景の色を変えたい時は次のように指定をします。

@mediascreenand(max-width:600px){body{background-color:#99cc00;}}

Navigation SideMenuの作り方

まずは、HTML全体を3つに分けます。

  • main : コンテンツを配置するエリア
  • topnav : ナビゲーションバー
  • sidenav : サイドメニュー

スクリーンショット 2019-12-14 9.36.54.png

ポイントは、topnavはmainの子要素として配置し、mainはsidenavのwidthの分だけleft-marginを取るようにします。

<html><head><style>.main{margin-left:160px;}.sidenav{width:160px;}</style></head><body><divclass="sidenav"></div><divclass="main"><divclass="topnav"id="myTopnav"></div></div></body></html>

次はmediaをを指定します。

やりたいことは、画面サイズが600px以下になったときにsidenavを非表示にしてmainをsidenavの分大きくすることです。

具体的には次のCSSの指定を行います。

  • 非表示 → display: none;

  • サイズ変更 → margin-left: 0px

@mediascreenand(max-width:600px){.sidenav{display:none;}.main{margin-left:0px;}}

最終的なコード例

<!DOCTYPE html><html><head><metaname="viewport"content="width=device-width, initial-scale=1"><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"><style>body{margin:0;font-family:Arial,Helvetica,sans-serif;}.topnav{overflow:hidden;background-color:#333;}.topnava{float:left;display:block;color:#f2f2f2;text-align:center;padding:14px16px;text-decoration:none;font-size:17px;}.topnava:hover{background-color:#ddd;color:black;}.topnava.active{background-color:#4CAF50;color:white;}.topnav.icon{display:none;}.main{margin-left:160px;/* Same as the width of the sidenav */font-size:28px;/* Increased text to enable scrolling */padding:0px;}.sidenav{height:100%;width:160px;position:fixed;z-index:1;top:0;left:0;background-color:#111;overflow-x:hidden;padding-top:20px;}.sidenava{padding:6px8px6px16px;text-decoration:none;font-size:25px;color:#818181;display:block;}.sidenava:hover{color:#f1f1f1;}@mediascreenand(max-width:600px){.topnava.icon{float:right;display:block;}.sidenav{display:none;}.main{margin-left:0px;}}</style></head><body><divclass="sidenav"><ahref="#about">About</a><ahref="#services">Services</a><ahref="#clients">Clients</a><ahref="#contact">Contact</a></div><divclass="main"><divclass="topnav"id="myTopnav"><ahref="#home"class="active">Home</a><ahref="javascript:void(0);"class="icon"onclick="myFunction()"><iclass="fa fa-bars"></i></a></div><divstyle="padding-left:16px"><h2>Responsive Topnav Example</h2><p>Resize the browser window to see how it works.</p></div></div></body></html>

上記のコードはここですぐに試す事ができます。

サイトに某ほとけ風な何かを呼び出すjQueryプラグイン・hotoke.jsを作った

$
0
0

ご存知の方は知っている某ドラマで現れる、「ほとけ」風ななにかを自分のサイト内に呼び寄せるjQueryプラグインを作成しました。

デモ

実装サンプルはこちらになります。ページを開いてから数秒後に登場します。
hotoke.jsのサンプルページ

使い方

以下のファイルを表示させたいページに読み込みます。

  • hotoke.css
  • jQuery(今回はバージョン2.2.4を使用して作成しました。他のバージョンで動くかは未検証です。)
  • hotoke.js
<linkrel="stylesheet"href="hotoke.css"><script src="jquery-2.2.4.js"></script><script src="hotoke.js"></script>

ファイルを読み込むパスはそれぞれ変更してください。
そして使用したいページで以下を記述します。

<script>$(function(){$('body').hotoke();});</script>

これで実行されます。

カスタマイズ方法

オプション

オプションが2つあり、

  • timeStart ほとけ呼びかけるまでの時間を指定(ミリ秒)
  • hotokeImgPath ほとけの画像へのパス(読み込むHTMLからのパス)
<script>$(function(){$('body').hotoke({timeStart:3000,hotokeImgPath:'../../hotoke.png'});});</script>

デフォルトでは3000ミリ秒でほとけが呼びかけ始めます。画像はそのHTMLと同階層のhotoke.pngを読み込みます。

セリフの変更

最初の呼びかけと、その後のセリフの編集はhotoke.jsを編集します。hotoke.jsの以下の部分を編集してください。ファイルの上部にあります。

//最初の呼び出し文言varhotokeShout=['ヨ○ヒコー','ヨ○ヒコよー'];//ほとけ降臨後の文言varhotokeWords=['ここにセリフを入れることができます。','セリフ2','セリフ3'];

ここに文言を追加・編集することで表示されるセリフが変わります。最後の項目以外は文末にカンマが必要です。

見た目の変更

hotoke.cssを編集してください。ちなみに、最初の呼び出し文言は文字数によって、降臨後の文言は画像の幅によって吹き出しのサイズが変わりますがCSSで変更可能です。

画像の変更

hotoke.pngを差し替えてください。デモの画像はフリー素材を組み合わせただけなので、あなただけのほとけを降臨させてください。

初心者によるプログラミング学習ログ 184日目

$
0
0

100日チャレンジの184日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

184日目は

Bootstrap 4 のcardを使ってWebサイトにオシャレなBOXを加える

$
0
0

オシャレなBOXをBootstrap4の『card』で作る

今回のイメージはこんな感じ。Free、Pro、Enterpriseの3つのBOXのことやね。

スクリーンショット 2019-12-14 22.18.49.png

これは、料金プランの選択肢を作成するときとかにオシャレですよね。

Cardの説明

まずcard単体はこんな感じ。

スクリーンショット 2019-12-14 22.24.12.png

card.html
<divclass="card mb-4 shadow-sm"><divclass="card-header"><h4class="my-0 font-weight-normal">Free</h4></div><divclass="card-body"><h1class="card-title pricing-card-title">$0 <smallclass="text-muted">/ mo</small></h1><ulclass="list-unstyled mt-3 mb-4"><li>10 users included</li><li>2 GB of storage</li><li>Email support</li><li>Help center access</li></ul><buttontype="button"class="btn btn-lg btn-block btn-outline-primary">Sign up for free</button></div></div>

簡単に言うと
上のグレーのFreeのところがclass="card-header"で
下の内容のところがclass="card-body"になってるんね。

そして、この単体のCardを最初の画像みたいにデザインする方法がcard-deck。

Card-deckで単体のcardを整列させる

そして、大事なcardsの整列方法。

スクリーンショット 2019-12-14 22.34.38.png

card-deck.html
<divclass="card-deck"><divclass="card"><imgsrc="..."class="card-img-top"alt="..."><divclass="card-body"><h5class="card-title">Card title</h5><pclass="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p><pclass="card-text"><smallclass="text-muted">Last updated 3 mins ago</small></p></div></div><divclass="card"><imgsrc="..."class="card-img-top"alt="..."><divclass="card-body"><h5class="card-title">Card title</h5><pclass="card-text">This card has supporting text below as a natural lead-in to additional content.</p><pclass="card-text"><smallclass="text-muted">Last updated 3 mins ago</small></p></div></div><divclass="card"><imgsrc="..."class="card-img-top"alt="..."><divclass="card-body"><h5class="card-title">Card title</h5><pclass="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p><pclass="card-text"><smallclass="text-muted">Last updated 3 mins ago</small></p></div></div></div>

class="card"のdivを例えば3つ作って、それらをclass="card-deck"というdivにまとめて入れるだけ。あら簡単。

参考 Bootstrap4 公式サイト
https://getbootstrap.com/docs/4.4/components/card/

ちなみに、Bootstrapを使用する時はheadタグの中に下記いれないと使えないからご注意を。

getstarted.html
<linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"crossorigin="anonymous">

まだCSS使ってるの?SCSS(Sass)を使ってみよう!【入門編】

$
0
0

はじめに

HTMLやCSSを少しでもかじった方ならわかると思いますが、CSSを書いているとき

  • ネストで書けないかな?
  • 変更するときに複数の箇所を変更するのが面倒...
  • 使いまわしたいところがある
  • コメントを/**/で囲むのが面倒...

こんなことを思ったことがありませんか?

実はこれらがSass(SCSS)で簡単に解決するのです!!

SassとSCSSとは?

SassとはSyntactically Awesome Stylesheetsの略です
自分でAwesome(すばらしい)と言うなんてすごい自信ですね(笑)
SassとSCSSの違いを簡単に言うとSassはインデント、SCSSはネストを使ってCSSを楽に書けるようにするものです
今回は私の使っているSCSSの方を紹介します

ネストで書いてみよう

実際に↓のようなものを作ると
ex1.gif
CSSはこのようになります。

css
ul{width:100px;background-color:#4d747e;padding:20px;list-style:none;}ulli{font-size:24px;color:#fff;}ulli.second{color:#e24350;}ulli:hover{background:#55c500;}

ulul liul li.second ul li:hoverのように同じものを何回も繰り返すの面倒に思いませんか?
それではSCSSを見てみましょう♪

scss
ul{width:100px;background-color:#4d747e;padding:20px;list-style:none;li{font-size:24px;color:#fff;&.second{color:#e24350;}&:hover{background:#55c500;}}}

このように繰り返しを減らすだけでなく、親子関係がわかるので非常に重宝します
ただし、SCSSでは&.second&:hoverのなどは&を付けないと機能しないので注意が必要です!

変数を使ってみよう

FireShot Capture 506 - Sass(SCSS) - .png
このCSSは普通に書いても簡単なのですが、

css
h1{color:#e66317;}p{color:#e66317;}

SCSSで書くとこんな感じになります。

scss
$text_color:#e66317;h1{color:$text_color;}p{color:$text_color;}

これはかんたんな例なのであまり恩恵はありませんが、$text_colorの色を変えるだけで他の色を変えることができるということは後々10個とか変えないといけなくなったときに重宝します。

コメントを書いてみよう

/**/ではなくて//でコメントになるよ!(やったね!!)
っていうだけです(でも地味にありがたいんです

最後に

SCSS(Sass)にはまだまだ便利な機能がたくさんあるのですが、今回はここらへんで終わりにします。
これを見てSCSS(Sass)使ってくれたら嬉しいです!

jQueryでフッターをページの長さに合わせてページ下部に固定する方法

$
0
0

1.はじめに

本記事はフッターをページ長さに合わせてページ下部に固定する方法について自分の勉強記録も兼ねて執筆します。

ちなみにfooterFixed.jsというライブラリを使えば簡単にできるみたいですが(笑)、本記事ではそれは使わずに実装していきます。

footerFixed.jsの使い方はこちら

2.目的

フッターをページ長さに合わせてページ下部に固定する

3.コード

簡単ですが、下がコード例です。
今回は簡略下のためcss、JavaScriptをhtmlファイル内に書き込んでいます。(実際は別ファイルで管理する方が良いと思います)

sample.html
<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><style>body{color:#fff;text-align:center;width:50%;margin:0;padding:0;}header{background:blue;height:100px;line-height:100px;}section{background-color:#444;height:200px;line-height:200px;}footer{background:orange;width:50%;height:100px;line-height:100px;}</style><header>ヘッダー</header><section>メインセクション</section><footerid='footer'>フッター</footer><script src='https://code.jquery.com/jquery-3.4.1.min.js'></script><script>$(function(){//フッターを最下部に固定var$footer=$('#footer');if(window.innerHeight>$footer.offset().top+$footer.outerHeight()){$footer.attr({'style':'position:fixed; top:'+(window.innerHeight-$footer.outerHeight())+'px;'});}})</script></body></html>

Google Chromeで表示すると下のようになります。
スクリーンショット 2019-12-14 21.35.46.png

ちなみにcssで要素のheightとline-heightの数値を揃えると文字を上下中央揃えに出来ます。
(結構使えます)

今回のメインとなるコードはその内、下のコードです。

sample.js
<script>$(function(){//フッターを最下部に固定var$footer=$('#footer');if(window.innerHeight>$footer.offset().top+$footer.outerHeight()){$footer.attr({'style':'position:fixed; top:'+(window.innerHeight-$footer.outerHeight())+'px;'});}})</script>

4.コードの解説

では上記のコードを解説していきます。

var $footer = $('footer');

まずvar $footer = $('#footer');でid='footer'のDOMを取得します。
<footer class='footer'>フッター</footer>だったらvar $footer = $('.footer');となります。
id属性とclass属性をつけたセレクタの指定の仕方はcssと同じなのでここでは割愛します。

DOMについてはこちら

簡単にいうとfooter要素を取得したと考えてもらえたらOKです。

フッターのDOMを取得したのでフッターをjavaScript(jQuery)で操作する準備が出来ました。

if(window.innerHeight > $footer.offset().top + $footer.outerHeight() )

まず上記コードの意味を簡単に言うと表示画面(window)の長さがフッターの下端までの距離より長い場合です。

なるべく詳しく説明していきます。

図で表すとこんな状態です。
image.png

上図のように表示画面の高さよりフッター下端までの距離が短い場合、本記事で解説している<script>〜</script>のコードがなければ表示画面の途中にフッターが表示されることになります。

ですので、このような場合にフッターの位置をページ最下部に固定したいのでif文を使っています。

.innerHeightは要素のpaddingを含んだ高さを取得するメソッド
.outerHeightは要素のborder、paddingを含んだ高さを取得するメソッド
.offset().topはその要素の上端の位置を取得するメソッド

です。

高さを取得するメソッドの詳しい説明はこちら
.offset()メソッドの詳しい説明はこちら

$footer.attr({'style': 'position:fixed; top:' + (window.innerHeight - $footer.outerHeight()) + 'px;' });

いよいよフッターをページ最下部へ固定していきましょう。

まず、.attrは要素の属性を取得、変更、追加することのできるメソッドです。

.attrメソッドについてはこちら

style属性を追加して、まず固定するためにposition: fixed;を指定します。
top:〜で固定場所を指定します。
(window.innerHeight - $footer.outerHeight()) + 'px;'で表示画面の下端からフッターのheightを差し引いた位置を指定しています。

つまり、ページ長さに応じて自動でフッターがページ最下部に固定されるということです。

コード解説は以上です!!

※ちなみにcssファイルを別で準備してhtmlファイルに読みこませるようにしていたら.cssメソッドでも実装できるかもです。

5.positon:fixed;との違い

みなさんに質問です。
「フッター固定したいならヘッダーを上部固定するみたいにcssでposition:fixed;を指定すればできるんじゃない?」って思いませんでしたか?
僕は当時は思いました。(みなさん思わないようでしたらすみません)

ですが、フッターに直接position: fixed;を指定した時に困ることがあります。

それについて追加で説明していきます。

まず、WEBサイトをつくる時って1ページで完成することもありますが、複数ページで構成されることの方が多いのではないでしょうか?

複数ページで同じフッターをページ下部に表示することになるので、同じcssを適用することになります。
そのページごとにposition:fixed;の座標をcssで指定しなければならなくなります。

例えば、
ヘッダー、メインセクション、フッターの高さがそれぞれ50px、300px、50pxの場合、

sample.css
footer{position:fixed;top:350px;}

とすれば、以下の通り綺麗にページ下部に固定できますよね。(図は不要と判断しましたのでイメージしてください)

しかし、別のページでメインセクションのheightが500pxになった場合、同じsample.cssを適用すると下の図のようにメインセクションとフッターが重なってしまいますよね。

image.png

このような場合

footer要素に<footer class='footer-1 footer-2'のように複数のclass属性値をつけてcssを分ける必要があります。

これが10ページくらいになるとすると、class属性値も10個つけなればなりません(笑)

控え目に言ってめちゃくちゃメンドクさいです。

プログラミングはめんどくさいことを効率化できるというメリットがあるのにめんどくせいことはできるだけやめましょう。

6.最後に

本記事ではjQueryを用いてページ長さに合わせてフッターをページ最下部に固定する方法について説明しました。

最後にもう一度ソースコードを載せておきます。

sample.html
<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><style>body{color:#fff;text-align:center;width:50%;margin:0;padding:0;}header{background:blue;height:100px;line-height:100px;}section{background-color:#444;height:200px;line-height:200px;}footer{background:orange;width:50%;height:100px;line-height:100px;}</style><header>ヘッダー</header><section>メインセクション</section><footerid='footer'>フッター</footer><script src='https://code.jquery.com/jquery-3.4.1.min.js'></script><script>$(function(){//フッターを最下部に固定var$footer=$('#footer');if(window.innerHeight>$footer.offset().top+$footer.outerHeight()){$footer.attr({'style':'position:fixed; top:'+(window.innerHeight-$footer.outerHeight())+'px;'});}})</script></body></html>

ご存知の方はたくさんいると思いますが、この機能はかなり便利(と思っています)なので是非使ってみて欲しいなと思います!

今回は以上です。

※コメント、ご指摘等ありましたら何でも受付けておりますので気軽にコメントいただけたらと思います。

僕のP2HACKS譚

$
0
0

はじまり

 12月7日~15日に開催される「P2HACKS」に参加してきました!当初に予定していたRailsではなく全く触ったことのない「React」で製作しました。というより、していますのほうが正しいんですが。しかし、全く触ったことのないものでアプリ製作を行って生じる苦労が1つや2つで収まるわけがないんです。

 とういうわけで、アプリ製作中に僕が学んだことや苦労したことのいくつかを書いていこうと思います。注意:書いてることの正確さは保証しません。

1index.htmlをいじらない

 まずそこからかよって思う人もいると思いますが、そこからなんです。HTMLとCSSは少しわかるがJavaScriptはあんまりわからない、という状況で僕はまず初めに脳死でindex.htmlをいじり始めました。
 Reactは基本的にindex.htmlをいじりません。App.js以下をいじっていれば何か変なことをしない限り勝手にindex.htmlを書き換えてくれます。少しだけ具体的に説明します。

index.htmlでは「root」という名前のidを読み込むことになっています。下記の画像は実際のindex.htmlのコードの一部です。
accc1131ed4d6eb22e7f23ed40b62025.png

次にindex.jsですが、「ReactDOM.render(, document.getElementById('root'));」の部分でAppの部分を編集すれば'root'という名前のidの場所でhtmlを書き換えてくれます。さらに、上の方にある「import App from './App'」でApp(fromの後)という名前でexport defaultされたモジュールをApp(fromの前)という名前で受け取ってます。
下記の画像はindex.jsのコードです
97efcb8bad6974329bdc827ca4d3ea67.png

最後にApp.jsです。ここで直接HTMLを操作したりするコードを書きます。下記の画像を見てください。これはApp.jsのコードです。一番下の「export default App」でこのファイルのデフォルトとしてAppというものをexportするよって意味です。だからfunction App(){ ~ }の中を書き書きすれば動きます。

挿入ミス

2jQueryとReactを併用するな

 jQueryとReactを併用してはいけない。理由はjQueryは本物のDOMをいじるがReactは仮想のDOMを使ってコンポーネントを描画するから処理がコンフリクトするらしい。...正直、説明聞いてもよくわからなかったので「併用してはいけない」という知見しか僕は得ることが出来なかった。それとjQueryを使うと問答無用で猫先輩に怒られる。下記は併用してはいけないことを知らずに僕がどや顔で書いたコードです。やりたかったことは画像をクリックしたとき、それが何の画像でも、src属性の値を持ってくるということです。それ自体は成功しましたが、当然没になりました。
ea0ee1d5737ae6f91a1721b130819e71.png

3flexboxについて(css)

 実装した機能の中に、HTMLでulとliを使って画像をたくさん表示するものがありました。しかし、何もしないままだと画像が縦一列に並んでしまうのでとても見にくいUIになってしまいます。
 そこで利用したものが「flexbox」というレイアウトモジュールです。flexboxでは要素を縦や横に柔軟に配置するためのものらしいです。今回やったことは画像をたくさん表示するときに横に3つずつ並べて居れていくことです。4つ目は次の行の一番左に…って感じです。要素を左から右に、入りきらなくなったら下に行を追加していく、ということを実装するには親要素に「flex-wrap:wrap;」を加えてあげればできます。その後、配置する要素の大きさを(100% /n)の大きさにしてあげれば、横一列にn個の要素が入ります。下記は今回実際に実装したulに対して加えたクラスのコードです。
18aa8c2cf806150658ef79fb75ca145e.png

今回のオチ

 今回、自分が先輩に教わったり自分で調べたりしたりして解決した苦労の一部を書きました。画面遷移とかも書きたかったんですが、自分のコード見ても何で動いてるのか思い出せなかったので止めました(笑)。しかも、かなりあやふやな知識で書いてるのであんまりあてにしないでください。あぁ、こいつはこんなことしてたんだな、くらいの気持ちで読んでいてくれたら嬉しいです。(本当はP2HACKSと関係ないことを紹介したかったけど出来なかったなんて口が裂けても言えない。)
 これ書いてる時間がP2HACKS最終日の1時なんですが、まだ開発が終わっていない...。ということで僕は開発を再開しなければならないので今回はこの辺りで。


Sassのmixinを用いたレスポンシブ化

$
0
0

Sassを導入した

CSSにも慣れてきたが
ベタベタのベタ書きがあまりにもひどくて目も当てられず

  • どこに何を書いたか分からなくなる
  • 同じようなスタイルを繰り返し書いている
  • テーマ全体の色味をコントロールしにくい
  • とにかく長すぎる

ある程度セクションごとにわけて書いていたが上記のような問題を早めに解決しておきたいと考えてました。

そこでよく聞くSassはどうやらこれらの問題を解決してくれる今をときめくCSSだとか。

Sassには「Sass」と「SCSS」の2種類の記法がありますがSCSSの書き方が一般的との事だったので早速取り入れました。

今回は1番理解が難しかったレスポンシブ化についてフォーカスして書いてみました。

mixinで画面状態を保存して使い回す

SCSSの細かい記法は置いておいて

@mixinでスタイルをあらかじめ作っておいて
@includeで呼び出して使いまわせる

という強力な能力があり
SCSSの入れ子で記述ができるという特徴と組み合わせるとメディアクエリが簡単かつ可読性の高い作り方ができる

↓イメージ↓

style.scss
@mixinlg{//画面サイズがlg以下を意味する記述をする//}@mixinmd{//画面サイズがmd以下を意味する記述をする//}@mixinsm{//画面サイズがsm以下を意味する記述をする//}p{color:black;@includelg{color:red;@includemd{color:blue;@includesm{color:green;}}}}

これだけの記述で
lgサイズ以上では黒色
lgサイズ以下では赤色
mdサイズ以下では青色
smサイズ以下では緑色
というレスポンシブ化が可能なのです。

mixinの記述方法

じゃあ肝心のmixin中身はどーすんよって話ですが
まずキーとブレイクポイントの値からなる変数を定義します

style.scss
$breakpoints:("lg":"screen and (max-width:1024px)","md":"screen and (max-width:768px)","sm":"screen and (max-width:480px)");

これで
lgのキーは1024px以下
mdのキーは768px以下
smのキーは480px以下
と定義付けができました。

一方mixinはどう書くかというと

style.scss
@mixinmq($breakpoint:md){@media#{map-get($breakpoints,$breakpoint)}{@content;}}

mqというmixinの引数に上記設定した変数のキーをいれることでメディアクエリの処理をさせる。

まあ@contentとかmap-getとか、しっかりと理解はしてません。
コピペは強い!
ちなみに引数内の$breakpoint:mdは引数の初期値をmdに設定するよってもの。

実際に使ってみる

実際に使うとどうなるか。

index.html
<body><divclass="box red"><p>1028px以下で丸に変形</p><p>768px以下で非表示</p></div><divclass="box blue"><p>768px以下で拡大</p><p>480px以下で非表示</p></div><divclass="box green"><p>480px以下で縮小</p></div></body>

上記htmlに対し記述するscssは

style.scss
.red{background-color:red;@includemq(lg){border-radius:50%;@includemq(){display:none;}}}.blue{background-color:blue;@includemq(){height:400px;width:400px;@includemq(sm){display:none;}}}.green{background-color:green;@includemq(sm){height:100px;width:100px;}}

結果こんな動きをします。

ezgif.com-video-to-gif.gif

結論

便利!!

おわりに

個人的にやりやすいからmax-widthで指定して
〇〇以下の時どうのこうの
のような書き方をしてましたが、
様々なサイトを参考にするとmin-widthを用いてるのが多かったです。
モバイルファーストを意識するなら〇〇以上の時〜の書き方に慣れるべきですね。

初めてのJavaScript~ペンの色・太さが変更できるお絵かきアプリを作ったよ~

$
0
0

Webアプリを作りたいなと思いながらなんとなーく先延ばしにしてたところ
初心者向けのJavaScript,HTML,CSSを使ったワークショップを見つけたので参加してみました。
その時作ったお絵かきアプリに機能を追加してペンの太さ・ペンの色の変更・画面の全消しができるようにしてます.

動作環境

あんまりよくわかってないけどCodeSandboxにsign inしてVanillaを使って作りました笑

おそらく…
・CodeSandbox
・Vanilla
・HTML
・JavaScript
・CSS
があればできるんだと思います.
違ってたらすみません.

やること

1.HTMLで部品を作ります

今回はお絵かきする部分とボタンを作成しました.

<!DOCTYPE html><html><head><title>Parcel Sandbox</title><metacharset="UTF-8"/></head><body><divid="app"></div><!--お絵かきする画面を消すボタン--><div><buttonid="pen-ss">極細</button><buttonid="pen-s"></button><buttonid="pen-m"></button><buttonid="pen-l"></button><buttonid="pen-ll">極太</button></div><!--お絵かきするところ--><div><canvasid="draw-area"width="400px"height="400px"style="border: 1px solid #000000"></canvas></div><!--色を変えるボタン--><div><buttonid="color-red"></button><buttonid="color-blue"></button><buttonid="color-green"></button><buttonid="color-black"></button><buttonid="eraser">消しゴム</button><buttonid="clear-button">全消し</button></div><script src="src/index.js"></script></body></html>

おそらくこんな感じになるかと…
スクリーンショット 2019-12-14 17.25.34.png

これでは動かないのでJavaScriptさんに動かしてもらいましょう

2.JavaScriptの登場

特にどうってこともないのでコード載せます

import"./styles.css";constcanvas=document.querySelector("#draw-area");constcontext=canvas.getContext("2d");canvas.addEventListener("mousemove",event=>{draw(event.layerX,event.layerY);});canvas.addEventListener("touchmove",event=>{draw(event.layerX,event.layerY);});//パソコンでクリックしてる間だけ描けるようにした機能canvas.addEventListener("mousedown",()=>{context.beginPath();isDrag=true;});canvas.addEventListener("mouseup",()=>{context.closePath();isDrag=false;});//スマホで描けるようにする機能canvas.addEventListener("touchstart",()=>{context.beginPath();isDrag=true;});canvas.addEventListener("touchend",()=>{context.closePath();isDrag=false;});//お絵かきするところをきれいにする機能constclearButton=document.querySelector("#clear-button");clearButton.addEventListener("click",()=>{context.clearRect(0,0,canvas.width,canvas.height);});//ペンの色を変える機能constcolorRed=document.querySelector("#color-red");colorRed.addEventListener("click",()=>{context.strokeStyle="red";});constcolorBlue=document.querySelector("#color-blue");colorBlue.addEventListener("click",()=>{context.strokeStyle="blue";});constcolorGreen=document.querySelector("#color-green");colorGreen.addEventListener("click",()=>{context.strokeStyle="green";});constcolorBlack=document.querySelector("#color-black");colorBlack.addEventListener("click",()=>{context.strokeStyle="black";});//消しゴムの機能consteraser=document.querySelector("#eraser");eraser.addEventListener("click",()=>{context.strokeStyle="white";});//ぺんの太さを変える機能constpenSS=document.querySelector("#pen-ss");penSS.addEventListener("click",()=>{context.lineWidth=1;});constpenS=document.querySelector("#pen-s");penS.addEventListener("click",()=>{context.lineWidth=5;});constpenM=document.querySelector("#pen-m");penM.addEventListener("click",()=>{context.lineWidth=10;});constpenL=document.querySelector("#pen-l");penL.addEventListener("click",()=>{context.lineWidth=15;});constpenLL=document.querySelector("#pen-ll");penLL.addEventListener("click",()=>{context.lineWidth=20;});letisDrag=false;//線をかく機能functiondraw(x,y){if(!isDrag){return;}context.lineTo(x,y);context.stroke();}

ここまでできればとりあえず動きます
デザインにも凝りたいって方はCSSをいじってください

3.CSSでも書きますか

今回はこだわりがなかったのでとりあえず実装しました程度です

/*お絵かきするところからはみ出た部分を隠してみた*/body{overflow:hidden;}

完成

スクリーンショット 2019-12-14 17.34.16.png

できました!
一応完成したやつのURL載せときます
パソコンでもスマホでも動くようにしました.
Androidで動くかはわかんないです
完成版

cssだけでうんち書いてみた

$
0
0

💩世界はうんちで満ちている💩

大人が1日に排せつするうんちの量は平均して400~500g、これは1年で換算すると142kgに相当します。142kgという重さはパンダ1頭分だそうです。
大人の💩

地球上の人間が1年で排せつするうんちの量は、約2900億kgに相当するとのこと。
地球の💩

これだけ世界を満たしている💩!
こりゃcssだけで書く需要ありそうです!💩💩💩

💩cssだけで書く💩

といってもhtmlも使わないといけない。
でも、それでも、極力使わない方法で書いてみたぞ!💩💩💩

See the Pen unchi by petapetapeta (@petapetapeta) on CodePen.

ちょっと僕の形(アイコン画像)からは遠のいてしまった。
だがしかし、ある程度似ているはずだから許してもらいたい。
ポイントは、backgorund-imageradial-gradient()でゴリ押ししていくことだ!
backgorund-sizebackgorund-positionも併用してゴリ押しする!
beforeafterの疑似要素を使って目と口を添えてやれば、立派なうんちの出来上がりだ!💩💩💩

💩参考💩

人は一生でどのくらいのうんちをするのか?をイラストで解説するとこうなる

classの小話 (cssが適用されないエラーについて)

$
0
0

はじめに

HamlSassでありがちなミスについて書いてみました。

実行

次のようなビューファイルがあるとします

.top.top__contents=image_tagsrc="https://image.png",class: ".top__contents__image"

画像表示させるコードです。
画像はリンクで表示させ、imageというクラスを設定してみます。
この画像の大きさを、height: 100px, width: 120pxにするために、次のようなCSSを適用してみます。

.top{&__contents{&__image{height:100px;width:120px;}}}

この状態では、画像は思った通りの大きさになりません。
一見すると問題なさそうですが、実は画像のクラスと、CSSが適用させようとしているクラスが間違っているからです。
最初のコードで、画像のクラスをclass: ".top__contents__image"としていますが、実は最初の.が必要なく、全く別のコードとして認識されています。
正しいコードは次のようになります。

.top.top__contents=image_tagsrc="https://image.png",class: "top__contents__image"

これで狙った画像の大きさになります。
この問題の厄介なところが、他の箇所は問題なくCSSが適用されるので、問題がどこにあるのかがわかりにくいことです。
延々と間違いのないCSSを編集し続けることもありえます。
なので、もしCSSが上手く適用されない時は、クラスが正確にかけているかどうかを確認すると良いかと思います。

HTMLとCSSでカレーライスを作った

$
0
0

カレーライスを作りました

See the Pen カレーライス by Thugumi Ishimaru (@thugumi-ishimaru) on CodePen.

どうやって作ったの

この記事ではカレーライスをHTMLとCSSで作ったときのポイントをいくつか抜粋したものを紹介します。
実業務ではきっと役には立ちませんので、
「CSSってこんな表現できるんだな」・「CSS楽しい」と思っていただければ幸いです。

パーツを細かく作る

カレーのカレーによるカレーのためのAtomic Designの記事で言及した、
Atomic Designの考えを元にして作りました。

Atomsの用意

  • にんじん
  • じゃがいも
  • 牛肉
  • 切った具材

スクリーンショット 2019-12-15 0.18.11.png

スクリーンショット 2019-12-15 0.18.16.png

スクリーンショット 2019-12-15 0.18.25.png

スクリーンショット 2019-12-15 0.18.38.png

スクリーンショット 2019-12-12 18.40.16.png

スクリーンショット 2019-12-15 0.18.31.png

これらをどう作ったか後ほど解説します。
(厳密には米はMoleculesですが、まぁよしとしましょう。)

これらを全て組み合わせることで、カレーライスを完成させました。

では、次に実際によく使ったCSSプロパティを紹介します。

秘伝のカレー3つのスパイス(プロパティ)

今回カレーライスを作るにあたって以下を意識しました。

  • 丸みや、曲線の表現

逆に言うとこの2点しか抑えてなかった

box-shadow:立体感を持たせるスパイス

https://developer.mozilla.org/ja/docs/Web/CSS/box-shadow

box-shadowは、要素に対して影をつけることができます。
これによってより立体的なになるように表現します。

じゃがいもの影のグラデーション、人参の棒線、切った具材の影、皿の凹凸等を再現しました。
じゃがいもを例にとってみます。

スクリーンショット 2019-12-15 10.58.57.png

じゃがいものdivを用意します。

<divclass="jaga"></div>

作成したdivに対して、box-shadowで土感を、
border-radiusでじゃがいも特有の丸み・曲線を表現します。

.jaga{width:300px;height:250px;background:#E8CD7F;border-radius:40%40%44%40%/35%65%40%70%;box-shadow:inset17px-20px36px24pxrgba(203,163,44,0.7),inset7px8px8px2pxrgba(149,94,55,0.3),10px9px11px-13pxrgba(178,113,49,0.64),inset31px0px96px-21px#B07331;}

border-radiusについてはこの後に解説します。

box-shadowは以下の値を設定できます。

box-shadow: {横にズラす値} {縦にズラす値} {ボカす値} {色};

また、insetを指定することで要素の内側に影をつけることができ、
さらにカンマ区切りにすることで上下左右それぞれに異なった影をつけることが可能です。
今回はじゃがいもの内側に影をつけてボカしたかったので、以下を指定しました。

box-shadow:inset17px-20px36px24pxrgba(203,163,44,0.7),inset7px8px8px2pxrgba(149,94,55,0.3),10px9px11px-13pxrgba(178,113,49,0.64),inset31px0px96px-21px#B07331;

これで、じゃがいものベースが出来上がりました。
スクリーンショット 2019-12-15 11.10.49.png

中にじゃがいもの芽を記述して完了です。
(ここでは省略するので、詳細はcodepenをみてください)
https://codepen.io/thugumi-ishimaru/pen/abzvGaq

border-radius:より自然な形にするスパイス

https://developer.mozilla.org/ja/docs/Web/CSS/border-radius

border-radiusは要素の角を丸めるのに使います。
円形や、真四角のボタンを角丸にするために使用することが多いです。
今回はじゃがいもの曲線や、牛の体、切った具材の形等の変形・ご飯のモコモコ感を再現するのに使用しました。
ここでは、切った具材とご飯を例にあげます。

左上・右上・右下・左下の丸みの数値を個別で指定します。

<divclass="ninjin"></div><divclass="jaga"></div><divclass="niku"></div>
$ninjin:#FF5F00;$ninjinShadow:#F44A1C;$jaga:#F2BD38;$jagaShadow:#CE8117;$niku:#BE6B21;$nikuShadow:#882B11;.ninjin{width:75px;height:100px;background:$ninjin;border-radius:80%26px60px23px;// 左上80%,左上26px,右下60px,左下23pxbox-shadow:inset-10px10px0$ninjinShadow;transform:rotate(95deg);}.jaga{width:115px;height:100px;background:$jaga;border-radius:80%76px70px33px;// 左上80%,左上76px,右下70px,左下33pxbox-shadow:inset-11px-5px0$jagaShadow;}.niku{width:97px;height:57px;background:$niku;border-radius:70px26px80px23px;// 左上70px,左上26px,右下80px,左下23pxbox-shadow:inset-6px-5px0$nikuShadow;}

この結果がこちらです。
にんじん、じゃがいも、肉それぞれいろんな丸みを持ったものができました。
上記で紹介したbox-shadowを使って影をつけて完了です!

スクリーンショット 2019-12-15 0.18.38.png

また、丸みのあるdiv同士を重ねることでご飯のもこもこ感を表現します。

まず、ご飯の中央部分とその周りを取り巻くもこもこ用のdivを作ります。

<divclass="rice"><divclass="rice_around"><divclass="rice_aroundItem rice_aroundItem-1"></div><divclass="rice_aroundItem rice_aroundItem-2"></div><divclass="rice_aroundItem rice_aroundItem-3"></div><divclass="rice_aroundItem rice_aroundItem-4"></div><divclass="rice_aroundItem rice_aroundItem-5"></div></div></div>

スクリーンショット 2019-12-15 19.28.07.png

このままではカッピカピの白米です。
インド人もびっくりです。

歯が割れちゃいけないので.rice_aroundItemに対して、border-radius:50%をつけ、丸みを出しご飯を柔らかくします。

スクリーンショット 2019-12-15 19.28.35.png

あとは、高さ・位置をpositionを駆使して調節・中の盛られている米粒たちを
表現すれば完成です。

スクリーンショット 2019-12-15 19.35.31.png

mask-image:角がある味(鋭角)をまろやかにするスパイス

mask-imageは要素のマスクレイヤーとして使用する画像の設定を行います。
上記の、「丸みのあるdiv同士を繋げたけど、鋭角が気になる。。。」といったところの解決方法として使用しました。

今回はカレールーの下記枠部分の曲線を表現するのに使いました。
スクリーンショット 2019-12-15 19.41.47.png

参考にした記事は以下です。
HTML + CSSでリアルな目玉焼きを作る

mask-imageradial-gradientを使用して、曲線部分を作成しました。

では具体的な作り方です。

まず上記のご飯と同様に丸みのあるdivを用意します。

<divclass="roux"><divclass="roux_item roux_item-1"></div><divclass="roux_item roux_item-2"></div><divclass="roux_item roux_item-3"></div><divclass="roux_item roux_item-4"></div></div>

スクリーンショット 2019-12-15 19.45.41.png

原始人の肉みたいなのができました。
このままでは、角があり、カクカクしててカレールーには見えません。
トロッと感を出すために、ここでmask-imageradial-gradientの登場です。

まず、鋭角を隠すために.roux_hideを作成します。
作成した.roux_hideに対して、mask-imageradial-gradientを設定します。

/*色々省略*/.roux{&_hide{background:$roux;position:absolute;z-index:2;&-1{width:70px;height:60px;-webkit-mask-image:radial-gradient(circleat50%-170%,rgba(0,0,0,0)80%,#BB5B2A80%);top:-43px;left:108px;transform:rotate(-1deg);}&-2{width:70px;height:50px;right:-32px;top:92px;transform:rotate(85deg);-webkit-mask-image:radial-gradient(circleat50%-180%,rgba(0,0,0,0)80%,#BB5B2A80%);}&-3{width:60px;height:80px;-webkit-mask-image:radial-gradient(circleat20%-130%,rgba(0,0,0,0)90%,black90%);transform:rotate(-173deg);top:95%;right:32%;}&-4{width:40px;height:80px;-webkit-mask-image:radial-gradient(circleat20%-160%,rgba(0,0,0,0)90%,black90%);transform:rotate(-93deg);top:150px;left:-39px;}}}

その結果がこちらです。

スクリーンショット 2019-12-15 19.51.36.png

mask-imageで作成した要素(.roux_hide)のくり抜きを設定し、radial-gradientで円の中心位置、サイズ、色を指定し透明にくり抜くようにしています。

盛り付け:お母さん「ご飯よーーーーーーー!!!!!」

色々と端折りましたが、ついに盛り付けです。

実家のカレーはルーを真上からかけます。

1つ1つのパーツをAtomsから作成したので、codepenで作成したもの1つ1つをコピペでペッと貼るだけです。
その後、位置・サイズ調整等を行い、カレーライスの!!!完成です!!!!!!

スクリーンショット 2019-12-14 20.06.55.png

さいごに

HTMLとCSSだけでカレーライスを作りました。
CSSでお絵かきする時に以下3つを覚えてってください!

  • box-shadow:影をつけるよ
  • border-radius:丸みを出してふんわりさせるよ
  • mask-image(IEは対応してません😈):滑らかな曲線にするよ

Twitterやってます!よかったらフォローしてみてください!

ありがとうございましたー!
カレーアドベントカレンダー引き続きよろしくお願いします。

Viewing all 8499 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>