20191203のHTMLに関する記事は16件です。

Three.jsで遊んでみよう

「GLSLの記事書いておいて、今さらWebGLのライブラリかよ!」というツッコミは置いておいて
実はオライリーのThree.jsの参考書を読んでいる最中なのです。
(第2版の内容はr78ですが、ここではr107で進めていきます。)

これからThree.jsを触ってみようという方向けに
流動食のように咀嚼しやすく飲み込みやすく書いていこうと思います。

Three.jsとは?

WebGLをイチから書くのは、とんでもなく大変なのです………。
「じゃあ、WebGLを簡単に書けるようにしようじゃなイカ!」
そうして生まれたJavaScriptのライブラリです。

WebGLのライブラリは他にもありますが、代表的なものだと
2DはPixiJS、3DはThree.js
といったところでしょうか?

そもそもWebGLとは?

すっごく簡単に言うと

インターネットブラウザをプレイステーションにしてしまう魔法の技術
(引用元:http://wise9.jp/archives/6060)

もうちょっと詳しくいうと…
ブラウザ上で3DCGプログラミングを実現できる、JavaScriptから利用できるAPI。
ブラウザを通してデバイスのGPUにアクセスすることができます。
(GPU:PCの中で画像処理を専門とした頭脳)

(上記ですでに書いてはいますが)
WebGLと聞くと3Dがすぐ思い浮かぶかと思いますが、実はWebGLは3Dのためだけの機能ではなく、2Dでの表現も可能です。

Three.jsで3D空間をつくってみる

まず、3D空間をつくる流れを説明します。

とりあえず何が必要でしょう…?

シーン
いわゆるステージ。テレビの撮影スタジオみたいなもの。すべてを保持し監視するコンテナ。

カメラ
そのままカメラ。シーンに何を描画するかを決定する。

レンダラ
すべてを踏まえ、つくったシーンがどう見えるか計算してくれる。

イラストにするとこんな感じでしょうか??

img_01.jpg

コードはこんな感じ↓↓↓

<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/107/three.min.js"></script>
</head>

<body>
<script>
var scene;
var camera;
var renderer;


function init() {
  // まず、シーンをつくる。
  scene = new THREE.Scene();


  // そして、カメラをつくる。PerspectiveCamera は遠近感があり自然な見た目になります。
  // PerspectiveCamera の引数は (視野角, アスペクト比, 近くはどこまで映すか, 遠くはどこまで映すか)
  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
  // カメラの位置を指定する。
  camera.position.set(-20, -15, -30);
  // カメラの視点を指定する。この場合はシーンの位置。
  camera.lookAt(scene.position);


  // 最後に、レンダラをつくる。antialias を true にしてあげると輪郭のギザギザが滑らかになりますが、重たくなるのでそこは様子をみて。
  renderer = new THREE.WebGLRenderer({ antialias: true });
  // デバイスの解像度を指定する。
  renderer.setPixelRatio(window.devicePixelRatio);
  // レンダラのサイズを指定する。
  renderer.setSize(window.innerWidth, window.innerHeight);


  // ボディにレンダラ(canvas)を追加する。
  document.body.appendChild(renderer.domElement);

  // レンダー用関数呼び出し
  render();
}


// レンダー用関数
function render() {
  // レンダラをシーンに追加する。
  renderer.render(scene, camera);
  // 1フレームごとにループする。
  requestAnimationFrame(render);
}


// リサイズイベント
function onWindowResize() {
  // カメラのアスペクト比を更新する。
  camera.aspect = window.innerWidth / window.innerHeight;
  // カメラのパラメータを変更したら必ず呼び出す。(カメラ投影行列を更新)
  camera.updateProjectionMatrix();
  // レンダラのサイズを更新する。
  renderer.setSize(window.innerWidth, window.innerHeight);
}


window.addEventListener('DOMContentLoaded', init);
window.addEventListener('resize', onWindowResize);
</script>
</body>

さて、見てましょう………!とはいかず、見てもエラーにはなりませんが
あくまで空間をつくっただけですので何も映りません。

ものを映すために必要なのは

ここからは撮影風景を思い浮かべるとわかりやすいかもです。

ライティング
撮影にはライティングが大事。

オブジェクトの配置
頑張って3D空間をつくっても、撮影小物や役者がいないと何も映らないですよね。

ここでもイメージイラストを載せておきます…笑

img_02.jpg

さてさて、以下はオブジェクトをつくるのに必要なもの…それは3つあります。

ジオメトリ
オブジェクトの形状を表す情報。ポリゴン。(頂点や線分、面など)

マテリアル
オブジェクトの質感の情報。オブジェクトの皮のようなもの。(色や、金属っぽいのか木っぽいのか…など)

メッシュ
ジオメトリとマテリアルの集合体。ここでいうと、オブジェクト=メッシュになります。

流れとしては、
① ジオメトリで形状をつくり、マテリアルで質感をつくる。
② 最後にメッシュにこの2つをいれてあげることでオブジェクトが完成します。

先ほどのサンプルに、オブジェクトを配置します。
(今回はライトの影響を受けないマテリアルを使用するので、ライトは省きます。)

<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/107/three.min.js"></script>
</head>

<body>
<script>
var scene;
var camera;
var renderer;

function init() {
  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.set(-20, -15, -30);
  camera.lookAt(scene.position);

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);


  // 円球のジオメトリ(ポリゴン)をつくる。SphereBufferGeometry の引数は (半径, 横方向を何面にするか, 縦方向を何面にするか)
  var sphereGeometry = new THREE.SphereBufferGeometry(6, 36, 36);
  // 円球のマテリアル(質感)をつくる。
  var sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
  // 円球のジオメトリとマテリアルをメッシュにまとめる。
  var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  // シーンに円球を追加する。
  scene.add(sphere);


  document.body.appendChild(renderer.domElement);

  render();
}

