また1からこつこつと

最高はひとつじゃないと信じてまたがんばります。

GoogleChromeでjQueryのバージョンによって、2つの処理ができたりできなかったり

ちょっと不思議に思ったのでメモ

学校の情報の課題でWebページを製作しているのだけれど、そのなかでjQueryのfadeIn()と、スクロールをかっこよくしてくれるコードを2つ使った。

いざ、動かしてみようと思ったら、fadeIn()は動くけどスクロールのほうは動かない。

ちなみにタイトルにもあるとおりGoogleChromeで動作せず、Safariだと正常に動いた。

jQueryのバージョンは2.2.0

コードはこんなかんじ

<script>
//フェードインのエフェクト
$(document).ready(function() {
	$('body').fadeIn(2000);
});
//スクロール
$(function(){
	$('a[href^=#]').click(function() {
                var speed = 700;
                var href= $(this).attr("href");
               	var target = $(href == "#" || href == "" ? 'html' : href);
                var position = target.offset().top-50;
                $('body,html').animate({scrollTop:position}, speed, 'swing');
                return false;
  });
});
</script>

おかしいなぁと思ってjQueryのバージョンを変えてみた。
ver1.11.2だと同じように動作せず...
ver1.12x系も同じく

ところが、ver1.11.3だと正常に動作した!

jQuery自体をあまり知らないのでこの差はよくわからないんだけど、この小さなマイナーアップデートの間になにがあったんだと思った

【Swift】タップした間隔からBPMを計算してみた

試験も終わり久しぶりにコード書きたくなったので、かねてから作っていたアプリに新しい機能を実装すべくいろいろ考えていた。

その中で、タップした間隔からそのBPMを取得するっていうのが必要で、実際にそれを作ってみたので紹介します。

そもそもBPMって?

音楽やってたりする人はよく耳にする言葉だと思うけど、もう一度おさらいしておきます。
BPMとは、 Beat Per Minutes の略で、1分間に何回ビートが打たれたかを示す値です。
BPM100っていうのは1分間に100回ビートを打ったときの速さという意味。
簡単に言ってしまえばBPMとは曲の速さを示してるということ。


タップのタイミングを計測する

UIButtonをタップしたときのタイミングをどうやって計測するかが最大の問題だった。
結局のところ、NSTimerを使って、計算する方法が一番だった

var cnt:Float = 0

func viewDidLoad(){
 super.viewDidLoad()
 timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "onUpdate:", userInfo: nil, repeats: true)
}

func onUpdate(timer: NSTimer){
        cnt += 0.01
        print(String(cnt))
}

まずこのコードでcnt変数が0.01秒毎に0.01ずつ増やすことができた。そこにUIButtonと組み合わせてタップした間隔を取得する。

import UIKit

class BPM: UIViewController {
	
	//時間データを格納する配列を用意
	var timeData:[Float] = []
	var difData:[Float] = []
	
	//各種変数を宣言
	var countNumber:Float = 0
	var timer:NSTimer!
	
	//UIパーツ
	let button:UIButton = UIButton()

	
	override func viewDidLoad() {
		super.viewDidLoad()
		
		//ボタンのUI
		button.frame = CGRectMake(0, 0, 100, 100)
		button.setTitle("tap me", forState: .Normal)
		button.titleLabel?.textAlignment = NSTextAlignment.Center
		button.addTarget(self, action: "tapped:", forControlEvents: .TouchDown)
		self.view.addSubview(button)
		
		//タイマーをスタートさせる
		timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "onUpdate:", userInfo: nil, repeats: true)
		
	}
	
	//ボタンが押された時の処理
	func tapped(sender: UIButton){
		print("tapped")
		
		//押された時の時間をtimeDataに格納
		timeData.append(countNumber)
		
		var ave:Float = 0
		
		//2回以上タップされていたら間隔を計算。それをdifData配列に格納する。
		if timeData.count > 1{
			
			difData.append(timeData[timeData.count-1] - timeData[timeData.count-2])
			
			//dif配列に格納されている値の平均値をとる
			//すべての値を足し合わせる
			for var i=0; i<difData.count; i++ {
				ave = ave + difData[i]
			}
			
			//平均値の計算
			ave = ave / Float(difData.count)
			
			//BPMを計算
			let bpm:Float = 60 / ave
			print(String(format: "%.01f", bpm))
			
		}
		
	}
	
	//タイマーが実行されるたびに呼ばれる = 0.01秒ごとに呼ばれる
	func onUpdate(timer: NSTimer){
		countNumber += 0.01
		print(String(countNumber))
	}

	
}

