cinera.web: Fix player sizing and auto-scrolling

• Video size may be based on the height if the width-based is too tall
• Auto-scrolling improvements:
    • It now cannot oscillate
    • It doesn't happen at all if scrolled to the very top / bottom

Thanks to @Freak_ on freenode for the report
This commit is contained in:
Matt Mascarenhas 2021-02-10 22:41:46 +00:00
parent 2d26562301
commit 33f6186aa1
5 changed files with 82 additions and 57 deletions

View File

@ -23,7 +23,7 @@ typedef struct
version CINERA_APP_VERSION = { version CINERA_APP_VERSION = {
.Major = 0, .Major = 0,
.Minor = 8, .Minor = 8,
.Patch = 5 .Patch = 6
}; };
#include <stdarg.h> // NOTE(matt): varargs #include <stdarg.h> // NOTE(matt): varargs

View File

@ -50,7 +50,7 @@ var CineraProps = {
FlexDirection: null, FlexDirection: null,
JustifyContent: null, JustifyContent: null,
O: null, O: null,
D: IsMobile() ? devices.MOBILE : devices.DESKTOP, IsMobile: IsMobile(),
ScrollX: null, ScrollX: null,
ScrollY: null, ScrollY: null,
}; };
@ -173,7 +173,7 @@ if(titleBar)
} }
viewsMenu = titleBar.querySelector(".views"); viewsMenu = titleBar.querySelector(".views");
if(viewsMenu && CineraProps.D !== devices.MOBILE) if(viewsMenu && !CineraProps.IsMobile)
{ {
menuState.push(viewsMenu); menuState.push(viewsMenu);
var viewsContainer = viewsMenu.querySelector(".views_container"); var viewsContainer = viewsMenu.querySelector(".views_container");
@ -280,7 +280,7 @@ var MobileCineraContentRule = GetOrSetRule(MobileCineraContentRuleSelector);
var MenuContainerRuleSelector = ".cineraMenus > .menu .quotes_container, .cineraMenus > .menu .references_container, .cineraMenus > .menu .filter_container, .cineraMenus > .menu .views_container, .cineraMenus > .menu .link_container, .cineraMenus > .menu .credits_container"; var MenuContainerRuleSelector = ".cineraMenus > .menu .quotes_container, .cineraMenus > .menu .references_container, .cineraMenus > .menu .filter_container, .cineraMenus > .menu .views_container, .cineraMenus > .menu .link_container, .cineraMenus > .menu .credits_container";
var MenuContainerRule = GetOrSetRule(MenuContainerRuleSelector); var MenuContainerRule = GetOrSetRule(MenuContainerRuleSelector);
if(CineraProps.D == devices.MOBILE) if(CineraProps.IsMobile)
{ {
InitMobileStyle(); InitMobileStyle();
} }
@ -292,7 +292,7 @@ else
var player = new Player(playerContainer, onRefChanged); var player = new Player(playerContainer, onRefChanged);
if(CineraProps.D == devices.MOBILE) if(CineraProps.IsMobile)
{ {
ConnectMobileControls(player); ConnectMobileControls(player);
} }

View File

@ -483,13 +483,21 @@ Player.prototype.updateSize = function() {
var width = 0; var width = 0;
var height = 0; var height = 0;
CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile); CineraProps.O = GetRealOrientation(orientations.LANDSCAPE_LEFT, CineraProps.IsMobile);
if(CineraProps.D === devices.DESKTOP) if(!CineraProps.IsMobile)
{ {
var VisibleArea = GetWindowDim(false);
var AvailableHeight = VisibleArea.Y - titleBar.offsetHeight;
width = this.videoContainer.offsetWidth; width = this.videoContainer.offsetWidth;
height = width / 16 * 9; // TODO(matt): Get the aspect ratio from the video itself? height = width / 16 * 9; // TODO(matt): Get the aspect ratio from the video itself?
if(height > AvailableHeight)
{
height = AvailableHeight;
width = height / 9 * 16;
}
this.markersContainer.style.height = height + "px"; this.markersContainer.style.height = height + "px";
var MenuMaxHeight = cinera.offsetHeight - titleBar.offsetHeight - 4; var VacantPixelsBelowMenus = 4;
var MenuMaxHeight = cinera.offsetHeight - titleBar.offsetHeight - VacantPixelsBelowMenus;
MenuContainerRule.style.maxHeight = MenuMaxHeight + "px"; MenuContainerRule.style.maxHeight = MenuMaxHeight + "px";
} }
else else

View File

@ -44,22 +44,30 @@ DeriveReliableWindowDimensions()
} }
function function
GetRealOrientation(PreferredLandscape, IsMobile) GetWindowDim(IsMobile)
{ {
var Result = window.orientation; var Result = {
var WindowDim = {
X: null, X: null,
Y: null, Y: null,
}; };
if(IsMobile) if(IsMobile)
{ {
WindowDim = DeriveReliableWindowDimensions(); Result = DeriveReliableWindowDimensions();
} }
else else
{ {
WindowDim.X = document.body.clientWidth; Result.X = document.body.clientWidth;
WindowDim.Y = window.innerHeight; Result.Y = window.innerHeight;
} }
return Result;
}
function
GetRealOrientation(PreferredLandscape, IsMobile)
{
var Result = window.orientation;
var WindowDim = GetWindowDim(IsMobile);
if(WindowDim.Y > WindowDim.X) if(WindowDim.Y > WindowDim.X)
{ {
Result = orientations.PORTRAIT; Result = orientations.PORTRAIT;
@ -262,52 +270,73 @@ GetOrSetRule(SelectorText)
return Result; return Result;
} }
function IsInRangeEx(Min, N, Max)
{
return N > Min && N < Max;
}
/* Auto-scrolling */ /* Auto-scrolling */
var LastScrollYPos = 0; var LastScrollYPos = 0;
var ScrollTicking = false; var ScrollTicking = false;
var ScrollerFunction; var ScrollerFunction;
var ScrollCondition; var ScrollCondition;
function ScrollTo(Element, ScrollPos, StickyObscuringElement) { function ScrollTo(Element, ScrollPos, IsMobile, StickyObscuringElement) {
var BoundingRect = Element.getBoundingClientRect(); var ScrolledToTop = ScrollPos == 0;
var Height = BoundingRect.height; var ScrolledToBottom = (window.innerHeight + Math.ceil(window.pageYOffset)) >= document.body.scrollHeight;
var PercentageOfInView = 89; if(!ScrolledToTop || !ScrolledToBottom)
var GatherableHeight = Height * (1 - PercentageOfInView / 100);
var ScrollY = BoundingRect.top;
var YOffsetFromPage = getElementYOffsetFromPage(Element);
var DesiredScroll = null;
var Ceiling = StickyObscuringElement ? StickyObscuringElement.offsetHeight : 0;
if(ScrollY < Ceiling)
{ {
if(ScrollY < 0) { ScrollY = -ScrollY; } var Ceiling = StickyObscuringElement ? StickyObscuringElement.offsetHeight : 0;
GatherableHeight -= Ceiling; var VisibleArea = GetWindowDim(IsMobile);
if(ScrollY <= GatherableHeight) VisibleArea.Y -= Ceiling;
var PercentageOfVisibleHeightToGather = 5;
var GatherableHeight = VisibleArea.Y * PercentageOfVisibleHeightToGather / 100;
var BoundingRect = Element.getBoundingClientRect();
var ElementTop = BoundingRect.top - Ceiling;
var ElementBottom = ElementTop + BoundingRect.height;
var UpperProtrusion = -ElementTop;
var LowerProtrusion = ElementBottom - VisibleArea.Y;
var DesiredScroll = null;
var YOffsetFromPage = getElementYOffsetFromPage(Element);
if(IsInRangeEx(0, UpperProtrusion, GatherableHeight))
{ {
DesiredScroll = YOffsetFromPage - Ceiling; if(!ScrolledToBottom)
{
DesiredScroll = YOffsetFromPage - Ceiling;
}
} }
} else if(IsInRangeEx(0, LowerProtrusion, GatherableHeight))
else
{
var LowerProtrusion = ScrollY - (window.innerHeight - Height);
if(LowerProtrusion > 0 && LowerProtrusion <= GatherableHeight)
{ {
DesiredScroll = ScrollPos + LowerProtrusion; if(!ScrolledToTop)
{
if(IsInRangeEx(0, UpperProtrusion + LowerProtrusion, GatherableHeight))
{
DesiredScroll = YOffsetFromPage - Ceiling;
}
else
{
DesiredScroll = ScrollPos + LowerProtrusion;
}
}
} }
}
if(DesiredScroll !== null) if(DesiredScroll !== null && DesiredScroll != ScrollPos)
{ {
window.scrollTo({ window.scrollTo({
top: DesiredScroll, top: DesiredScroll,
behavior: "smooth" behavior: "smooth"
}); });
}
} }
} }
function function
InitScrollEventListener(Element, StickyObscuringElement) InitScrollEventListener(Element, IsMobile, StickyObscuringElement)
{ {
window.addEventListener('scroll', function() { window.addEventListener('scroll', function() {
if(ScrollCondition == undefined || ScrollCondition == true) if(ScrollCondition == undefined || ScrollCondition == true)
@ -317,7 +346,7 @@ InitScrollEventListener(Element, StickyObscuringElement)
if (!ScrollTicking) { if (!ScrollTicking) {
window.requestAnimationFrame(function() { window.requestAnimationFrame(function() {
clearTimeout(ScrollerFunction); clearTimeout(ScrollerFunction);
ScrollerFunction = setTimeout(ScrollTo, 2000, Element, LastScrollYPos, StickyObscuringElement); ScrollerFunction = setTimeout(ScrollTo, 2000, Element, LastScrollYPos, IsMobile, StickyObscuringElement);
ScrollTicking = false; ScrollTicking = false;
}); });

View File

@ -2938,19 +2938,7 @@ ComputeOptimalGridSize()
Y: null, Y: null,
}; };
var WindowDim = { var WindowDim = GetWindowDim(CineraProps.IsMobile);
X: null,
Y: null,
};
if(CineraProps.IsMobile)
{
WindowDim = DeriveReliableWindowDimensions();
}
else
{
WindowDim.X = document.body.clientWidth;
WindowDim.Y = window.innerHeight;
}
var DimReduction = { var DimReduction = {
X: 0, X: 0,
Y: Nav.Controls.Header.offsetHeight, Y: Nav.Controls.Header.offsetHeight,