function render() {
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

window.addEventListener('DOMContentLoaded', init);
window.addEventListener('resize', onWindowResize);
</script>
</body>

img_03.jpg

確かに円球らしきものは見えましたが、これだけだと面白くはないですよね〜…
…ということで、もう少しゴニョゴニョしたいと思います。

<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/107/three.min.js"></script>
</head>

<body>
<script>
var scene;
var camera;
var renderer;
// キューブマップ
var cubeMap = {
  path: './assets/cubemap/',
  urls: [ 'posx.jpg', 'negx.jpg','posy.jpg', 'negy.jpg','posz.jpg', 'negz.jpg' ]
}

function init() {
  scene = new THREE.Scene();
  // シーンの背景にキューブマップを設定する。
  scene.background = new THREE.CubeTextureLoader().setPath(cubeMap.path).load(cubeMap.urls);

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.set(-20, -15, -30);
  camera.lookAt(scene.position);

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);

  var sphereGeometry = new THREE.SphereBufferGeometry(6, 36, 36);
  // マテリアルに環境マッピングを設定する。(シーンの背景)
  var sphereMaterial = new THREE.MeshBasicMaterial({ envMap: scene.background });
  var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  scene.add(sphere);

  document.body.appendChild(renderer.domElement);

  render();
}


function render() {
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}


function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}


window.addEventListener('DOMContentLoaded', init);
window.addEventListener('resize', onWindowResize);
</script>
</body>

img_04.jpg

これはいわゆる環境マッピングというやつです。
(スカイボックスを作らないでシーンに背景をそのまま貼り付けられるようになったんだ…とか、こっそり感動していました。)

ここでは紹介していませんが、OrbitControlsdat.guiを使うと
マウスでぐりぐり動かせたり、メーターで色や形を変更できるようになります。

最後に

Three.jsはどうしても3DCGの知識が伴うので、あまり知らない人にとっては敷居が高いかもしれません。
…が、ちょろっと遊ぶくらいなら簡単にできるので、ぜひとも遊んでいただきたいです。

また、誤字や間違いなどがあれば、ご指摘いただけると幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

100日チャレンジの175日目

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

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

175日目は

最近ただのログとりになってますね。
まあ、しょうがありません。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ハーイ、バブー、ちゃーん

まじでこの世の全てのイクラ好きに教えてあげたいんだが

このQiitaの記事には全ての人間を虜にする禁断のイクラのレシピがある。
これが美味しそうでもなく、もはや食べられないのだが、
HTMLとCSSだけでイクラを再現したからぜひ全国のイクラ好き、
イクラを愛する者たち、イクラを憎む者たち、全てのイクラ関係者に伝われ

イラストチックなイクラを作った

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

イクラのレシピ

HTMLを用意する

イクラの枠組みを作る

<div class="container">
  <div class="ikura">
    <div class="ikura_inner">
      <div class="ikura_luster">
        <div class="ikura_lusterInner"></div>
      </div>
    </div>
  </div>
</div>

スタイルシートを用意する

イクラに命を捧げましょう
まずは色を適当につけます。

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

なんだか、心もとないですね。
イクラの色は箇所によって薄いところと、濃い色の箇所があるので、
そこを linear-gradient で再現しましょう。

