昔、自作のCSSで作ったサイトをBulmaに切り替える(簡単なBulmaの使い方)

初めに

昔、若気の至りで作成したCSS/HTMLで作成したサイトをBULMAに切り替えてみた備忘録

結論

やっぱり、デザインに関しては中途半端にチャレンジするのであればあるものを実装したほうが良いと思いました。
切り替え自体も1時間程度で終了しましたし、スッキリしました。

変更前

スクリーンショット 2019-10-06 0.55.59.png

変更後

スクリーンショット 2019-10-06 0.57.18.png

手順

旧式のHTMLサイトとCSSを用意しました。
今回のサイトはCSSが該当HTML内に入っていたため1ファイルでしたが…

1,既存のCSSを全削除

不用意に残っていると悪さをしそうなのですべて削除しました。

2,Bulmaを読み込ませる

ヘッダー部に下記の1行を入れます。

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css">  

3,ベースをどのように書くか調べる

とりあえず、全体構成が最初であるため BulmaLayoutを参照します。
この中の、Containerを参照し body要素直下に埋め込みます。
こんな感じですね。

  <body>  
    <div class="container">  
      <div class="notification">  
      </div>  
    </div>  
  </body>  

4,タイトルをどうするか考える

タイトルに関してはheroというのがあったのでこれを利用しました。
こんな感じに記載すれば綺麗になりました。

<section class="hero is-info">  
    <div class="hero-body">  
    <div class="container">  
        <h1 class="title">  
        hasito.com  
        </h1>  
        <h2 class="subtitle">  
        しがないサラリーマンプログラマ  
        </h2>  
    </div>  
    </div>  
</section>  

5,全体構成を考える

次に、現状の構成から大きく変えない方法で少しみてみたところ…
tilesがそれっぽいのでこれをそのまま流用しました.

こんな感じの構成です。
スクリーンショット 2019-10-06 1.13.14.png

該当の要素に各コンテンツを埋め込んでいくだけですね。
完成は下記になります。

https://hasito.com

悩んだ所

そこまでなかったので備忘録的に書いておきます。

Herotilesの間にmarginが生まれない

正規な解決方法があるのでしょうけど、すぐに探せなかったため改行で逃げています…

tilesが最も長い要素に依存する。

例えば横軸で長い要素が1個あると、他の要素も長く取ろうとして不格好になります。
私サイトはTwitterが長さ指定無しだったため6000px程度になりかなり見にくくなってしまいました。
Twitterの埋め込みはdata-height="x"で高さを指定できるため、これで解決しました。

riot.jsで作る雑ブログシステム

はじめに

概要

雑なブログシステムを作ろうと思ったので作りました。
なにせ雑なので、下記のような制限付き。

  • DBは利用しない。
  • Server側の処理はなるべくなし

完成品は下記
hasito.com

仕様

機能

  • Markdownをサポート
  • タイトルと編集時期を設定可能

システム概要

  • Markdown処理のパッケージを利用
  • 表示はめんどくさいのでbootstrap
  • ファイルは下記の2つを記事として参照
    • {index}.md 記事の内容
    • {index}.json 更新日とタイトル
  • 参照は記事ファイルのindexを信じて0からループ…404なったら終わり

ファイル構成

-/  
  +blog.tag  
  +index.html  
  -component/markdown-it/dist/markdown-it.min.js  
  -article  
    +0.json  
    +0.md  
    +1.json  
    +1.md  
    +...  

コード

blog.tab

<blog>  
  <div class="list-group">  
    <button each={v,i in articles} onclick={viewart.bind(this,i)} type="button" class="list-group-item">{v.cnf.name}</button>  
  </div>  
  <script>  
    var self=this;  
    self.articles=[];  
    var md = window.markdownit({html:true,breaks:true});  
    viewart(i){  
       $(".view").html(md.render(self.articles[i].md));  
    }  
    self.on("mount",(e)=>{  
      console.log("mount");  
      self.articles=[];  
      var idx=0  
      var cb=(v)=>{  
        if(v){  
          var art={md:v};      
          get_article_cnf(idx,(vv)=>{  
            art.cnf=vv;  
            self.articles.push(art);  
            get_article(++idx,cb)  
          })  
        }else{  
          self.update();  
        }  
      }  
      get_article(idx,cb);  
    });  
  
    var get_article=(i,cb)=>{  
      fetch(`article/${i}.md`)  
        .then(res => {  
          if (!res.ok) {throw Error(false);}  
          return res.text();  
        }).then(body => {  
          cb(body);  
        }).catch(err=>{  
          cb(false);  
        });  
    }  
    var get_article_cnf=(i,cb)=>{  
      fetch(`article/${i}.json`)  
        .then(res => {  
          if (!res.ok) {throw Error(false);}  
          return res.json();  
        }).then(body => {  
          cb(body);  
        }).catch(err=>{  
          cb(false);  
        });  
    }  
  </script>  
