Help us understand the problem. What is going on with this article?

PowerAppsで円スライダーを作った話

More than 1 year has passed since last update.

PowerAppsに標準で用意されているスライダーは1方向です。
勉強中に2次元いけるんじゃない?って思って試したら出来たので共有します。
ちょっと動きが不安定なので改善の余地はありますが、考え方が伝わればよいかなと思います。

こんなのできました

円のスライダー
円スライダー2.gif

どうやって作ったか

スライダーの位置をずらしながら円の上を操作しているように見せかけています。
スライダーを透明にしているので、実際に見えているボタンとレールは単なるアイコンで実際にそれを操作しているわけではありません。

円スライダー解説用1.gif

詳細

初期設定をどこかで行います。
今回はReset用のボタンを挿入してOnSelectに配置しました。

btnReset.Onselect
UpdateContext({Const:{sRight:1,sTop:2,sLeft:3,sBottom:4}});
UpdateContext({radius:100,angle:180,centerX:500,centerY:300,sliderPos:Const.sLeft,sliderThickness:50,tStart:false});
Reset(Slider);
UpdateContext({nicoX:1000,nicoY:300}) // スマイルアイコン用

スライダーの位置をボタンとともに動かす

ボタンを表示している位置とスライダーの位置を合わせるため、ボタンに重なるようにスライダー動かします。
また1方向にしか動かせないスライダーを2方向に動かすため、一定条件を満たしたときに縦と横を切り替えます。
今回はSlider.Max=145、Slider.Min=35としたため、Slider.Vale>135、Slider.Vale<45の時に縦と横を切り替えるようにしました。スライダーの上下左右の情報はsliderPosに保管しています。
また、切り替えはスライダーだけでは実装できないのでタイマーを挿入して以下のように設定しスライダーを監視させます。
タイマーがsliderPosを変更していきます。

SliderPosTimer
Start = tStart
Duaration = 10
Repeat = true
OnTimerStart = If(Slider.Value>135,If(sliderPos=Const.sTop || sliderPos =Const.sLeft,UpdateContext({sliderPos:Mod(sliderPos,4)-1}),UpdateContext({sliderPos:Mod(sliderPos,4)+1})));
               If(Slider.Value<45 ,If(sliderPos=Const.sTop || sliderPos =Const.sLeft,UpdateContext({sliderPos:Mod(sliderPos,4)+1}),UpdateContext({sliderPos:Mod(sliderPos+2,4)+1})));
               UpdateContext({angle: Switch(sliderPos,Const.sRight,Mod(Slider.Value-90,360),Const.sTop,-Slider.Value+180,Const.sLeft,-Slider.Value+270,Const.sBottom,Slider.Value+180)})

sliderPosの値を受けて、スライダーを動くようにします。

Slider
X = centerX + Switch(
    sliderPos,
    Const.sRight,
        Cos((-Slider.Value+90)/180 * Pi()) * radius-sliderThickness/2,
    Const.sLeft,
        Cos((Slider.Value+90)/180 * Pi()) * radius-sliderThickness/2,
    -radius
)
Y = centerY + Switch(
    sliderPos,
    Const.sTop,
        Sin((-Slider.Value)/180 * Pi()) * radius-sliderThickness/2,
    Const.sBottom,
        Sin((Slider.Value)/180 * Pi()) * radius-sliderThickness/2,
    -radius
)
Width  = If(Mod(sliderPos,2)=1,sliderThickness,radius*2)
Height = If(Mod(sliderPos,2)=0,sliderThickness,radius*2)
Layout = If(Mod(sliderPos,2)=1,Vertical,Horizontal)
Visible = false // テスト中はtrueのほうがよい
Onselect = UpdateContext({tStart:false}); 
           UpdateContext({tStart:true})  // タイマーを起動する
OnChange = UpdateContext({tStart:false}) // タイマーを停止する
Min = 35
Max = 145

見せかけのボタンとレールを追加する。

円を二つ用意してボタンとレールのようにします。

SliderBtnCircle
X = centerX-15 + Cos(
    Switch(
        sliderPos,
        Const.sRight,
            Mod(Slider.Value-90,360),
        Const.sTop,
            -Slider.Value + 180,
        Const.sLeft,
            -Slider.Value + 270,
        Const.sBottom,
            Slider.Value + 180
    )/180 * Pi()
) * radius
Y = centerY-15-Sin(
    Switch(
        sliderPos,
        Const.sRight,
            Mod(Slider.Value-90,360),
        Const.sTop,
            -Slider.Value + 180,
        Const.sLeft,
            -Slider.Value + 270,
        Const.sBottom,
            Slider.Value + 180
    )/180 * Pi()
) * radius
SliderRailCircle
X = centerX-radius
Y = centerY-radius

以上で円のスライダーが完成します。

スマイルマークを動かす

ここからは蛇足ですが、スマイルマーク(iconSmile)を動かすには以下の設定をすればOKです。

SliderPosTimer.OnTimerEnd
UpdateContext({nicoX:nicoX+Cos(angle/180*Pi())*10});
UpdateContext({nicoY:nicoY-Sin(angle/180*Pi())*10})
iconSmile
X = nicoX
Y = nicoY

課題

スライダーの円をなぞる分には問題がないのですが、ちょっとずれたりするとボタンが暴れます。
もう少し位置や縦横の切り替えタイミングを調整すれば解決できるかもしれません。
仕組みもまだまだ複雑なのでもっと簡略化したいです。手ごろに使えるようなところまで落とし込みたいですね。
(行列使えばいける・・・?)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした