質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

swift3でアナログ時計の回転軸が分からない

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 1,890

keys

score 199

正しい質問の仕方が出来てないかもしれませんがご了承ください。アナログ時計を実装しているのですが、秒針がうまく回転しましせん。時間通りに回転はするのですが、ブーメランみたいにくるくる回ってるだけです。

イメージ説明

 分からないこと

画像を正確に回転させるロジックがよくわかっていません。例えば、UIViewの座標の原点が左上だとしたら、左上から中心になるように画像を表示させ、そのまま回転を加えても、同じようなことになります。

どのような画像を、どのよう座標の原点で回せばいいのでしょうか。考え方をアドバイスいただけますか。まあ、QuartzCore、CALayer、CGAffineTransform、CATransform3D、CAAnimationらへんの知識を積もうと思っています。

 実装

赤い丸と秒針は別々の画像です。秒針の一番下を軸として、赤い丸の部分から離脱することなく正確に回したいです。上記の画像の実装のロジックは下記のように書いています。

 Timer  を使って1秒ごとに処理を実行します。

func update(tm: Timer) {
        //アナログ時計実装のための関数
let date = Date()
let calendar = Calendar.current
let sDeg = seconds * (360 / 60)
let seconds = calendar.component(.second, from: date)

回転実行

secondsImage.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI * Double(sDeg) / 180.0))

//下記のような警告が出てます

//'M_PI' is deprecated: Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.

 全ソース

let xPosition = TopMenu.frame.origin.x
        let yPosition = TopMenu.frame.origin.y - CGFloat(isClosed)
        let height = TopMenu.frame.size.height
        let width = TopMenu.frame.size.width
        UIView.animate(withDuration: 1.0, animations: {
        self.TopMenu.frame = CGRect(x:xPosition, y:yPosition, width:width, height:height)
        })
    }
    func update(tm: Timer) {
        //アナログ時計実装のための関数
        let date = Date()
        let calendar = Calendar.current
        let hour = calendar.component(.hour, from: date)
        let minutes = calendar.component(.minute, from: date)
        let seconds = calendar.component(.second, from: date)

        let hDeg = (hour % 12) * (360 / 12);
        let mDeg = minutes * (360 / 60);
        let sDeg = seconds * (360 / 60)
        print(hDeg)
        print(mDeg)
        print(sDeg)


          secondsImage.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI * Double(sDeg) / 180.0))

          //= CGAffineTransform(rotationAngle: CGFloat(M_PI * Double(sDeg) / 180.0));

   }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • fuzzball

    2017/05/22 09:18

    秒針の画像はどのような画像でしょうか?例えば、2x100のような縦長の画像でしょうか?

    キャンセル

回答 2

checkベストアンサー

+3

 手抜き

簡単なのは下のような画像を用意することです。
秒針

赤が秒針で、緑が回転の中心になります。
黒い外枠は分かりやすいように付けているだけで、実際には下半分は透明です。

下記のような警告が出てます
'M_PI' is deprecated: Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.

書いてある通りDouble.piを使って下さい。

 真面目に

変換するの面倒なのでSwift2.3です。

let t1 = CGAffineTransformMakeTranslation(0, -secondsImage.bounds.height/2) //起点ずらす
let t2 = CGAffineTransformMakeRotation(CGFloat(M_PI * Double(sDeg) / 180.0)) //回転
secondsImage.transform = CGAffineTransformConcat(t1, t2) //合体!

絵はこんな感じ。
秒針

 honamiさんの回答をコード化

起点をずらす。
viewDidLoad()などで一回代入しておけばいいです。

secondsImage.layer.anchorPoint = CGPoint(x: 0, y: +1.0)

回転部分のコードは変更なし。

secondsImage.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi * Double(sDeg) / 180.0))

絵は「真面目に」と同じです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/22 10:48

    ご丁寧にご回答ありがとうございます。おっしゃる通り考えてみれば、画像の中心に針の先端部がくるようにしないとブーメランみたいに回るのは普通に考えればわかることでした。非常に助かりました、ありがとうございます。

    キャンセル

  • 2017/05/22 15:24

    わざわざコード書いてもらって申し訳ない!助かります。

    キャンセル

+2

CALayer anchorpointあたりのキーワードが参考になるかもしれません。
UIViewのアニメーション基準点を変更することができます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/22 10:49

    ご回答ありがとうございました。CALayerやanchorpointの知識足りてないので勉強させていただきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る