思いつきでテキトーに書いた(Circle Seek Bar 2016/08/10修正版)



手抜きだからドラッグなんて実装してない。というかインターフェイス的にどれが正しいかわからん。Oriduruが半円なのはそういう意味もあるんだけどね。直線型と操作が似るから。

あんまり円をでかくするとやっぱりメモリ喰うから気をつけて。

Image_computer/seekbar.png



// ==PREPROCESSOR==
// @name "Circle Seek Bar"
// @author "Junya Renno"
// @version "2016/08/10"
// ==/PREPROCESSOR==


//設定項目
var margin = 40; //上、左の余白ピクセル
var start_degree = 270; //スタートする角度 0~360 0-右 90-下
var direction = true; //向き、true=時計回り false=逆回転
var c_size = 200; //円の直径
var line_width = 4; //線の幅
var shadow_color = RGB(180,180,180); //円の後ろの影色
var circle_color = RGB(250,140,140); //円の色
var change_value = 5; //ホイール操作で変化する値
var time_show = true; //時間表示
var time_font = gdi.Font("MS ゴシック",20); //時間表示フォント
var click_width = 6; //クリック判定の遊び

var val = 0;
var limit = 360;
var degree = val + start_degree;
var ww = window.Width;
var wh = window.Height;
var temp_bmp = gdi.CreateImage(c_size+line_width,c_size+line_width);
var mask_bmp = gdi.CreateImage(c_size+line_width,c_size+line_width);
var r,d;
var c_half = (c_size+line_width)/2;
var points = new Array;
var pole_points = new Array;
var g_drag = 0;
var g_drag_seek = 0;
var length = fb.PlaybackLength;
var txt;
var side_in = c_size/2 - (click_width + line_width/2);
var side_off = c_size/2 + (click_width + line_width/2);

//時間の文字列整形
function TimeFmt(t){
var zpad = function(n){
var str = n.toString();
return (str.length<2) ? "0"+str : str;
}
var h = Math.floor(t/3600); t-=h*3600;
var m = Math.floor(t/60); t-=m*60;
var s = Math.floor(t);
if(h>0) return h.toString()+":"+zpad(m)+":"+zpad(s);
return m.toString()+":"+zpad(s);
}

function rad2deg(r){
var d = r * 180 / Math.PI;
return d;
}
function deg2rad(d){
var r = d * Math.PI / 180;
return r;
}
function RGB(r, g, b) {
return (0xff000000 | (r << 16) | (g << 8) | (b));
}

function RGBA(r, g, b, a) {
return ((a << 24) | (r << 16) | (g << 8) | (b));
}

function loop_degree(d){
if (d<0)
d = d+360;
if (d>360)
d = d-360;
return d;
}

function initilaize_points(){
pole_points[0] = calc_position(start_degree);
pole_points[2] = calc_position(loop_degree(start_degree+90));
pole_points[3] = calc_position(loop_degree(start_degree+180));
pole_points[4] = calc_position(loop_degree(start_degree+270));
}

function calc_position(d){
var r = deg2rad(d);
var x = c_size * Math.cos(r) +c_half;
var y = c_size * Math.sin(r) +c_half;
if (!direction)
x = -x + c_size;
return [x,y];
}

function make_graphic(){
temp_gr = temp_bmp.GetGraphics();
temp_gr.SetSmoothingMode(4);
temp_gr.DrawEllipse(line_width/2,line_width/2, c_size, c_size, line_width, circle_color);
temp_bmp.ReleaseGraphics(temp_gr);
}

function make_mask(d){
mask_gr = mask_bmp.GetGraphics();

if (val == limit)
mask_gr.FillSolidRect(0,0,mask_bmp.width,mask_bmp.height,RGB(0,0,0));
else {
mask_gr.FillSolidRect(0,0,mask_bmp.width,mask_bmp.height,RGB(255,255,255));
var pp = Math.floor(loop_degree(degree - start_degree)/90);
pole_points[1] = calc_position(degree);
points.push(c_half,c_half,pole_points[0][0],pole_points[0][1]);
if (pp > 0)
points.push(pole_points[2][0],pole_points[2][1]);
if (pp > 1)
points.push(pole_points[3][0],pole_points[3][1]);
if (pp > 2)
points.push(pole_points[4][0],pole_points[4][1]);
points.push(pole_points[1][0],pole_points[1][1]);
mask_gr.SetSmoothingMode(4);
mask_gr.FillPolygon(RGB(0,0,0), 0, points);
points = [];
}
mask_bmp.ReleaseGraphics(mask_gr);
}

//init
initilaize_points();
make_graphic();

