カテゴリーアーカイブ JavaScript

asaba 著者:asaba

【javaScript】今更WebAudioAPIを試す

去年の話ですが、お遊びで動物の鳴き声を使った目覚ましアプリを作ろうとしたときにWeb Audio APIというプラグインを知りました。

javascriptにおける音声を再生または取り込むための機能は、フラッシュやhtml5対応の</audio>タグがその役割を担っています。

両方とも音声の再生をする分には困ることはないのですがこれらのオブジェクトはいかんせん制約が多く、現在の速さが求められる

アプリ開発とは相性が悪いです。なのでこれからはWeb Audio APIを使ってねという記事を目にしました。

Web Audio APIとは、webアプリケーション向けに開発された、音声ファイルの管理に特化したjavaScriptAPIです。

コード量も少ないので、複雑な処理でなければ初心者のかたでも扱うことができます。

ざっくりとですが、コンテキストで音声の再生を管理するコードがこちらです。

var context;
window.addEventListener('load',init,false);
function init(){
  window.AudioContext = window.AudioContext || window.webkitAudioContext;
  context = new AudioContext();
}
  catch(e){
  alert('web Audio API is not supported in this browser');
  }
}
[/javascipt]

initで初期化させてスタンバイさせておけば、後はcontextで読み込んでくれるのでここだけ抑えておけば基本は大丈夫だと

思います。iphoneでは未検証なので断言はできないですが、他の従来のプラグインも素直に動いてくれているのでAPIサポート外

でもない限りこっちでも問題ないのではないでしょうか。

後はこれをreactとかのライブラリに入れるとちゃんと動くのかなとか考えることもありますが、現状javaScriptで音声を

扱いたいなと思ったらこのwebAudioAPIで間違いないと思うので、もしよろしければ参考に・・・

  • この記事いいね! (0)
著者:杉浦

LeafletのアイコンオプションiconAnchorの意味

 Leafletは地図をJavaScriptで描画、操作するためのライブラリです。地図上に何かを置きたい時、それはアイコンオブジェクトを用いて実現することが多いです。アイコンを定義する際にはicon関数を用いて次の様に定義します。次のコードはMarkers With Custom Icons – Leaflet – a JavaScript library for interactive mapsからの引用です。

var greenIcon = L.icon({
    iconUrl: 'leaf-green.png',
    shadowUrl: 'leaf-shadow.png',

    iconSize:     [38, 95], // size of the icon
    shadowSize:   [50, 64], // size of the shadow
    iconAnchor:   [22, 94], // point of the icon which will correspond to marker's location
    shadowAnchor: [4, 62],  // the same for the shadow
    popupAnchor:  [-3, -76] // point from which the popup should open relative to the iconAnchor
});

 このオプションの中にiconAnchorというものがあります。直訳してマーカーの位置に対応するアイコンの点です。Leafletはこの緯度経度に、このアイコンを用いてマーカ―を、この地図上に置く、という様にマーカーを地図上に置きます。

L.marker([51.5, -0.09], {icon: greenIcon}).addTo(map);

 マーカーという以上、地図を見るものにその印を示すために絵を用います。iconAnchorはこの絵のどの部分に指定した緯度経度がくるかを指定するオプションです。もしiconAnchorを間違えた場合、矢印の根元のような直感的でない部分が位置を指すことになってしまいます。
 Explanation of Leaflet Custom Icon LatLng vs XY Coordinates – Stack Overflow
 このStack Overflowの図説が完結にまとまっていました。

 左上を(0,0)とし、用いるimgに合わせてpx単位で合わせることが基本になります。割合を用いないのはアンチパターンに見えますが、アイコンを定義する際の単位はいずれもピクセル単位となっているためこのやり方が推奨のやり方となっています。

  • この記事いいね! (0)
著者:杉浦

HSL表記によって色を自然に変化させる

 色の表記の定義である色空間には様々なものがありますよく聞くものに赤青緑の三原色を用いたRGB、それに加えて透明度を足したRGBAがあります。他にも印刷で使われるCMYK(Cyan, Magenta, Yellow, Key plate)やLab色空間、XYZ表色系など目的に合わせて多くのものが作られています。HSLはその中の一つでHLSとも呼ばれ色相(Hue)、輝度(Lightness)、彩度(Saturation)の3値から定義される色空間です。HLSの値の大雑把な意味は次です。

  • 色相:色味を0~360度の範囲の角度で表す。0度は赤で、その反対側に位置する180度は赤の反対色にあたる青緑。すなわち、反対色を見つけるのも容易。色相についてはHSVと同じ。
  • 彩度:HSVとは違い、純色から彩度が落ちるということは、すなわち灰色になっていくという考え方に基づいている。
  • 輝度:明度100%を純色とし、そこからどれだけ明るさが失われるかを示すHSVとは違い、輝度0%を黒、100%を白とし、その中間(50%)を純色とする。50%以下はHSVの明度を示し、50%以上はHSVの彩度を示すと考えると分かりやすいだろう。

HLS色空間 – Wikipediaより引用

 紹介するHSLの主な利点は二つです。まず第一にCSSのオプションとして直接指定できます。次の様にhsl(hue, ssaturation, lightness)を指定するのみで大変楽です。

style="background-color: hsl(90deg, 100%, 50%);

CSS を使った HTML の要素への色の適用 – HTML: HyperText Markup Language | MDN #HSL_functional_notation
– CSS: カスケーディングスタイルシート | MDN #HSL_colors
 わざわざ変換式を実装してRGBに変える必要も、RGB上でややこしい計算をする必要もありません。
 第二は自然で多彩な色の変化を簡単に表せることです。次のJSFiddleはHSL方式とRGB方式それぞれで箱の中の色を変えるコードの実装です。

 色相の下に彩度、輝度が引っ付いているイメージで簡単に色を決定することができると思います。RGBでは赤緑青から離れる程どうやって思いついた色を作るのかてこずるでしょう。
 HSLがRGBに比べて特に便利なのがある色からある色への変化です。同時刻にある色になる様に三値をそれぞれ一次関数的に変化させるのみできれいな色の変化を実現できます。

  • この記事いいね! (0)
asaba 著者:asaba

【html-css】複数のセレクトボックスを並列で表示させる

今回は、セレクトボックスを複数並べたいかつ横に揃えたい時にしたことを書いていきます。

セレクトボックス、決められた項目をプルダウンで表示させるアレのことです。よくアンケートフォームやアプリの会員登録画面で

見受けられますが、案件によってはこのオブジェクトを複数決められた位置に並べたいという時もあるのではないでしょうか。

現に今どきのフォームだと○○県○○市といった県と市を分けて表示するデザインが増えており、今はもうそんな感じのデザインが

主流なのかなと勝手に考えております。

自分も、今回の開発でセレクトボックスを複数出したかったので汚いながらも気合でやってみたのでもしこんなのでよければ参考に

してください。

まずは、htmlからです。reactで書いた誕生日のサンプルですね。

</pre>
<span className="birthday">
<p>生年月日</p>
<select value={this.state.member.year || ''} onChange={(e) => this.handleYearChange(e)} >
{ this.yearData.map( d => <option key={d.value} value={d.value}>{d.label}</option>)}
</select>
<label htmlFor="select-01">年</label>
<select value={this.state.member.month || ''} onChange={(e) => this.handleMonthChange(e)} >
{ this.monthData.map( d => <option key={d.value} value={d.value}>{d.label}</option>)}
</select>
<label htmlFor="select-01">月</label>
<select value={this.state.member.day || ''} onChange={(e) => this.handleDayChange(e)} >
{ this.dayData.map( d => <option key={d.value} value={d.value}>{d.label}</option>)}
</select>
<label htmlFor="select-01">日</label>
<span className="error">{this.state.error ? this.state.error.birthday : ''}</span>
</span>
<pre>

なんでdivじゃないのとツッコミを受けそうですが、divを使うと改行してしまい一行ずつセレクトボックスが表示されてしまうという

事態が起きるので、代用して改行をしないspanを使い並列に並べるという意図でございます。

続いてcssです。

</pre>
span.birthday {
width: 90px;
padding:0;
font-size:0px;
}
span.birthday select {
width:110px;
height: 50px;
margin:10px;
border:1px solid black;
display: inline-block;
text-align: center;
font-size:16px;
background-color:#fff;
}
<pre>

あまり深いことは書いていないのですが、span.birthdayでセレクトボックスを三つ並べられるようエリアを拡大していますね。

下のspan.birthday.selectでセレクトボックスそのものの大きさとセレクトボックスの外線、位置を決めています。

以上でセレクトボックスを横向きに表示するコーディングはおしまいです。実はこれもネットにも中々乗っておらず、一つ一つ

パーツを繋ぎ合わせてせこせこ書いていました。いびつですが、正しく動きますので、reactで同じようなコンポーネントを

作りたい、でもどこにも思ったことが書いていない!というかたはもしよろしければ参考にしてみてください。

  • この記事いいね! (0)
著者:杉浦

Vue.jsでVue.js向けに開発されていないライブラリを用いる

 Vue.jsはwebページを部品化してコーディングすることを目的としたJavaScriptのフレームワークです。単一コンポーネントの仕組みを用いたVue.jsのコード例の多くは(少なくとも私の読んだコードでは)次の様になっています。

// コンポーネント定義用Vue.jsコード
<template>
  // Vue.jsと連携するHTMLコード
</template>

<script>
export default {
  name: 'hoge',
  // prop:{}とかdeta(){return {hogehoge}}とかmethods:{}とかVue.jsと連携するためのプロパティ
};
</script>

<style scoped>
  // このコンポーネント内でのみ適用されるcss
</style>
// コンポーネント読み込み用JavaScriptコード
window.$ = window.jQuery = require('jquery');
// 色々グローバルで使うライブラリ

window.Vue = require('vue');

Vue.component('hoge', require('./hoge.vue').default);

const app = new Vue({
  el: '#app',
});

 自分はVue.jsで使うことを前提にしていないライブラリはJavaScript側2、3行目の様に色々読み込むものだと思っていました。一方でこのようなやり方はグローバル汚染がひどく、重要なごく一部のライブラリ以外を読み込んだ場合あっという間にバグが生まれるとも思っていました。実際はそのようなことをせずともよく、次の様に記述することで管理しやすくライブラリを用いることができました。

<template>
  // Vue.jsと連携するHTMLコード
</template>

<script>
import 'fuga';
import foo from 'foo';

// Vue.jsに依らない静的処理
const bar = foo.bar();

export default {
  name: 'hoge',
  // importしたライブラリや変数barを用いたVue.jsと連携するコード
};
</script>

<style scoped>
  // このコンポーネント内でのみ適用されるcss
</style>

 <script>タグの先頭に記述するだけです。<script>タグの内部ならばVue.jsがいい感じにスコープを作ってくれるのでグローバル汚染を気にせず好き勝手できます。
 <script>export default {で始めて、}</script>で終わらなければならないという風に思い込んでいましたがVue.jsにその様な縛りはなく、実際はかなり自由に記述できました。

  • この記事いいね! (0)
村上 著者:村上

【JavaScript】「The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype」エラーの対処法

長いタイトルですみません…。
現在開発中のシステムで導入している ESLint という検証ツールで、タイトルにあるエラーが発生したので、対処法をまとめ。
エラー文は「The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype.」というもので、翻訳したところ「for-inの本体は、プロトタイプから不要なプロパティをフィルタリングするためにif文でラップする必要があります。」とのことでした。
…いまいち意味が分からない…。

 

今回参考にさせていただいた記事はこちら。

JSLintオプション考察「unfiltered for in」|もっこりJavaScript|ANALOGIC(アナロジック)
http://analogic.jp/jslint-options-forin/