.ikura {
  background: linear-gradient(#D83F28, #FB8B00 95%);
  &_inner {
    background: rgba(246, 74, 7, 0.5);
  }
}

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

少しイクラ感出てきました。
ただ、なんかまだイラスト感がありますね。
外側のイクラの色と内側のイクラの色の境目がパキっとなっているので、
box-shadowで境目のパキっと感をぼかしてあげましょう。

.ikura_inner {
  box-shadow: 5px 5px 10px 0px rgba(246, 74, 7, 0.5);
}

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

少し柔らかい印象になりました。

最後に、白い光沢の部分に若干影をつけてあげるとより近づきます。

.ikura_luster {
  background: #fff;
  box-shadow: -7px 2px 7px 11px #DA8151;
}

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

イクラーーーー!チャーーーーーーン!!!!

最後に全体のscssを置いておきますね。(汚いとかはちょっとすみません)

.ikura {
  background: $ikura;
  width: 200px;
  height: 200px;
  border-radius: 100%;
  transform-style: preserve-3d;
  perspective-origin: 0% 50%;
  &_inner {
    background: rgba(246, 74, 7, 0.5);
    box-shadow: 5px 5px 10px 0px rgba(246, 74, 7, 0.5);
    width: 180px;
    height: 180px;
    border-radius: 50%;
    transform: translateX(5px) translateY(3px);
  }
  &_luster {
    background: #fff;
    border-radius: 50%;
    width: 40px;
    height: 30px;
    margin: auto;
    transform: translateX(-70%) translateY(90%) rotate(-40deg);
    box-shadow: -7px 2px 7px 11px #DA8151;
    position: relative;
    &:after {
      content: "";
      display: block;
      position: absolute;
      width: 30px;
      height: 40px;
      background: #fff;
      border-radius: 50%;
      transform: rotate(118deg);
      right: -6px;
      top: -4px;
    }
  }
}

おわりに

か、カレーは明日から()

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ブラウザでbase64エンコードしたPDFファイルを表示する

概要

ブラウザでbase64のPDFファイルを表示する。

実装

HTML5の標準機能で実装可能。
↓の !!!!ここにbase64エンコードしたPDFファイルの文字列を入れる!!! 部分にbase64エンコードしたPDFファイルの文字列を入れる。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8" />
  <title>Document</title>
</head>

<body style="height: 100%; width: 100%; overflow: hidden; margin:0px; background-color: rgb(82, 86, 89);">

  <embed style="position:absolute; left: 0; top: 0;" width="100%" height="100%" type="application/pdf"
    src="data:application/pdf;base64,!!!!ここにbase64エンコードしたPDFファイルの文字列を入れる!!!" />

</body>

</html>

おまけ

base64エンコード用のコマンド。

base64 -w0 Untitled-1.pdf > tmp.txt
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CakePHP2】formタグのスコープ外からformの内容をcontrollerに送信

やりたいこと

formタグの外にあるボタンやリンクでもcontrollerに値を渡したい

やったこと

test.ctp
                            <?= $this->Form->create('HogeList', ['type' => 'GET']); ?>
                            <div class="searchInputArea" style="margin-bottom: 0px;margin-top: 0px;">
                                <table class="em9">
                                    <tr>
                                        <th>
                                            ID
                                        </th>
                                        <td>
                                            <?php
                                                echo $this->Form->input('id', [
                                                    'type'     => 'text',
                                                    'id'       => 'item_id',
                                                    'size'     => 30,
                                                    'label'    => false,
                                                    'div'      => false,
                                                    'empty'    => true,
                                                    'required' => false,
                                                ]);
                                            ?>
                                        </td>
                                    </tr>
                                    <tr>
                                        <th>
                                            名前
                                        </th>
                                        <td>
                                            <?php
                                                echo $this->Form->input('name', [
                                                    'id'       => 'name',
                                                    'type'     => 'text',
                                                    'size'     => 30,
                                                    'label'    => false,
                                                    'div'      => false,
                                                    'empty'    => true,
                                                    'required' => false,
                                                ]);
                                            ?>
                                        </td>
                                    </tr>
                                    <tr>
                                        <th>
                                            ステータス有効のみ
                                        </th>
                                        <td>
                                            <?php
                                                echo $this->Form->input('status', [
                                                    'type'  => 'checkbox',
                                                    'div'   => false,
                                                    'value' => TestAppModel::STATUS_ACTIVE,
                                                    'label' => '',
                                                ]);
                                            ?>
                                        </td>
                                    </tr>
                                </table>
                            </div>
                            <div class="submitArea hasSubAction">
                                <ul class="submitButtons">
                                    <li>
                                        <label class="submitBase primary" for="submit">
                                            <?php echo $this->Form->hidden('mode', ['value'=> '']); ?>
                                            <?php
                                                echo $this->Form->submit('検索', [
                                                    'type'  => 'submit',
                                                    'id'    => 'submit',
                                                    'div'   => false,
                                                    'label' => false
                                                ]);
                                            ?>検索
                                        </label>
                                    </li>
                                </ul>
                            </div>
                            <?php echo $this->Form->end(); ?>
                        </div>
test.ctp
        <!--formの外に追加-->
        <?php echo $this->Html->link('formの値を送信した使いたいリンク', 'javascript:clickOutOfFormLink();void(0)', ['class' => 'actionBtnBase hogeListOutput']); ?>

<!--jQuery部分-->
<script>
    // スコープ外から検索ボタンを押下
    function clickOutOfFormLink() {
        // 検索機能をform外の処理に切り替えるためhiddenを設定
        $('#HogeListMode').val('hogehoge');

        document.getElementById('submit').click();

        // 検索機能に戻すためhiddenをクリア
        $('#HogeListMode').val('');
    }
</script>

結果

TestController.php
    /**
     * 一覧
     *
     * @return void
     */
    public function index(): void {
        if (Hash::get($this->request->query, 'mode') === 'hoge') {
            // modeがhogeである場合はform外のリンクが押下されている
            echo 'hoge';

            // 入力値も使用可能🐈
            var_dump($this->request->query);
        }
    }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Excelって名前しか知らないPCに不慣れな感覚派22歳プログラミング完全未経験者がRubyを習得するまでの軌跡。Part4

【HTML-CSS編】

はじめはpart2,3のように用語の説明や文型をまとめようとおもったがprogateの説明だけで完成されており、理解することが可能。最低限大事なことだけまとめる。

1.HTMLとCSSってなんなのか CSSは色、大きさ、形などデザインに関するプログラミング HTMLが素材でCSSが職人。
2.CSSはHTMLとは別にファイルを作って記述する。
3.プロパティはCSSの機能 ex.color.font-size,background-color,width,height

やってて感じたこと

HTML-CSSはRubyと比べると内容自体はすごく簡単で意味がわからないということはほぼないと想う。ただRubyが詩だとするとHTML-CSSは単文といった感じで1文1文で完結していて面白みはあまりない。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTML+CSS ドロップダウンメニュー

ドロップダウンで表示するメニューの要素に”display: none”を設定しておき、ホバー時に、displayを切り替えるだけ。

HTML

index.html
<!DOCTYPE html>
<html>

<head>
  <title>transarent nav bar</title>
  <link rel="stylesheet" type="text/css" href="css/styles.css">
</head>

<body>

  <ul>
    <li>
      <a href="#">Home</a></li>
    <li><a href="#">About</a>
      <ul>
        <li><a href="">profile</a></li>
      </ul>
    </li>
    <li><a href="#">Category</a>
      <ul>
        <li><a href="">category1</a></li>
        <li><a href="">category2</a></li>
        <li><a href="">category3</a></li>
        <li><a href="">category4</a></li>
      </ul>
    </li>
    <li><a href="#">Contents</a>
      <ul>
        <li><a href="">content1</a></li>
        <li><a href="">content2</a></li>
      </ul>
    </li>
    <li><a href="#">New</a></li>
  </ul>

</body>

</html>

CSS

styles.css
body {
 background-size: none;
 margin-left: 10%;
}

ul {
 margin: 0px;
 padding: 0px;
 list-style: none;
 font-family: arial;
}

ul li {
 float: left;
 width: 200px;
 height: 40px;
 background-color: black;
 opacity: .8;
 line-height: 40px;
 text-align: center;
 font-size: 20px;
}

ul li a {
 text-decoration: none;
 color: white;
 display: block;
}

ul li a:hover {
 background-color: green;
}

/*非表示にしておく*/
ul li ul li{
 display: none; 
}

/*ドロップダウンの要素を表示*/
ul li:hover ul li {
 display: block;
}


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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

中スクロールで右側のpaddingが入らない問題の対応

はじめに

中スクロールを実装する際に時々以下のような右側のpaddingが入らない時の対応について紹介します。

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

解決方法

結論を言うと、親要素も inline-block にしたらpaddingが入るようになりました。

原因

デフォルトのblock要素の横幅は親要素の幅一杯が限界で、ただ横を突き抜けてしまっているだけでした。
突き抜けちゃっているので、右側のpaddingの設定が効いていないように見えます。
(試しにoverflow: hiddenとかしたら途切れるのが分かると思います)
スクリーンショット 2019-12-03 11.42.33.png

inline-blockにすると親の幅関係なく子要素で作られた幅だけ伸びてくれるので、paddingもキチンと一番後ろのところで効くようになります。
スクリーンショット 2019-12-03 11.43.01.png

(ちなみこれが分からない時は擬似要素を入れて対応してました・・・)

まとめ

とりあえずinline-blockで横に並べる場合は親要素もinline-blockにしましょう!と言うことでした。
サンプルコードは以下に置きますので参考にして貰えますと幸いです。

See the Pen 横に並べる by wintyo (@wintyo) on CodePen.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自分を癒すためだけに『Pendulum waves』を作ってみた

Pendulum waves(ペンデュラムウェーブ)とは?

Pendulumとは英語で『振り子』です。
Pendulum wavesとは、その名の通り『振り子を揺らします』
※ここで言う『waves』とは『波』ではなく、一時期流行った野球やサッカーの観戦時にやるアレっぽいヤーツです

最終的な完成物

紆余曲折ありつつ最終的には下記のようなモノになりました。

See the Pen Pendulum waves by nanba (@nanba) on CodePen.

複数個の振り子にて、不思議で美しいパターンが表現できていますよね?
※70秒周期で繰り返します
ザックリ説明すると、糸の長さを順番に少しづつ変えて、周期をズラすことによって、ずっと見てても飽きない美しい癒しがソコに現れます。
1列に揺れていたかと思えば、バラバラになり、3列になったかと思えば、4列になったりと、なんとも言えず不思議で心地よい感情が溢れてきます。(やや大げさな表現)

一日中モニターとニラメッコしつつ、日々多方面からの無理難題と向き合っている我々(少なくとも私)には必要な『癒し』です。

『癒し』を手にするためには?

物理的な方法だと【購入】するか【作成】するかということになるかと思います。

購入するとなると結構な出費になります…下記サイト参照
:link: amazon.co.jp

自作するとなると…超大変そうです…下記サイト参照
:link: 自由研究でPendulum Wave【ペンデュラムウェーブ】を作りました

この時点で費用対効果など総合的に考慮し、物理的な『癒し』は諦めざるを得ないという結論に達しました。

手軽にお金をかけずに『癒し』を手に入れる方法を考えながら、イロイロとググっていた時に、ふと
どうせ一日中眺めているモニターに表示させておけばイイんじゃね?ってことに気付く
「一番手軽で簡単に出来るhtml+cssでサクっと作ろう!」
※動画サイトやら、wikiなどに頼らずに、自作しちゃおうっていうコーダー魂のカケラぐらいは残っていた

当初の構築予定

  • 振り子っぽく見せるために支える『糸・紐』は必須!
  • htmlは複雑にしない!(疑似要素もあるしタグ要素は ol>li のみでイイよね…時間ないし)
  • cssは複雑にしない!(球体と紐を繋いで、紐の端っこ支点で rotate させればOKだよね…時間ないし)

※結局、上記のみの実装では当然のように『癒し』にはなりませんでした

具体的Pugったhtml

ol
  - for (var x = 0; x < 20; x++)
    li
      span

これっぽっちです。
ここはまぁ説明するまでもないリスト構造でしかありえあないでしょうね。

最終的に書いたscss全文

ただ普通に20個の振り子を少しづつズラして動かすだけなら、こんなにガチャガチャと書く必要はないのですが…
作っていくうちに「もう少しリアルに…」「もう少し滑らかに…」などと、欲張っていくうちに長くなりました。

ol{
  li{
    list-style:none;
    width:40px;
    position:absolute;
    left:calc(50% - 20px);
    transform-origin:top;
    span{
      display:flex;
      align-items:center;
      justify-content:center;
      position:relative;
      overflow:hidden;
      border-radius:50%;
      box-shadow:2px 2px 10px rgba(255,255,255,.6);
      &::before{
        content:"";
        display:block;
        width:10px;
        height:10px;
        position:absolute;
        top:10px;
        left:10px;
        background:#fff;
        border-radius:50%;
        z-index:2;
        filter:blur(3px);
      }
      &::after{
        content:"";
        display:block;
        width:45px;
        height:45px;
        position:absolute;
        background:transparent;
        border-radius:50%;
        z-index:1;
        filter:blur(5px);
        box-shadow:inset -5px -5px 0 2px #333;
      }
    }
    &::before{
      content:"";
      width:2px;
      position:absolute;
      top:0;
      left:calc(50% - 1px);
    }
  }
}
$deg: 20;
@for $i from 0 to $deg{
  ol li:nth-child(#{$i + 1}) {
    height: calc(650px - #{$i * 25}px);
    padding-top: calc(610px - #{$i * 25}px);
    animation:pendulum #{70 / (52 - $i)}s infinite;
    &::before{
      height:calc(610px - #{$i * 25}px);
      background:rgba(($i + 8) * 8,($i + 8) * 8,($i + 8) * 8,1);
    }
    span{
      margin-left:calc(0px - #{$i / 2}px);
      width:calc(40px + #{$i}px);
      height:calc(40px + #{$i}px);
      background:rgba(($i + 8) * 8,($i + 8) * 8,($i + 8) * 8,1);
    }
  }
}
@keyframes pendulum{
  0%{transform:rotate(-25deg);animation-timing-function:cubic-bezier(.45,0,.55,1);}
  50%{transform:rotate(25deg);animation-timing-function:cubic-bezier(.45,0,.55,1);}
  100%{transform:rotate(-25deg);animation-timing-function:cubic-bezier(.45,0,.55,1);}

当初の構築予定から大幅に路線変更したcss記述の詳細解説的なアレ

下記に欲張った項目ごとに解説をザックリと

振り子(球体)をソレっぽくする

  • 重なり合った時に少しだけ影というか、ぼかした感じにしたかったので球体に box-shadow を設定
  • 球体に光沢と影を出したかったため球体疑似要素に fliter(blurを使用) を設定

遠近法を少しだけ意識する

  • 奥にある球体が小さく見えるよう幅・高さに calc(40px + #{$i}px) を設定
  • メリハリをつけるため奥にある球体・紐の色自体を濃くするように background:rgba(($i + 8) * 8,($i + 8) * 8,($i + 8) * 8,1); を設定

力学的エネルギー保存の法則を少しだけ意識する

  • 両端に行くほど遅く、中央に近づくほど速く動くように animation-timing-function を設定

制作時間

  • 構想:5分
  • 初期構築:5分
  • 最終調整:1時間(もはや調整の域を超えて時間かけましたね…)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

情報基礎2 第3回

ex03-1.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>今日の天気</title>
  </head>
  <body>
    <input type="button" value="ボタン" onclick="tenki()">
    <script type="text/javascript">
    function tenki(){
      var name = prompt("今日の天気は?");

      if (name=="晴れ"){
        alert("素敵な1日を");
      }else {
        alert("今日も頑張りましょう");
      }
    }
    </script>
  </body>
</html>
ex03-2.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>占い</title>
  </head>
  <body>
    <input type="button" value="ボタン" onclick="uranai()">
    <script type="text/javascript">
      function uranai() {
        var num = Math.random();

        if (num < 0.1) {
          alert("");
        } else if (0.1 <= num < 0.33) {
          alert("小吉");
        } else if (0.33 <= num < 0.66) {
          alert("中吉");
        } else if (0.66 < num) {
          alert("大吉");
        }
      }
    </script>
  </body>
</html>
ex03-3.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>夕食</title>
  </head>
  <body>
    <input type="button" value="if-elseボタン" onclick="dinner()">
    <input type="button" value="switch-caseボタン" onclick="dinner2()">
    <script type="text/javascript">
      function dinner(){
      var name = prompt("今日の夕飯の気分を 洋食/和食/中華/その他 で答えてください");

        if (name=="洋食"){
        alert("サイゼリヤがお勧め");
      }else if (name=="和食"){
        alert("大戸屋がお勧め");
      }else if (name=="中華"){
        alert("餃子の王将がお勧め");
        }else {
        alert("マックがお勧め");
        }
      }

      function dinner2(){
      var word = prompt("洋食/和食/中華/その他のいずれかを入力してください。");
      switch (word) {
        case "洋食":
        alert("サイゼリヤがお勧め");
        break;

        case "和食":
        alert("大戸屋がお勧め");
        break;

        case "中華":
        alert("餃子の王将がお勧め");
        break;

        case "その他":
        alert("マックがお勧め");
        break;

        default:
        alert("理解できません。");
      }
    }
    </script>
  </body>
</html>
ex03-4.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>夕食</title>
  </head>
  <body>
    <input type="button" value="ボタン" onclick="day()">
    <script type="text/javascript">
      function day(){
      var name = prompt("曜日は?");

        if (name=="月曜"){
          var jigen =prompt("時限は?")
          if (jigen=="4"){
            alert("情報基礎2");
          }else if (jigen=="5"){
            alert("情報基礎2");
          }else{
            alert("何も履修していません");
          }
        }

        if (name=="火曜"){
          var jigen =prompt("時限は?")
          if (jigen=="2"){
            alert("地域と社会");
          }else if (jigen=="3"){
            alert("政策立案論");
          }else if (jigen=="4"){
            alert("21世紀の企業の挑戦");
          }else if (jigen=="5"){
            alert("ライティング技法ワークショップ");
          }else{
            alert("何も履修していません");
          }
        }

        if (name=="水曜"){
          var jigen =prompt("時限は?")
          if (jigen=="1"){
            alert("何も履修していません");
          }else if (jigen=="2"){
            alert("何も履修していません");
          }else if (jigen=="3"){
            alert("何も履修していません");
          }else if (jigen=="4"){
            alert("何も履修していません");
          }else{
            alert("何も履修していません");
          }
        }

        if (name=="木曜"){
          var jigen =prompt("時限は?")
          if (jigen=="2"){
            alert("データ・ドリブン");
          }else if (jigen=="3"){
            alert("統計基礎");
          }else{
            alert("何も履修していません");
          }
        }

        if (name=="金曜"){
          var jigen =prompt("時限は?")
          if (jigen=="1"){
            alert("英語");
          }else if (jigen=="2"){
            alert("体育");
          }else if (jigen=="3"){
            alert("英語");
          }else{
            alert("何も履修していません");
          }
        }
      }
    </script>
  </body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

画像に文字を乗せる

画像に文字を乗せるには、画像のクラスのpositionを”relative”にする。
文字のクラスのpositionを"absolute"にし、位置を指定する。

.visual {
position: relative;
}

.visual p {
position: absolute;
width: 50%;
transform: translate(-50%,-50%); /縦と横の文字のズレを修正
top: 45%; /
画像のtopからの位置
left: 50%; /画像の左からの位置(右からにするには-50%とする)
/
文字の装飾を指定する*/
}

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

htmlでファイルを指定する

一つ上の階層を指定するには ”../” を使う。

・1つ上の階層にある画像ファイルを指定
“../画像名.png”

※上に上がる毎に ../../

・一つ上の階層の別フォルダの中にあるファイルを指定

”../フォルダ名/画像名.png”

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】license-tools-pluginで出力したlicenses.htmlで、URLが長いと改行位置がずれてしまう

はじめに

アプリでライセンス表示を埋め込む際、色々な方法があるかと思います。
今回クックパッドさんが開発されたlicense-tools-pluginを使わせていただくこととなり、
実際に表示まで行なった際に表題の問題が発生してしまいました。
その原因と対応方法を自分用のメモとして残しておきたいと思います。

license-tools-pluginの詳細な使い方については、
他の方がわかりやすくまとめられている為、本記事では割愛させていただきます。
あの素晴らしいlicense-tools-pluginをもう一度

どういう現象か

以下のように、横幅(width)より、リンクの文字列が長くなってしまった場合、
少しはみ出た状態での改行になってしまいます。
ずれ.png

原因と対応方法

出力したlicenses.htmlを確認してみると、はみ出ていた部分は以下のようになっていました。

<p><a href="https://developer.android.com/topic/libraries/architecture/index.html">https://developer.android.com/topic/libraries/architecture/index.html</a></p>

HTMLをあまり詳しく知らなかったため、調査したところ、CSSの設定が足りていないことが原因であることが判明。
URLが自動改行してくれない問題

<style></style>の中に、<a>タグ用の設定として以下を追記することで、ずれなくすることができました。

<style>
  a {
  word-break: break-all;
  }
</style>

補足

尚、出力するたびに上記の設定を追記する必要があるため、面倒であるのと対応するの忘れそう…
流石に他にlicense-tools-pluginを使っている方も同じ現象に陥っているのでは…?と思い、
公式のGitHabリポジトリを確認すると、なんと以下のプルリクエストを発見。
https://github.com/cookpad/license-tools-plugin/pull/124

出力時に以下の設定を追加するようにされており、
手動で試してみたところ、こちらでもずれが発生しないことを確認できました。

  a {
  overflow-wrap: break-word;
  }

ですので、クックパッドさんがlicense-tools-pluginを次回アップデートされる際には修正されたものが上がってくるかと思います。

修正版が上がるまでは面倒ですが、以下のどちらかを手動で追記して対応するようにしましょう。
word-break: break-all;
overflow-wrap: break-word;

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ログイン中ユーザーの投稿内容をshowアクション以外で出力する方法

SNSっぽいアプリケーションのマイページで、ログイン中ユーザの投稿一覧を取得したかっただけなのにかなり詰まったので備忘録として残しておきます。

アプリの仕様上showアクションやshow.html.erbファイルを使用できず、index.html.erbで表示させるというレア?パターンではありますが。

環境

Rails 5.2.3
Ruby 2.5.1
gemのdeviseを使用
当記事で使用しているモデル名はplace

詰まった所

homes/index.html.erbファイル内にてeach doを利用し投稿内容を全部出力したい。

homes/index.html.erb
<% @myplaces.each do |myplace| %>
  #省略
<% end %>

全部のplaceを取得するのはhomesコントローラー内のindexアクションで

./controllers/homes_controller
@places = Place.all

こう書けばいい。そりゃそうだ。
問題はログイン中ユーザの投稿内容だけを取得したい時。

./controllers/homes_controller
@myplaces = Place.find(current_user.id)

と入力するとundefined method 'each' for nil:NilClassでエラーが発生する。これは@myplacesが空だからeachする元ネタがありませんよっていう怒られ方。できそうな気もするのに。

試しにターミナルでfind(1)として出力してみる。

ターミナル
pry(main)> Place.find(1)
   (0.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  Place Load (0.3ms)  SELECT  `places`.* FROM `places` WHERE `places`.`id` = 1 LIMIT 1
=> #<Place:0x00007f831ad85618
 id: 1,
 name: #以下省略

問題ない。
idが1であるcurrent_user.idを適当な変数に代入して出力してみる

./controllers/homes_controller
@user = current_user.id
homes/index.html.erb
<%= @user %>
#=> 1

こっちも問題がない。
なんで出力されないのか不思議で仕方がなかったんですが、驚いた事にこんな書き方だけで解決しました。

./controllers/homes_controller
@places = Place.all
places = @places
@myplaces = current_user.places
homes/index.html.erb
<% @myplaces.each do |myplace| %>
  #省略
<% end %>

目ン玉飛び出そうになりました。こんな簡単な記述でよかったんかと。。。普通にidを指定すれば出来るやろって余裕こいてたら痛い目見ました。

原因は今度時間を見つけて探してみます。今度作る時にはハマらないように…

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

最近勉強して知ったこと、まとめてみた2

はじめに

Qiitaアドベントカレンダー3日目です。
今日も最近学んだことについて自分なりにまとめていきたいと思います。

BDD(ビヘイビア駆動開発)

TDD(テスト駆動開発)から発展したもの。
TDDと同様、テストコードを書くが、「要求される仕様」に近い形でテストコードを記述する。仕様(スペック)とテストがかなり近いものとなるので、BDDでは、「スペックファースト」となる。私は、Rubyを使ったプロジェクトの開発で、Rspecを使いました。

REST

リソースを扱うための考え方である。
リソースはそれぞれ固有のURIを持っていて、そのURIにアクセスすることで、それぞれのリソースを操作することとなる。操作はHTTPのメソッドを正しく使うことで行う。

メソッド 役割
GET リソースの取得
POST リソースの新規作成
PUT 既存のリソースのアップデート
DELETE リソースの削除

form_with,form_for,form_tagの違い

form_tagは以前まで、modelがない場合に使用されていたもので、逆にform_forはmodelがある場合に使用されていました。ですがRails5.1以降では、modelの有無に関係なく、2つを統合したようなform_withができたので、今はform_withを使うことが推奨されている。(url,modelの指定など可能)

HTMLフォーム

ユーザとWebサイトやアプリケーションの対話の要となるもの。
フォームによって、ユーザはWebサイトへデータを送ることができる。
だいたい、1つ以上のウィジェットとで作られ、テキストフィールド、エリア、セレクトボックス、ボタン、チェックボックス、ラジオボタンなどがある。
ウィジェットには、用途を説明するためのラベルがついていることが多い。
フォームで集めたデータは、だいたいWebサーバに送られる。

最後に

Ruby on Railsなどで開発をしていると学ぶことが多くて大変です。:sweat_smile: 初めてのことが多くて躓くことが多いですが、その度に、トライアンドエラーで乗り越えることが大切だなって最近思います。まだ、説明が曖昧なのでもっと勉強して、知識の幅を広げていきたいと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新卒がHTML5プロフェッショナル認定試験レベル1に合格した方法

Advent Calenderも技術投稿もはじめまして!

ALH Advent Calender4日目です。
技術的な投稿もAdvent Calenderもはじめてですが、ぜひ、温かいまなざしで見ていただけたら幸いです…!

丸腰の新卒、Web系試験に合格できました

2019年11月2日に、HTML5プロフェッショナル認定試験レベル1に無事(ぎりぎり)、合格することができました。
この機会に、知識0の状態から始まった試験対策や実際のテストについてまとめてみようと思います。

HTML5プロフェッショナル認定試験とは?

テスト概要

所要時間:90分
問題数:60問
受験料:15,000円(税別)
日時・会場:全国各地のテストセンターから自由に選択できる
試験方式:コンピュータベーストテスト(CBT)
キーボード入力問題がいくつか出題される。
認定の有効期限:5年間
HTML5プロフェッショナル認定試験公式サイト

HTML5,CSS3,JavaScriptなど最新のマークアップに関する技術力と知識を認定する認定資格で、デザイン・Web・開発に関わる幅広い職種が対象となっています。
レベルは1と2があり、私はレベル1を受験しました。

受験動機

  • 初心者でも受験しやすい
  • コーディングベースのWeb基礎知識を身につけたかった

Webデザイン系の試験はいくつかありますが、日常の業務でコーディングを中心に行っているので、すぐに現場で生かせることが資格取得のきっかけになりました。

試験対策

  • 参考書を読む
  • LPI主催の試験対策セミナーに参加★
  • Ping-tのオンライン問題集をひたすら解く★
  • 社内のWeb系ワークショップに参加★

以上の4点を中心に、7月末から11月の試験まで、約3か月ほど勉強しました。
勉強は、平日は通勤時間に、休日は自宅で1,2時間ほど行いました。
★が付いたものは特に役立った勉強法なので、時間がない方はそちらから読んでいただけたら幸いです。

参考書を読む(7月末~8月末)

  • すぐにとりかかりやすい勉強法
  • 毎日取り組む分量を決めやすい
  • まず情報をインプットしたい初期には最適

最初のうちは、参考書を読んで、練習問題を解く、ということを繰り返しました。
私が使っていたのは、マイナビ出版のHTML5プロフェッショナル認定試験 レベル1 対策テキスト&問題集 Ver2.0対応版です。
HTML、CSS、レスポンシブWebデザイン、API概要、Web関連の規格と技術の5つのチャプターに分かれています。

勉強法としては
平日:隙間時間で5ページ前後読み進めていく。
休日:章末の問題を解き、間違った問題をノートにとる。
といった感じです。
個人的にアウトプットにはあまり向かなかったので、最初の導入とわからない時に調べるための辞書的な役割として私は重宝しました。

LPI主催の試験対策セミナーに参加★(8/25)

  • 参加費無料
  • APIやレスポンシブWebデザインなど独学では勉強しにくい部分を講義でカバーしてくれる
  • 参加特典として試験の割引と学習サイトの有料コンテンツを1か月無料で使える

HTML5プロフェッショナル認定試験公式サイトから事前に参加予約が必要ですが無料で参加することができます。

3時間ほどの実施で、私が参加した8月の回はAPIについての集中的な講義でした。APIなどの概念については、少し事前知識があるとその後の勉強がかなりしやすくなりました。
各回の内容を見たところ、APIやWebレスポンシブデザインに関する講義が多い印象です。

また、参加特典として、認定試験を10%割引きで受験できる割引クーポンと、オンラインで試験勉強が出来る学習サイトPing-tの有料コンテンツを無料で30日間使える権利を獲得できます。
私はこのPing-tでほとんど試験勉強をカバーできたので、とてもおすすめです。

Ping-tのオンライン問題集をひたすら解く★(8月末~10月末)

Ping-tとは
  • Ping-tは、問題を解いたり、模擬試験を受けることができる学習サイト
  • 学習ログが残るので得点率の遷移をみることができる
  • HTML5の他にもCCNA ICND1、LinuC、Oracle Master Bronze SQL基礎、ITILファンデーション、ITパスポートなどユーザー登録をすれば無料で利用できるコンテンツもある

Ping-t公式サイト

勉強法としては
問題を一通り解いていく。
エディターなどを使ってコードを書いて動きを確認する。
解ける問題が増えてきたら模擬試験を行う。
よく間違える問題は簡単にまとめておいて隙間時間に見返す。
試験前までに全問題を2回以上正答の状態、模擬試験の正答率を90%以上にしておく。

HTMLやCSSの分野に関しては、似たような要素やプロパティなどを使った問題は実際にソースを書いて動かしてみることが記憶にも残りやすくて効果的でした。

レスポンシブWebデザインやAPI概要など、用語を覚える時にはネットで分かりやすく言い換えているサイトを探したり、間違いやすい用語は内容を書き起こして隙間時間に見るという受験生っぽい勉強をしました。

模擬試験は実際の試験同様、60問で90分間時間を自動的に計ってくれますが、解答を確認する時間を含めても実施時間は1時間ほどでした。

最初は全ての問題が銅のステータスですが、正答率を上げていくごとに銀、金とレベルが上がっていくので、得意、苦手なカテゴリーが分かりやすいのと、何よりモチベーションが上がります。頑張るとランキングに入れたりするのも嬉しいところです。

全問題を金の状態にするとくす玉みたいでうれしい。
1.png
学習ログが残るので、自分の得点率の遷移がわかりやすい。
2.png

社内のWeb系ワークショップに参加★(10/21)

  • 実際にWeb制作をしてみて根本が理解できた。
  • 暗記だけではつまずいていた部分が解消された。
  • Webデザインってわくわくする!ということに気が付いた。

ざっと暗記はしたけれど、模擬試験の正答率に伸び悩んでいた停滞期があり、ちょうどそのタイミングで社内イベントのWeb系ワークショップに参加しました。

HTMLとCSSを使って実際にWeb制作をしてみたことで、暗記していただけではよくわからなかった部分が体感的にわかるようになりました。

勉強して煮詰まってきていた時だったので、Webサイトを作ってみるのって楽しいということも実感できた大事な一日でした。
そういった機会を作ってくださって大感謝です…!

実際の試験

  • 獲得点数70点(最低点)
  • 回答時間は充分
  • キーボード入力問題が2問ほど
  • 自信のある問題が50%、少し自信がない問題20%、かなり自信がない問題20%、わからない問題10%

問題は45分ほどで解き終わり、2.3回はゆっくり見直せる時間がありました。

問題の内2問ほどキーボード入力式の問題がありましたが、基礎的な単語と、数字を入力するものだったので、そんなに難しさはなかったです。

聞き方は違うものの、Ping-tで解いたレベル感の問題が多かった印象でした。解答に書いてある細かな補足情報までインプットできていればもう少し自信を持って解答できたかなと思います。完全に見たことない問題は全体の10%ほどありました。

私は本当にギリギリの合格だったのでもっと確実に得点を取得するためには、Ping-tの問題の解答部分の補足もよく読み込む必要があるかと思います。私が正答率を7、8割超えてきたタイミングが試験の一週間前くらいだったので、もう少し早い段階で合格県内に入っておくと安心だと思います。

ただ、問題集の章末問題や、公式サンプルの問題は実際の試験より難しかった印象なので、Ping-tをやっている場合は、他のテキストで勉強するよりはPing-tを極めていくのが効率が良さそうだと感じました。

受験してよかったこと

  • ソースコードに苦手意識を感じなくなった
  • ウェブサイトを作るイメージが沸くようになった

ソースコードの読み書きに前ほど苦手意識がなくなって、Webサイトを自作してみるなどできることが広がりました。

今は話題のGASを使ったWebサイトをCSSのフレームワークのBootstrapを導入して見よう見まねで作成しています。こちらの記事を参考に私も好きなエディタでやってみようかな、、!

もちろんわからないことはたくさんありますが、調べて分かることが少し増えたのは成長かなと思います。

全体的にPing-tの回し者かのような書きっぷりになってしまいましたが、全くそんなことはありませんので、ご安心ください。
ただ、本当に使いやすくておすすめなので、もしも気になる方がいたら是非試してみてください。

文章が多くなってしまいましたが、最後まで読んでくださり、ありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む