</blog>  

index.html

<html>  
  <head>  
    <title>Hello Riot.</title>  
    <meta charset="UTF-8"/>  
  
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->  
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>  
    <!-- Latest compiled and minified CSS -->  
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">  
    <!-- Optional theme -->  
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">  
    <!-- Latest compiled and minified JavaScript -->  
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>  
  </head>  
  <body>  
      <div class="container-fluid">  
        <div class="row">  
            <div class="col-xs-12"><h2>hasito.com</h2></div>  
        </div>  
        <div class="row">  
          <div class="col-xs-2">  
              <blog></blog>  
          </div>  
          <div class="col-xs-10 view">  
          </div>  
        </div>  
    <script type="riot/tag" src="blog.tag"></script>  
   <script src="https://cdn.jsdelivr.net/npm/riot@3.9/riot+compiler.min.js"></script>  
   <script src="component/markdown-it/dist/markdown-it.js"></script>  
   <!-- <script src="riot/riot+compiler.min.js"></script> -->  
    <script>riot.mount('blog')</script>  
  </body>  
</html>  

1.json

  
{  
    "name":"テスト2",  
    "date time":"2018/04/02 02:46"  
}  
  

1.md

  
# テスト記事2  
## sub  
### sub sub  
こんにちわ、これはテスト記事です。  
  
aa**aaaa**aa  
xx__xxxx__xx  
  

Aliexpressで購入したLCDをArduino互換機で動かす

最初に

最近、Aliexpressで部品を購入して遊ぶことが多くメモ。

購入したもの

lec

購入店舗
https://ja.aliexpress.com/item/32786773241.html?spm=a2g0s.9042311.0.0.27424c4dfs7NFj
これの1.98$のやつ
image.png
image.png

uno互換機

Amazonで2個で1000円くらいのuno互換機

image.png

配線図

image.png

プログラム

モジュールをこちらからダウンロードしインストール
https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads/

こちらのサイトの参考コードをコピーさせていただき。
Tutorial – PCF8574 backpacks for LCD modules and Arduino

無事に動きました。
image.png

詰まったところ

複数のモジュールがある

Ardiunoはインクルードに同一のヘッダファイルがある場合警告が出ます。
その場合インクルードファイルが有る場所の重複しているフォルダを削除しましょう。

私はMACなので~/Documents/Arduino/libraries/配下にありました

image.png

点滅するだけで文字が出ない

裏面の可変抵抗ををマイナスドライバーで回しましょう。
これはコントラストを操作しているらしく、これが合っていないと表示が出ないことがあります。
(これでめちゃくちゃ時間食ったのでここに備忘録とします。)
image.png

こちらのサイト参考にさせていただきました

Tutorial – PCF8574 backpacks for LCD modules and Arduino

DynamodbをLambdaからSQLっぽく操作する

説明の前に

pipのモジュールを利用する方法は、下記の記事を参考にさせていただきました。
ありがとうございました。

【Python】AWS Lambdaで外部モジュールを使用する
https://qiita.com/SHASE03/items/16fd31d3698f207b42c9

1.準備

LambdaにPipのモジュールを持ってくる必要があるため、ローカルにDQLモジュールをインストールする。

プロジェクトフォルダ内で、下記

$pip install dql -t ./  

2. ソースコード

ファイル名はlambda_function.py

import dql  
def lambda_handler(event, context):   
    engine = dql.Engine()  
    engine.connect(region="us-west-2")  
    results = engine.execute("DELETE FROM tablename WHERE tm >= 1420071600 AND tm <= 1420705200;")  
    print(results)  
    return "hi world"  

