Added zoom UI

This commit is contained in:
Tamius Han 2025-01-12 23:25:20 +01:00
parent 42ac51f1e9
commit 23ea9e77c4
3 changed files with 186 additions and 47 deletions

View File

@ -76,6 +76,29 @@
</GhettoContextMenuOption>
</slot>
</GhettoContextMenu>
<GhettoContextMenu alignment="right">
<template v-slot:activator>
Zoom
</template>
<slot>
<GhettoContextMenuOption
v-for="(command, index) of settings?.active.commands.zoom"
:key="index"
:label="command.label"
:shortcut="getKeyboardShortcutLabel(command)"
@click="execAction(command)"
>
</GhettoContextMenuOption>
<GhettoContextMenuItem
:disableHover="true"
>
<ZoomControl
:settings="settings"
:eventBus="eventBus"
/>
</GhettoContextMenuItem>
</slot>
</GhettoContextMenu>
<GhettoContextMenu alignment="right">
<template v-slot:activator>
<div class="context-item">
@ -211,6 +234,7 @@ export default {
AlignmentOptionsControlComponent,
SupportLevelIndicator,
TriggerZoneEditor,
ZoomControl,
},
mixins: [
UIProbeMixin,

View File

@ -0,0 +1,112 @@
<template>
<div>
Custom zoom
</div>
<div class="top-label">Zoom:</div>
<div class="input range-input">
<input
type="range"
class="slider"
min="0"
max="3"
step="0.01"
/>
<input
/>
</div>
<template v-if="true">
<div class="top-label">Vertical zoom:</div>
<div class="input range-input">
<input
type="range"
class="slider"
min="0"
max="3"
step="0.01"
/>
<input
/>
</div>
</template>
<div><input type="checkbox"/> Control vertical and horizontal zoom independently.</div>
</template>
<script>
export default {
data() {
return {
zoomAspectRatioLocked: true,
zoom: {
x: 0,
y: 0
},
// TODO: this should be mixin?
resizerConfig: {
crop: null,
stretch: null,
zoom: null,
pan: null
}
}
},
mixins: [
],
props: [
'settings', // required for buttons and actions, which are global
'eventBus'
],
methods: {
getZoomForDisplay(axis) {
// zoom is internally handled logarithmically, because we want to have x0.5, x1, x2, x4 ... magnifications
// spaced out at regular intervals. When displaying, we need to convert that to non-logarithmic values.
return `${(Math.pow(2, this.zoom[axis]) * 100).toFixed()}%`
},
toggleZoomAr() {
this.zoomAspectRatioLocked = !this.zoomAspectRatioLocked;
},
resetZoom() {
// we store zoom logarithmically on this component
this.zoom = {x: 0, y: 0};
// we do not use logarithmic zoom elsewhere
// todo: replace eventBus with postMessage to parent
// this.eventBus.send('set-zoom', {zoom: 1, axis: 'y'});
// this.eventBus.send('set-zoom', {zoom: 1, axis: 'x'});
this.eventBus?.sendToTunnel('set-zoom', {zoom: 1, axis: 'y'});
this.eventBus?.sendToTunnel('set-zoom', {zoom: 1, axis: 'x'});
},
changeZoom(newZoom, axis) {
// we store zoom logarithmically on this compnent
if (!axis) {
this.zoom.x = newZoom;
} else {
this.zoom[axis] = newZoom;
}
// we do not use logarithmic zoom elsewhere, therefore we need to convert
newZoom = Math.pow(2, newZoom);
if (this.zoomAspectRatioLocked) {
this.eventBus?.sendToTunnel('set-zoom', {zoom: newZoom, axis: 'y'});
this.eventBus?.sendToTunnel('set-zoom', {zoom: newZoom, axis: 'x'});
} else {
this.eventBus?.sendToTunnel('set-zoom', {zoom: newZoom, axis: axis ?? 'x'});
}
},
}
}
</script>
<style lang="scss" src="@csui/res/css/flex.scss" scoped></style>
<style lang="scss" src="@csui/src/res-common/panels.scss" scoped module></style>
<style lang="scss" src="@csui/src/res-common/common.scss" scoped module></style>

View File

@ -62,6 +62,56 @@ button, .button {
padding: 0.5rem 2rem;
}
.input, .range-input {
background-color: rgba($blackBg, $normalTransparentOpacity);
border: 1px solid transparent;
border-bottom: 1px solid rgba(255,255,255,0.5);
padding-top: 0.25rem;
padding-bottom: 0.25rem;
position: relative;
&:active, &:focus, &:focus-within {
border-bottom: 1px solid rgba($primary, 0.5);
}
input {
width: 100%;
outline: none;
border: 1px solid transparent;
background-color: transparent;
color: #fff;
}
.unit {
position: absolute;
right: 0px;
pointer-events: none;
opacity: 0.69;
font-size: 0.8rem;
top: 0;
transform: translateY(69%);
}
}
.range-input {
display: flex;
flex-direction: row;
* {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
input {
max-width: 5rem;
}
input[type=range] {
max-width: none;
}
}
.field {
display: flex;
flex-direction: row;
@ -86,53 +136,6 @@ button, .button {
.input, .range-input {
flex: 0 0 70%;
max-width: 24rem;
background-color: rgba($blackBg, $normalTransparentOpacity);
border: 1px solid transparent;
border-bottom: 1px solid rgba(255,255,255,0.5);
padding-top: 0.25rem;
padding-bottom: 0.25rem;
position: relative;
&:active, &:focus, &:focus-within {
border-bottom: 1px solid rgba($primary, 0.5);
}
input {
width: 100%;
outline: none;
border: 1px solid transparent;
background-color: transparent;
color: #fff;
}
.unit {
position: absolute;
right: 0px;
pointer-events: none;
opacity: 0.69;
font-size: 0.8rem;
top: 0;
transform: translateY(69%);
}
}
.range-input {
display: flex;
flex-direction: row;
* {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
input {
max-width: 5rem;
}
input[type=range] {
max-width: none;
}
}
.hint {