function on_paint(gr){
length = fb.PlaybackLength;
if(length > 0){
if(g_drag){
val = g_drag_seek;
txt = TimeFmt(Math.floor((val / 360) * length)) + " / " + TimeFmt(fb.PlaybackLength);
} else {

val = Math.floor(360 * (fb.PlaybackTime / length));
txt = TimeFmt(fb.PlaybackTime) + " / " + TimeFmt(fb.PlaybackLength);
}
}
degree = loop_degree(val + start_degree);
gr.SetSmoothingMode(4);
gr.DrawEllipse(margin, margin, c_size, c_size, line_width, shadow_color);
make_mask(degree);
var temp_clone = temp_bmp.clone(0,0,c_size+line_width,c_size+line_width);
temp_clone.ApplyMask(mask_bmp);
//gr.DrawImage(mask_bmp,margin-line_width/2,margin-line_width/2, mask_bmp.width, mask_bmp.height,0,0,mask_bmp.width, mask_bmp.height,0,255);
gr.DrawImage(temp_clone,margin-line_width/2,margin-line_width/2, temp_bmp.width, temp_bmp.height,0,0,temp_bmp.width, temp_bmp.height,0,255);
//時間表示
if (time_show){
// gr.FillRoundRect(c_size/2+margin-70,c_size/2+margin-20,140,36, 4, 4, RGBA(255,255,255,120));
gr.DrawString(txt,time_font,RGB(0,0,0),c_size/2+margin-50,c_size/2+margin-15,140,30);
}
temp_clone.Dispose();
}


function on_size(){
ww = window.Width;
wh = window.Height;
}

function on_mouse_wheel(delta){
if(delta>0){
val = val+change_value>limit ? limit : val+change_value;
} else {
val = val-change_value<0 ? 0 : val-change_value;
}
fb.PlaybackTime = Math.floor((val * length / 360) );
window.Repaint();
}
function on_playback_starting(cmd, paused){
}

function on_mouse_lbtn_down(x,y){
g_drag = 1;
}
function on_mouse_lbtn_up(x,y){
if(g_drag){
g_drag = 0;
if (x > margin+c_size+click_width+line_width/2 || x < margin - click_width - line_width/2 || y > margin+c_size+click_width || y < margin-click_width)
return;
var tmp_line = Math.round(Math.sqrt(Math.pow(x - margin - c_size/2,2) + Math.pow(y - margin - c_size/2,2)));
if (side_in < tmp_line && side_off > tmp_line){
if (direction){
var r2 = Math.atan2(x - margin - c_size/2,-(y - margin - c_size/2));
} else {
var r2 = Math.atan2(-(x - margin - c_size/2),-(y - margin - c_size/2));
}
var d2 = loop_degree(Math.round(rad2deg(r2))-start_degree);
d2 = loop_degree(d2 - 90);
val = d2;
fb.PlaybackTime = Math.floor((val * length / 360) );
window.Repaint();
}
}
}

function on_playback_new_track(info){
window.Repaint();
}
function on_playback_stop(){
window.Repaint();
}
function on_playback_seek(time){
window.Repaint();
}
function on_playback_time(time){
window.Repaint();
}
function on_playback_stop(reason) {
if (reason == 1){
val = 360;
window.Repaint();
}
}
//EOF




Image_computer/touka.jpg

追記2:概要
元になるアイディアは、マスク用のモノクロ画像を作って 円の画像にApplyMask()するというもの。

マスク画像を作る

Image_computer/poly.png

水色がマスク画像。大きさはa*aピクセル。
中心が(a/2,a/2)、半径aの円を想定し、開始角度の円周上の点をp1にする。
円を4等分するようにp2,p3,p4を計算しておく。
円周上のp5は現在位置。


開始角度からの角度の差が
0-90:始点(a/2,a/2) - p1 - p5
90-180:始点 - p1 - p2 - p5
180-270:始点 - p1 - p2 - p3 - p5
270-360:始点 - p1 - p2 - p3 -p4 - p5

の座標を結ぶポリゴンを描く。緑の領域。


ということで。


 

>円形プログレスバー

組み合わせればいけそうな・・・気がする。

FUIで作った円形プログレスバーのコードを晒しておきます。


On Playback Time (Per Second)

$removeobject(%S_O%)
$if(%playback_can_seek%,



$gp_arc(%mainid%,%S_X%,%S_Y%,%S_W%,%S_H%,
270,
$calc(%S_CIRCLE%*{%playback_position%/%playback_length%}),
pen:215-255-0-0-2,glow:104-155-255-4-8)
$hash(S_O,%_result%)
$updateobject(%S_O%)


,)


----------------------------------------
Load


$clearobject(%_id%,event:load)


$hash(S_X,15)
$hash(S_Y,100)
$hash(S_W,370)
$hash(S_H,370)
$hash(S_CIRCLE,360)



$gp_circle(%_id%,%S_X%,%S_Y%,%S_W%,%S_H%,pen:100-255-255-255-2)

$updatewindow(%_id%)


矩形のシークバーでドラッグに挑戦中・・・死ぬかも。

Posted by 羅刹 at 2016/08/07 (Sun) 10:52:48

>Func UIってまだ動くん?

動いたためしがないからあきらめてたんだけど。

Posted by 連野 at 2016/08/07 (Sun) 21:52:24

>ごめん、URL書いてあるとコメント弾く設定。

一時期中国系からのコメントスパムが凄くて、アドレス書いてあると一律に弾く設定にしてあります。
スパムってのは誘導しないと意味がないので、これが一番効果的なんです。
ログは取っているので伝わってはいます。謝謝。

Posted by 連野 at 2016/08/08 (Mon) 10:48:47

コメントは日本語でお願いします。(URLは入力禁止:Do not URL writing.) :System message: コメントを受けつけています。