これでBPMが得られます。

BPMを数式化してみる

上記のコードを理解するためにBPMの算出方法を数式にしてみる。
数式と言っても大したことないです。

  • (BPM60)= 1分間に60回のビート = 1秒 / 1回
  • (BPM120) = 1分間に120回のビート = 1秒 / 2回 = 0.5秒 / 1回

このことから、

  • 60 / 間隔の秒数 = BPM

となります

複数の値の平均値から算出する

//dif配列に格納されている値の平均値をとる
//すべての値を足し合わせる
for var i=0; i<difData.count; i++ {
	ave = ave + difData[i]
}

//平均値の計算
ave = ave / Float(difData.count)

//BPMを計算
let bpm:Float = 60 / ave
print(String(format: "%.01f", bpm))

これは上のソースから抜粋したものです
for文で配列に入っている値すべてを足し合わせたあとに、それを配列の個数で割ることで平均値を求めています
この値を使用するメリットは、求めたBPMの値の精度が上がることです
前後2つのデータを比較するだけだと振り幅がけっこう大きくて、かなり大雑把なものになってしまいます

ただし、タップしすぎると要素数が多くなりすぎて比較が困難になるので、定期的にリセットしてあげたほうが効果的でした

うーん、説明下手ですみません
これを実装したアプリは近日中にAppStoreで公開する予定です

【AppleWatch】簡単なカウントアプリを作ってみた

昨年の8月に購入したAppleWatchだけど、プロビジョニングファイルの諸々の設定が前に使っていたAppleIDに紐付いていたりしてなかなか開発できていなかった。もともと開発用に買ったのに…

今日、少しスイッチがはいったので久しぶりにコード書いてみた。

とりあえずソースコード

ほぼほぼ見たまんま書いてるのであまり参考にはならないですが、とりあえずソースコード載せておきます。

//
//  InterfaceController.swift
//  HelloWatch Extension
//
//  Created by mjk on 2016/01/06.
//  Copyright © 2016年 Kirie Miyajima. All rights reserved.
//

import WatchKit
import Foundation


class InterfaceController: WKInterfaceController {
    @IBOutlet var myLabel: WKInterfaceLabel!
    @IBOutlet var plusBtn: WKInterfaceButton!
    @IBOutlet var minusBtn: WKInterfaceButton!
    
    var num:Int = 0

    override func awakeWithContext(context: AnyObject?) {
        super.awakeWithContext(context)
        
        myLabel.setText(String(num))
        myLabel.setTextColor(UIColor.whiteColor())
        
        plusBtn.setTitle("+1")
        plusBtn.setBackgroundColor(UIColor.redColor())
    
        minusBtn.setTitle("-1")
        minusBtn.setBackgroundColor(UIColor.blueColor())
        
        
        //FourceTouch時の設定
        addMenuItemWithItemIcon(WKMenuItemIcon.Decline, title: "reset", action: Selector("SelectMenu"))
        
    }
    
    func SelectMenu(){
        num = 0
        myLabel.setText(String(num))
    }
    

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
    }
    
    @IBAction func plus(){
        num++
        myLabel.setText(String(num))
    }
    
    @IBAction func minus(){
        num--
        myLabel.setText(String(num))
    }

}

これを動かすとこうなります