上の記事によると、for-in ループを使用したときに列挙されるプロパティには、実際のデータ以外にも、プロトタイプ連鎖から来たプロパティも含まれるとのことでした。
そのため、取得したデータがオブジェクト自身が持つプロパティなのか、プロトタイプ連鎖から来たプロパティなのかを判断する必要があります。
で、それは hasOwnProperty() を使うことで判断できるとのこと。

使い方は下記のとおりです。

const list = ['A', 'B', 'C', 'D', 'E'];
for (data in list) {
    if (list.hasOwnProperty(data)) {
        // 実行したい処理
    }
}

3行目で、データの判別を行っています。
こちらを追加したところ、エラーが解消され、問題なく実行できました。

 

以上、JavaScript の for-in 文で発生したエラーの対処方法でした。
なおこの後、実装しているコードでは for-in よりも forEach の方が向いているとわかり、上記は使用しないように修正しました…。
が、うっかりと再発させそうなエラーだったので、備忘録としてまとめました。
もし、同じことでお困りの方は参考にしていただければと思います。

  • この記事いいね! (0)
著者:杉浦

Leaflet関連のライブラリを用いる際たまに起こるライブラリのバグ

Leaflet – a JavaScript library for interactive maps
 LeafletはJavaScript上で地図を描画、操作できる様にするライブラリです。地図の需要は多くLeafletを拡張するライブラリもまた多くあります。紹介するのはこのLeafletに何かを付け足すようなライブラリにありがちなバグです。
 Leaflet関連のライブラリはLeafletに様々なものを載せます。例えばフルスクリーン化、google map、ミニマップ、サイドバー。重要なのはこれらのいずれもまずLeafletありきだということです。このためライブラリの中には単独で動くようにライブラリ内でLeafletを読み込んでくれるものがいます。これ自体はありがたいしそのライブラリ単独ではむしろ良いことです。ですがこの動作を既にLeafletが読み込まれているにも関わらず行った場合、問題が起きます。既に読み込まれていたLeafletを壊すことがあるのです。このLeafletを壊すような問答無用な読み込み動作を行うライブラリが稀にあります。
 Leaflet読み込み動作付きライブラリと他のライブラリを混ぜ合わせて使うと、他のライブラリを上書きして、存在するはずの関数が存在しない、引数の型が期待したものと異なるといった混乱が引き起こされバグが発生します。対処法はライブラリの中を見て

import L from 'leaflet'

の様な変数Lにleafletを出力している様な記述があるかチェックして消し、プロジェクト内に移動しパスを変更するだけです。
 ライブラリの中をいじること自体はバージョン管理が面倒になるアンチパターンもいい所なのであまり褒められたやり方ではありませんが、幸いLeaflet拡張機能系統のライブラリは小さなものが多く個人でもすぐに読み解け管理できます。

  • この記事いいね! (0)
村上 著者:村上

【React】エンターキーが押されたことを検知する方法

チャット画面を作成していたとき、エンターキーでテキスト入力エリアに入力したテキストを送信するという処理を行いたかったので、その方法について。
React と書いていますが、恐らく通常の JavaScript でも扱えるはず。

今回参考にさせていただいた記事はこちらから。

Reactでエンターキーのイベントを取得する方法 – 1日1%成長するブログ
http://masarufuruya.hatenadiary.jp/entry/2017/09/06/200551

 

さて、実装方法ですが、キー入力されたことは onKeyDown イベントで検知します。

<input type='text' onKeyDown={(e) => this.handleKeyDown(e)} />

上記は、なにかしらのキーが押された場合、その都度 handleKeyDown 関数が呼び出されます。

で、handleKeyDown 関数の中身は下記のとおりです。

handleKeyDown(e) {
  if (e.keyCode === 13) {
    // エンターキーが押された時の処理
  }
}

エンターキーは keyCode では 13 という数字が割り振られているとのことだったので、keyCode の値を見て判断します。
あとは、この if 文の中で、テキストを送信した際に行いたい処理を実行すればOKです。
非常に簡単でした!

 

以上、エンターキーが押されたかどうかを検知する方法でした。
なお、Androidの実機と iOS の Simulator でも動作確認を行いましたが、問題なく動作しました。
実行ボタンが無くなると、やはりレイアウトがすっきりする気がします。
是非、ご参考にしていただければと思います。

  • この記事いいね! (0)
asaba 著者:asaba

【react】render内で’===’を使うとなぜか文字列に変換される

reactのrender内では三項演算子がうまく働かない時があるんですが原因はなんなのでしょうか。

例えば

</pre>
const number = 1;

const shelter = number === 1 ? 'number' : 'ather';
<pre>

三項演算子はこのように定義するのですが、ここでは通常ならばnumber変数の中身は1なので変数shelterには’number’が入ります。

ですが、これをrender()内で実行すると、なぜかatherさんが格納されてしまうという事態に!

render()はstateが呼ばれるたびに更新するので、その時に変数も更新されてundefinedになっているのではと思ったのですがどちらの変数に

もしっかりと1が入っている(どういうこと!?)しかも文字列ではなくて普通に数値なんですがそれは・・・。

だとしたらもう怪しいのはお前しかいない、===!とりあえず特定をしたくてこれと==を比較して使ってみたのですが

見事にそれぞれ文字列と数値を吐き出していました。

てな訳で原因が分かったところで結局=を一つ減らして再render()して力ずくで解決させてしまいました。

そもそも数値で定義しているのになぜ文字列に解釈されているのかが分からないのですが。reactには勝手に値を変換するプラグインとかも

入れていないしjavascriptに型推論なんて存在しないしデフォルトの状態でこれならもう’===’を使うのを躊躇してしまいますw

ここは素直に’==’を使いましょうということでしょうか・・・

とりあえずrender()内で値を扱う時は値の型に気を配ってコーディングしなさいという戒めだと思って肝に銘じておきます。

  • この記事いいね! (0)
村上 著者:村上

【Cordova】端末のシェイクジェスチャーを検知できるプラグイン「cordova-plugin-shake」

今回は、スマートフォン端末がシェイクされたことを検知できるプラグイン「cordova-plugin-shake」をご紹介。
正直、今回実際に使うまでは「こんなプラグイン、一体いつ使うのか…」とも思っていましたが…意外と使うものなんですね。

そんな意外なプラグインのGitHubページはこちらから。

GitHub – leecrossley/cordova-plugin-shake: Cordova / PhoneGap Plugin to detect when a physical device performs a shake gesture
https://github.com/leecrossley/cordova-plugin-shake

 

実装方法ですが、まず下記のコマンドでプラグインをインストールします。

cordova plugin add cordova-plugin-shake

で、サンプルコードは下記のとおりです。

const onShake = function () {
  // シェイク検知成功時の処理
};
const onError = function () {
  // シェイク検知失敗時の処理
};
// シェイクジェスチャーの検知を開始
shake.startWatch(onShake, 30, onError);

shake.startWatch() 関数の第2引数と第3引数はオプションなので、指定しなくてもOKです。
ちなみに、第2引数の数値は、シェイク検知の感度のようですが…いまいちよく分かっていません。
なお、こちらのデフォルト値は 30 です。

で、シェイクの検知を終了したいときは、下記を呼び出します。

// シェイクジェスチャーの検知を終了
shake.stopWatch();

コードとしては以上です。
上記のサンプルコードそのままではないのですが、実際に使ってみたところ、問題なく動作しました。
感度も良く、何度も端末を振らなくてもすぐにシェイクジェスチャーが検知されました。

 

以上、シェイクジェスチャーを検知できるプラグイン「cordova-plugin-shake」のご紹介でした。
冒頭でも書きましたが、実際に使う場面はそうそう多くなさそうですが…もしご入用の際はご活用ください。

  • この記事いいね! (0)