mirror of
https://github.com/ApfelTeeSaft/LiveSplitOne.git
synced 2026-09-03 11:53:24 +00:00
Switch to Canvas Rendering
This switches the rendering of the layout from using HTML and CSS to using a canvas (technically it's two). This not only should improve the performance but also brings the rendering in line with our native renderers, enabling new features such as vertical resizing and horizontal layouts. This also removes a lot of code specific to the HTML rendering and thus greatly simplifies the codebase. There is one slight regression in that the layout editor doesn't allow clicking and dragging the individual components directly on the layout anymore. This is however something we can explore directly in `livesplit-core` in the future, so other frontends can benefit from it as well.
This commit is contained in:
@@ -1,6 +0,0 @@
|
||||
.abbreviated {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
@import 'Time';
|
||||
@import 'variables';
|
||||
|
||||
.detailed-timer {
|
||||
position: relative;
|
||||
|
||||
@include time;
|
||||
|
||||
.detailed-timer-left-side {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
top: 0;
|
||||
left: $side-padding;
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
|
||||
.detailed-timer-icon-container {
|
||||
height: 100%;
|
||||
padding: $vertical-padding $side-padding;
|
||||
margin-right: $side-padding;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.detailed-timer-icon-inner-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
vertical-align: center;
|
||||
|
||||
.detailed-timer-icon {
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detailed-timer-left-side-text {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.detailed-timer-segment-name {
|
||||
position: absolute;
|
||||
top: $vertical-padding;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.detailed-timer-comparisons {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: $vertical-padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.graph {
|
||||
display: block;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
@import 'Time';
|
||||
@import 'variables';
|
||||
|
||||
.key-value {
|
||||
height: $default-component-height;
|
||||
padding: 0 $side-padding;
|
||||
display: flex;
|
||||
|
||||
@include time;
|
||||
|
||||
&.key-value-two-rows {
|
||||
height: $two-row-height;
|
||||
padding-top: $vertical-padding;
|
||||
padding-bottom: $vertical-padding;
|
||||
flex-wrap: wrap;
|
||||
align-items: stretch;
|
||||
|
||||
.key-value-value {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.key-value-center {
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
.key-value-key {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
&.key-value-left-right {
|
||||
.key-value-key {
|
||||
padding-right: $side-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.key-value-key {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.key-value-value {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
|
||||
.key-value-value-inner {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
-15
@@ -1,27 +1,42 @@
|
||||
@import 'variables';
|
||||
@import 'Font';
|
||||
|
||||
.layout {
|
||||
font-family: "fira", sans-serif;
|
||||
font-size: $default-font-size;
|
||||
text-shadow: 2px 2px 2px rgba(0, 0, 0, 0.5);
|
||||
position: relative;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
.resizable-layout {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
height: 100% !important;
|
||||
top: 0;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
|
||||
.resizable-handle {
|
||||
.react-resizable {
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
}
|
||||
|
||||
.resizable-handle-east {
|
||||
cursor: e-resize;
|
||||
bottom: -4px;
|
||||
right: -4px;
|
||||
right: -10px;
|
||||
bottom: 10px;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.resizable-handle-south {
|
||||
cursor: s-resize;
|
||||
bottom: -10px;
|
||||
left: 0;
|
||||
right: 10px;
|
||||
position: absolute;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.resizable-handle-south-east {
|
||||
cursor: se-resize;
|
||||
bottom: -10px;
|
||||
right: -10px;
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
@import 'variables';
|
||||
|
||||
.separator {
|
||||
background-color: hsla(0, 0%, 43%, 1);
|
||||
height: $thick-separator-width;
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
@use 'sass:math';
|
||||
|
||||
@import "Time";
|
||||
@import 'variables';
|
||||
|
||||
$split-column-width: $default-line-height * 3;
|
||||
$split-label-height: $default-component-height - $thick-separator-width;
|
||||
$split-icon-size: $default-component-height - $vertical-padding * 2;
|
||||
$split-icon-two-row-size: $two-row-height - $vertical-padding * 2;
|
||||
|
||||
.splits {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
.split {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: $default-component-height;
|
||||
|
||||
@include time;
|
||||
|
||||
&.two-rows {
|
||||
height: $two-row-height;
|
||||
|
||||
.split-rows {
|
||||
flex-wrap: wrap;
|
||||
padding-top: $vertical-padding;
|
||||
padding-bottom: $vertical-padding;
|
||||
|
||||
.split-row {
|
||||
height: initial;
|
||||
|
||||
&.split-second-row {
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.split-icon-container {
|
||||
width: $split-icon-two-row-size;
|
||||
}
|
||||
}
|
||||
|
||||
.split-icon-container {
|
||||
padding: $vertical-padding $side-padding;
|
||||
width: $split-icon-size;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.split-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
filter: drop-shadow(2px 2px 1px rgba(0, 0, 0, 0.3));
|
||||
}
|
||||
}
|
||||
|
||||
.split-icon-container-empty {
|
||||
padding-right: $side-padding;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.split-rows {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
|
||||
.split-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
&.split-first-row,
|
||||
.split-name {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&.split-second-row,
|
||||
.split-time {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.split-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
overflow: hidden;
|
||||
padding: 0 $side-padding;
|
||||
padding-left: 0;
|
||||
height: 100%;
|
||||
|
||||
.split-name-inner {
|
||||
padding: 0;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.split-time {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 $side-padding;
|
||||
padding-left: 0;
|
||||
height: 100%;
|
||||
|
||||
&.split-time-full {
|
||||
width: $split-column-width;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.split-time-inner {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.split-label {
|
||||
height: $split-label-height;
|
||||
}
|
||||
|
||||
.current-split-background,
|
||||
.split-borders {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.split-borders {
|
||||
border-bottom-width: $thin-separator-width;
|
||||
border-top-width: $thin-separator-width;
|
||||
border-bottom-style: solid;
|
||||
border-top-style: solid;
|
||||
top: math.div(-$thick-separator-width, 2);
|
||||
height: calc(100% + #{math.div($thick-separator-width, 2)});
|
||||
|
||||
&.separator-above {
|
||||
border-top-width: $thick-separator-width;
|
||||
border-top-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@mixin time {
|
||||
.time {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
.timer {
|
||||
will-change: transform;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
@import "variables";
|
||||
|
||||
$game-icon-size: $two-row-height - $vertical-padding * 2;
|
||||
|
||||
.title {
|
||||
height: $two-row-height;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding-top: $vertical-padding;
|
||||
padding-bottom: $vertical-padding;
|
||||
|
||||
.game-icon-container {
|
||||
max-width: $game-icon-size;
|
||||
max-height: $game-icon-size;
|
||||
padding: $vertical-padding 0;
|
||||
padding-left: $side-padding;
|
||||
flex-shrink: 0;
|
||||
|
||||
.title-icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.run-info {
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
|
||||
.title-game {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 50%;
|
||||
padding: 0 $side-padding;
|
||||
|
||||
&.centered .abbreviated {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.lower-row {
|
||||
display: flex;
|
||||
position: relative;
|
||||
height: 50%;
|
||||
|
||||
&.centered {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&.one-line {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.title-category {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
padding: 0 $side-padding;
|
||||
|
||||
&.centered .abbreviated {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.title-attempts,
|
||||
.title-attempts-invisible {
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.one-line {
|
||||
height: 50%;
|
||||
align-self: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.title-attempts {
|
||||
justify-content: flex-end;
|
||||
padding-right: $side-padding;
|
||||
}
|
||||
|
||||
.title-attempts-invisible {
|
||||
justify-content: flex-start;
|
||||
padding-left: $side-padding;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user