页面切换

如果我们希望活动界面包括多个页面, 可以通过在超出屏幕的部分放置其他页面的内容, 并通过整个页面所有元素的移动达到类似页面切换的效果.

例如, 我们可以这样放置横纵六个页面的内容:

            |-----------|
            |   3, 2    |
            |           |
            |-----------|
            |   2, 2    |
            |           |
|-----------|-----------|-----------|-----------|
|   1, 1    |   1, 2    |   1, 3    |   1, 4    |
|           |           |           |           |
|-----------|-----------|-----------|-----------|

可以在每个页面的左上角放置一个 o 方便计算每个页面上的元素的位置:

# o
let tmp_rect = [page_offset_x_1 + page_offset_x_2 + page_offset_x_3, page_offset_y_1 + page_offset_y_2, 0.1, 0.1]
img(id: o11, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

let tmp_rect = [o11.l + 2, o11.t, 0.1, 0.1]
img(id: o12, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

let tmp_rect = [o11.l + 4, o11.t, 0.1, 0.1]
img(id: o13, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

let tmp_rect = [o11.l + 6, o11.t, 0.1, 0.1]
img(id: o14, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

#>if(page_offset_y_1_ratio)
let tmp_rect = [o12.l, o11.t - 2 * top, 0.1, 0.1]
img(id: o22, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)
#>fi

#>if(page_offset_y_2_ratio)
let tmp_rect = [o12.l, o11.t - 4 * top, 0.1, 0.1]
img(id: o32, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)
#>fi

在以上的定义中, 我们通过 page_offset_x_npage_offset_y_n 定义了 o11 的偏移量, 由于其他页面的偏移量都是相对于 o11 的, 所以在 o11 移动时, 其他页面的元素也会跟着移动.

此外, 我们还通过 #>if 设置了 o22o32 绘制的时机. 这是为了防止纵向切换后, 用户在活动首屏看到当前页面上方页面的内容. 通过这个值, 我们可以将页面上方的内容移出屏幕.

为了得出这些偏移量的具体值, 我们需要使用定义一些用于切换页面的按钮, 并通过按钮的 last 属性计算出偏移量的值.

global btn_r_1 = @btn
global btn_l_2 = @btn

global btn_r_2 = @btn
global btn_l_3 = @btn

global btn_r_3 = @btn
global btn_l_4 = @btn

global btn_r_3 = @btn
global btn_l_4 = @btn

global btn_u_1 = @btn
global btn_d_2 = @btn

global btn_u_2 = @btn
global btn_d_3 = @btn

# btn_lr_1234
let tmp_rect = [o12.l - 0.1, o11.t + top - 0.05, 0.1, 0.1]
img(id: btn_r_1_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/right_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_r_1, r: tmp_rect, t:fit)

let tmp_rect = [o12.l, o12.t + top - 0.05, 0.1, 0.1]
img(id: btn_l_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/left_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_l_2, r: tmp_rect, t:fit)

let tmp_rect = [o13.l - 0.1, o12.t + top - 0.05, 0.1, 0.1]
img(id: btn_r_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/right_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_r_2, r: tmp_rect, t:fit)

let tmp_rect = [o13.l, o13.t + top - 0.05, 0.1, 0.1]
img(id: btn_l_3_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/left_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_l_3, r: tmp_rect, t:fit)

let tmp_rect = [o14.l - 0.1, o13.t + top - 0.05, 0.1, 0.1]
img(id: btn_r_3_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/right_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_r_3, r: tmp_rect, t:fit)

let tmp_rect = [o14.l, o14.t + top - 0.05, 0.1, 0.1]
img(id: btn_l_4_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/left_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_l_4, r: tmp_rect, t:fit)

# btn_ud_123
let tmp_rect = [o12.l + 1 - 0.05, o12.t, 0.1, 0.1]
img(id: btn_u_1_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/up_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_u_1, r: tmp_rect, t:fit)

#>if(page_offset_y_1_ratio)
let tmp_rect = [o22.l + 1 - 0.05, o12.t - 0.1, 0.1, 0.1]
img(id: btn_d_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/down_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_d_2, r: tmp_rect, t:fit)

let tmp_rect = [o22.l + 1 - 0.05, o22.t, 0.1, 0.1]
img(id: btn_u_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/up_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_u_2, r: tmp_rect, t:fit)
#>fi

#>if(page_offset_y_2_ratio)
let tmp_rect = [o32.l + 1 - 0.05, o22.t - 0.1, 0.1, 0.1]
img(id: btn_d_3_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/down_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_d_3, r: tmp_rect, t:fit)
#>fi

其中按钮 id 最后的编号表示按钮所在的页面.

在定义了按钮后, 我们可以通过按钮的 last 属性计算出偏移量的值:

let animation_duration = 0.7
let animation_speed = 1 / animation_duration

let a = btn_r_1.last
let b = btn_l_2.last
# back and forth
let x = min((t - a) * animation_speed, 1)
let y = max(1 - (t - b) * animation_speed, 0)

# a > b ? x : y
let page_offset_x_1_ratio = (a > b) * x + (a <= b) * y

# easeInOutQuad
let x = 4 * page_offset_x_1_ratio * page_offset_x_1_ratio * page_offset_x_1_ratio
let y = 1 - (-2 * page_offset_x_1_ratio + 2) * (-2 * page_offset_x_1_ratio + 2) * (-2 * page_offset_x_1_ratio + 2) / 2
let page_offset_x_1_ratio_eased = (page_offset_x_1_ratio < 0.5) * x + (page_offset_x_1_ratio >= 0.5) * y
let page_offset_x_1 = page_offset_x_1_ratio_eased * -2

关于纵向切换的偏移量,我们可以通过类似的方法计算出.

这样, 我们就完成了页面切换效果.

完整的 UML 代码如下:

let animation_duration = 0.7
let animation_speed = 1 / animation_duration

global btn_r_1 = @btn
global btn_l_2 = @btn

global btn_r_2 = @btn
global btn_l_3 = @btn

global btn_r_3 = @btn
global btn_l_4 = @btn

global btn_r_3 = @btn
global btn_l_4 = @btn

global btn_u_1 = @btn
global btn_d_2 = @btn

global btn_u_2 = @btn
global btn_d_3 = @btn

# ---
let a = btn_r_1.last
let b = btn_l_2.last
# back and forth
let x = min((t - a) * animation_speed, 1)
let y = max(1 - (t - b) * animation_speed, 0)

# a > b ? x : y
let page_offset_x_1_ratio = (a > b) * x + (a <= b) * y

# easeInOutQuad
let x = 4 * page_offset_x_1_ratio * page_offset_x_1_ratio * page_offset_x_1_ratio
let y = 1 - (-2 * page_offset_x_1_ratio + 2) * (-2 * page_offset_x_1_ratio + 2) * (-2 * page_offset_x_1_ratio + 2) / 2
let page_offset_x_1_ratio_eased = (page_offset_x_1_ratio < 0.5) * x + (page_offset_x_1_ratio >= 0.5) * y
let page_offset_x_1 = page_offset_x_1_ratio_eased * -2
# ---

# ---
let a = btn_r_2.last
let b = btn_l_3.last
let x = min((t - a) * animation_speed, 1)
let y = max(1 - (t - b) * animation_speed, 0)
let page_offset_x_2_ratio = (a > b) * x + (a <= b) * y

let x = 4 * page_offset_x_2_ratio * page_offset_x_2_ratio * page_offset_x_2_ratio
let y = 1 - (-2 * page_offset_x_2_ratio + 2) * (-2 * page_offset_x_2_ratio + 2) * (-2 * page_offset_x_2_ratio + 2) / 2
let page_offset_x_2_ratio_eased = (page_offset_x_2_ratio < 0.5) * x + (page_offset_x_2_ratio >= 0.5) * y
let page_offset_x_2 = page_offset_x_2_ratio_eased * -2
# ---

# ---
let a = btn_r_3.last
let b = btn_l_4.last
let x = min((t - a) * animation_speed, 1)
let y = max(1 - (t - b) * animation_speed, 0)
let page_offset_x_3_ratio = (a > b) * x + (a <= b) * y

let x = 4 * page_offset_x_3_ratio * page_offset_x_3_ratio * page_offset_x_3_ratio
let y = 1 - (-2 * page_offset_x_3_ratio + 2) * (-2 * page_offset_x_3_ratio + 2) * (-2 * page_offset_x_3_ratio + 2) / 2
let page_offset_x_3_ratio_eased = (page_offset_x_3_ratio < 0.5) * x + (page_offset_x_3_ratio >= 0.5) * y
let page_offset_x_3 = page_offset_x_3_ratio_eased * -2
# ---

# ---
let a = btn_u_1.last
let b = btn_d_2.last
let x = min((t - a) * animation_speed, 1)
let y = max(1 - (t - b) * animation_speed, 0)
let page_offset_y_1_ratio = (a > b) * x + (a <= b) * y

let x = 4 * page_offset_y_1_ratio * page_offset_y_1_ratio * page_offset_y_1_ratio
let y = 1 - (-2 * page_offset_y_1_ratio + 2) * (-2 * page_offset_y_1_ratio + 2) * (-2 * page_offset_y_1_ratio + 2) / 2
let page_offset_y_1_ratio_eased = (page_offset_y_1_ratio < 0.5) * x + (page_offset_y_1_ratio >= 0.5) * y
let page_offset_y_1 = page_offset_y_1_ratio_eased * 2 * top
# ---

# ---
let a = btn_u_2.last
let b = btn_d_3.last
let x = min((t - a) * animation_speed, 1)
let y = max(1 - (t - b) * animation_speed, 0)
let page_offset_y_2_ratio = (a > b) * x + (a <= b) * y

let x = 4 * page_offset_y_2_ratio * page_offset_y_2_ratio * page_offset_y_2_ratio
let y = 1 - (-2 * page_offset_y_2_ratio + 2) * (-2 * page_offset_y_2_ratio + 2) * (-2 * page_offset_y_2_ratio + 2) / 2
let page_offset_y_2_ratio_eased = (page_offset_y_2_ratio < 0.5) * x + (page_offset_y_2_ratio >= 0.5) * y
let page_offset_y_2 = page_offset_y_2_ratio_eased * 2 * top
# ---

# o
let tmp_rect = [page_offset_x_1 + page_offset_x_2 + page_offset_x_3, page_offset_y_1 + page_offset_y_2, 0.1, 0.1]
img(id: o11, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

let tmp_rect = [o11.l + 2, o11.t, 0.1, 0.1]
img(id: o12, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

let tmp_rect = [o11.l + 4, o11.t, 0.1, 0.1]
img(id: o13, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

let tmp_rect = [o11.l + 6, o11.t, 0.1, 0.1]
img(id: o14, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)

#>if(page_offset_y_1_ratio)
let tmp_rect = [o12.l, o11.t - 2 * top, 0.1, 0.1]
img(id: o22, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)
#>fi

#>if(page_offset_y_2_ratio)
let tmp_rect = [o12.l, o11.t - 4 * top, 0.1, 0.1]
img(id: o32, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/blank.png", r: tmp_rect, t:fit)
#>fi

# btn_lr_1234
let tmp_rect = [o12.l - 0.1, o11.t + top - 0.05, 0.1, 0.1]
img(id: btn_r_1_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/right_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_r_1, r: tmp_rect, t:fit)

let tmp_rect = [o12.l, o12.t + top - 0.05, 0.1, 0.1]
img(id: btn_l_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/left_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_l_2, r: tmp_rect, t:fit)

let tmp_rect = [o13.l - 0.1, o12.t + top - 0.05, 0.1, 0.1]
img(id: btn_r_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/right_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_r_2, r: tmp_rect, t:fit)

let tmp_rect = [o13.l, o13.t + top - 0.05, 0.1, 0.1]
img(id: btn_l_3_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/left_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_l_3, r: tmp_rect, t:fit)

let tmp_rect = [o14.l - 0.1, o13.t + top - 0.05, 0.1, 0.1]
img(id: btn_r_3_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/right_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_r_3, r: tmp_rect, t:fit)

let tmp_rect = [o14.l, o14.t + top - 0.05, 0.1, 0.1]
img(id: btn_l_4_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/left_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_l_4, r: tmp_rect, t:fit)

# btn_ud_123
let tmp_rect = [o12.l + 1 - 0.05, o12.t, 0.1, 0.1]
img(id: btn_u_1_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/up_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_u_1, r: tmp_rect, t:fit)

#>if(page_offset_y_1_ratio)
let tmp_rect = [o22.l + 1 - 0.05, o12.t - 0.1, 0.1, 0.1]
img(id: btn_d_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/down_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_d_2, r: tmp_rect, t:fit)

let tmp_rect = [o22.l + 1 - 0.05, o22.t, 0.1, 0.1]
img(id: btn_u_2_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/up_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_u_2, r: tmp_rect, t:fit)
#>fi

#>if(page_offset_y_2_ratio)
let tmp_rect = [o32.l + 1 - 0.05, o22.t - 0.1, 0.1, 0.1]
img(id: btn_d_3_bkg, url: "https://teamflos.github.io/phira-docs/assets/uml/advanced/page_switch/down_arrow.png", r: tmp_rect, t:fit)
btn(id: btn_d_3, r: tmp_rect, t:fit)
#>fi

let $h = 2 * top - 0.02