基本的な構造

AppleWatchのアプリはStoryBoardを使わないと開発できない。僕はiOSアプリを開発するときにStoryboardを使わない派だったので、単純にStoryboardの使いかたがわからずちょっと悩んだw

UIKitは使えず、WatchKitをimportする
なのでUILabelとかUIButtonとかは使えなくて、その代わりWKInterfaceLabelやWKInterfaceButtonというクラスが用意されている

awakeWithContextがいってみればviewDidLoadみたいな感じかな
とりあえずここに書いておけば動く
...ちゃんと調べますすみません

forceTouch

forceTouchの実装って大変なのかなって思ってたけどなにも難しくなかった

addMenuItemWithItemIcon(WKMenuItemIcon.Decline, title: "reset", action: Selector("SelectMenu"))

これだけ。forceTouchするとアプリのMenuが呼ばれる仕組みになっているので、addMenuItemsしてしまえば勝手になってくれるらしい
便利だ

ちなみに、WKMenuItemIconっていうのにはあらかじめ用意されているアイコンを載せることもできるし、自分でimageを貼り付けることもできる
こちら一覧です

f:id:mjk0513:20160107001936j:plain
【AppleWatch】コードからコンテキストメニューを生成する | 株式会社スカイセンス

【追記 2016/01/07】
GitHubソースコード置きました
github.com

2015年にはまったこと【ガジェット編】

今年買ったガジェットといえば、言わずもがなAppleWatchですね。8月の中旬にAppleStore表参道で友人とふたりで購入してから4ヶ月ちょい。

mjk0513.hateblo.jp

今のところずっと使い続けている。

実は途中で一度修理にだしたことがあった。初期不良でセンサー系統に不具合があり、スタンドがまったく記録されなかったり、ワークアウトがすぐに一時停止になってしまったりと。それを直しに行ったのが10月の頭とかかな。

まだ第一世代ということもあり、正直なところ動作も大分まったりしてたり、レスポンスあんまりよくない。そこら辺を早く改善してほしい。

あと技術的な面を話すと、WatchOS2になってからデベロッパができることの幅がかなりひろがった。将来的にiOS8のリリース時みたいに大量のAPI群がどかっと開放されたりするだろうから、いまのうちにマスターしておきたい。

10月に行った勉強会で、AppleWatch上でゲーム開発した人の話がおもしろすぎたのでリンク貼っておきます。@giginet 氏

giginet.hateblo.jp

こういう開発の手法、かっこよさです。

2015年にはまったこと【デザイン編】

大晦日ですね。続き書きます。

今年はデザインをよくやった年だった。ちょっとはセンスがあがったかな?

Photoshopの使いかたを習得した

過去記事にも書いたけど、文化祭のポスターとパンフレットを製作した。

mjk0513.hateblo.jp

 ここでいろいろ試行錯誤した結果、Photoshopの使いかたをかなり学んだ。これで大抵のことはフォトショでできるようになった。

細かい話で言うと、たとえばRGBCMYKの違いについてとかね。印刷用だとCMYKで出力しなきゃいけないの知らなくて印刷会社に言われたのはいい思い出。

イベントのロゴを作った

f:id:mjk0513:20151217165259j:plain

これなんかもPhotoshopで作ってるんだけど、なんかそれっぽい。ちゃんとした風に見えるので良い。

デザインのセンス

僕はこれまでデザインについて勉強したことが一度もない。どこかのタイミングでしたいなとはおもっているんだけどなかなか手がでない。

なので今まで作ってきたものはすべて直感というか、ある意味センスだけで成り立っている非常に脆いもの。ある程度それっぽく見えるのは、しっかりとしたデザインに「インスパイア」されているからであり僕自身の純粋なセンスじゃないんだよな。

センス磨いて自分のものにしたいね。

音楽といい、デザインといい、なんだかアーティスティックな方面に興味が移ってることをひしひしと感じる2015年の大晦日でした。