regiontablename、クエリなどは任意の設定に修正してください。

3. zip化してアップロード

zip -r dpl.zip ./*  

完成したZIPをLambdaにアップロードすれば完成です。

「今あなた以外に○○名がこのサイトを見ています!」をGoogle Analyticsで簡単実装!

はじめに

少し前に話題になったこの記事。
旅行予約サイトの「今あなた以外に○○人が見ています」はウソだったことが判明 - GIGAZINE

「これってGoogle AnalyticsのRealtimeの情報をAPIで取得すれば結構簡単に実装できるんじゃないかな…」と思い立ち、実装してみましたという話。

システム全体

イメージ的には下記の様な形で実装しました。

更新

①GAS(Google Apps Script)でGoogleAnalyticsのRealtime情報を取得(1分単位)
②取得した情報をスプレッドシートに書き込み

image.png

取得

①他のアプリからHTTPによるGET要求
②要求に対しスプレッドシート内最新値を検索
③最新値を返信
※GASにてHTTPサーバを構築しています。

image.png

構築

1.準備:Analytics側(アカウント権限追加)

Analytics側に利用するアカウントにデータを参照する権限を付与する必要があります
下記の手順で行うことが出来ます。

①管理をクリック

image.png

②ユーザ管理

image.png

③ユーザ追加

image.png

④ユーザ追加2

image.png メールアドレスにGoogle Apps Scriptを使うGoogleユーザを入力し、新規ユーザにメールで通知するのチェックを外し、「追加」ボタンをクリックしてください。

2.準備:Analytics側(ビューID追加)

下記の方法でビューIDを取得しておきます

①管理をクリック

image.png

②ビューの設定

image.png

この画面の「ビューID」をコピーしておく
image.png

3.準備:GAS側(Google AnalyticsAPI許可)

次は、GAS側で設定をしてきます。
Google Analytics APIを許可します。

①スプレッドシート

「ツール」>「スクリプトエディタ」を選択
image.png

②スクリプトエディタ

「リソース」>「Googleの拡張サービス」を選択
image.png

③Googleの拡張サービス

「Google Analytics API」をオンにして「OK」を選択
image.png

4.コーディング

下記のコードをコピーし貼り付けます。
**[VIEW_ID]**の部分にコピーしておいた「ビューID」を貼り付けます。

function getRalTimeUser() {  
  var ret = Analytics.Data.Realtime.get('ga:[VIEW_ID]', 'rt:activeUsers')  
  return ret.totalsForAllResults["rt:activeUsers"]  
}  
  
function main() {  
  var raltimeuser = getRalTimeUser();  
  var sheet = SpreadsheetApp.getActiveSheet();  
  sheet.appendRow([raltimeuser, new Date()]);  
}  
  
function getSeetRalTimeUser(){  
  var sht = SpreadsheetApp.getActiveSheet();  
  var _row = sht.getLastRow();  
    
  var _count = sht.getRange(_row,1).getValue();  
  var _time  = sht.getRange(_row,2).getValue();  
  return [_count,_time]  
}  
  
function doGet(e) {  
  var out = ContentService.createTextOutput();  
  out.setMimeType(ContentService.MimeType.JSON);  
  out.setContent(JSON.stringify(getSeetRalTimeUser()));  
  return out;  
}  

5.準備:GAS側(タイマー設定)

コーディングで作成した関数を定期実行するように設定します。
これにより、スプレッドシートに最新の人数が1分置きに更新されるようになります。

① スクリプトエディタ

タイマーアイコンをクリック
image.png

②トリガー設定画面

下記の手順でトリガーを設定

image.png

画面通りに設定して「保存」をクリック
image.png

保存が完了すると、実行するユーザ認証が始まります。
自己責任にて許可を行ってください。

③Googleアカウント 認証確認

このアプリケーション実行するアカウントを選択
image.png
「このアプリケーションは確認されていません」と表示されますが「詳細」をクリック
image.png
下側の「アプリ名(安全ではないページ)に移動」をクリック

image.png

「許可」をクリック
image.png

準備(GAS側:WEBサーバ設定)

①スクリプトエディタ

「公開」>「ウェブアプリケーションとして導入…」をクリック
image.png

②ウェブアプリケーション設定

「バージョン」に数値を入力
「Who has access to app」を全ユーザーに変更し、「Deploy」をクリック
image.png

③URL生成

URLが生成されます。
コレをコピーしておいてください。
image.png

テスト

コピーしたURLにブラウザでアクセスすると、1分単位ですがページを見ているアクティブユーザの数が表示されます。

image.png

注意

[注意]流用などは自由ですが、自己責任にてお願いいたします。
(私自身軽く動きを確認したのみなので…)

http要求を行い、ステータスコードが200の場合のみ内容を保存する

#背景
curlにて機能を作っていたが、「要求が失敗した場合も-o(output option)に保存されてしまう」問題が有りシェルスクリプト化しました。

#コード

#!/bin/bash  
# ./curl+.sh {url} {output}  
URL=$1  
OUTPUT=$2  
TMPOUTPUT=/tmp/$(date +%Y%m%d_%H%M%S_%3N)  
   
status=`curl -o $TMPOUTPUT -li $URL -w '%{http_code}' -s`  
if test $status -eq 200 ; then  
cp $TMPOUTPUT $OUTPUT  
echo 1  
else  
echo 0  
fi  

カメラで顔検出して位置に応じてCSSで影をつける

はじめに

tensorflowを勉強したいなと思っていて色々と調べていて簡単なデモがあったので作ってみました。
※深いところまでは全然触っていないのであしからず…

結果

こんなふうになりました。
カメラを起動していただければ顔を検知して、影が移動します。

名称未設定.mov.gif

ソースコード

埋め込みだと動きませんのであしからず…
Codepenに移動していただければ動きます。

See the Pen face detection shadow by hashito (@hashito) on CodePen.

内容

初期化部分

// load...  
const net = await posenet.load();  
// 人の検出  
const pose = await net.estimateSinglePose(video, imageScaleFactor, flipHorizontal, outputStride);  
// video:入力元  
// imageScaleFactor:イメージの縮小率  
// flipHorizontal:映像を反転させるか?  
// outputStride:出力ストライド数、高いほど制度が上がる(32,16,8のみ許容)  

簡単ですね…
※複数人検出する場合は別の関数になります。

取得されるデータ

こちらの学習済みデータは人のボーンを推定するものですので、各特徴部位がスコアと共に帰ってくる形です。
取得されたデータがこちらになります。

スクリーンショット 2019-06-02 2.10.27.png こちらも分かりやすい… ※スコアが低い部位はカメラに入っていないため推定できていないものと思われます。

顔の基準

データは色々ともらえるのですが今回は顔の中心であるnoseだけを利用します。
noseの位置を取得し、画面上の中心点との差分を係数で変換し、CSSを変更するだけ!

30分で瞬発的にコーディングする。(メモ)

#背景
朝にカフェで勉強などしているんですが、気分が乗らなかったので30分という時間制限でコーディングをしました。
そこでの気付きをここにまとめておきます。

目標

これをCSSに実装
元Tweet
https://twitter.com/InfinityLoopGIF/status/1221289968099823616?s=20
あああああ.mov.gif

結果

こちらになります。
色々未完成…
名称未設定.mov.gif

Codepen

See the Pen half circle Animation by hashito (@hashito) on CodePen.

気づき

考える時間を最小に、実装で試す

そのままですが、考え続けるとどうしても時間がかかってしまいます。
なので、出来る限り最短でトライアンドエラーを試すのが良いと思います。
1.結果を想像する
2.そのために何がたりないかを考える
3.どうすればそうなるかを考える←これが結構かかりますね…
4.可能性が高い方を試す
これの繰り返しかな。

スマートな実装は捨てる、まず動かす

単純に私の中の悪魔が「これは、こうすれば…行数が減るな…」とか考えるんですが、
これは初期では無視しましょう。
まず、目的の形にすることを優先する。

思い切る

これが一番難しいですね。
例えば「思い切って別の場所に移動する」や「削除する」という判断です。
これをすると「そもそもしないほうが良かった」とかなる場合もあるので、

最後に

正直、実作業はもっと大規模なものがメインだと思うのでこれで最後まで実装しちゃうと大変な事になりそうですので、時々立ち戻ってシステム全体を構成し直したりとかが必要だと思います。

ただ、この集中と発散を効率的に繰り返せるプログラマの方は良いプログラミングができそうな気もします。