FXL: add zoom setting

The value of the `zoom` attribute can be either `"fit-page"` (default),
`"fit-width"`, or a number.
This commit is contained in:
John Factotum
2024-10-11 06:41:32 +08:00
parent 7cbc36b489
commit b82ec0b294
+28 -9
View File
@@ -30,6 +30,7 @@ const getViewport = (doc, viewport) => {
} }
export class FixedLayout extends HTMLElement { export class FixedLayout extends HTMLElement {
static observedAttributes = ['zoom']
#root = this.attachShadow({ mode: 'closed' }) #root = this.attachShadow({ mode: 'closed' })
#observer = new ResizeObserver(() => this.#render()) #observer = new ResizeObserver(() => this.#render())
#spreads #spreads
@@ -41,6 +42,7 @@ export class FixedLayout extends HTMLElement {
#right #right
#center #center
#side #side
#zoom
constructor() { constructor() {
super() super()
@@ -52,10 +54,20 @@ export class FixedLayout extends HTMLElement {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
overflow: auto;
}`) }`)
this.#observer.observe(this) this.#observer.observe(this)
} }
attributeChangedCallback(name, _, value) {
switch (name) {
case 'zoom':
this.#zoom = value !== 'fit-width' && value !== 'fit-page'
? parseFloat(value) : value
this.#render()
break
}
}
async #createFrame({ index, src: srcOption }) { async #createFrame({ index, src: srcOption }) {
const srcOptionIsString = typeof srcOption === 'string' const srcOptionIsString = typeof srcOption === 'string'
const src = srcOptionIsString ? srcOption : srcOption?.src const src = srcOptionIsString ? srcOption : srcOption?.src
@@ -102,15 +114,20 @@ export class FixedLayout extends HTMLElement {
const blankWidth = left.width ?? right.width const blankWidth = left.width ?? right.width
const blankHeight = left.height ?? right.height const blankHeight = left.height ?? right.height
const scale = portrait || this.#center const scale = typeof this.#zoom === 'number' && !isNaN(this.#zoom)
? Math.min( ? this.#zoom
width / (target.width ?? blankWidth), : this.#zoom === 'fit-width' ? (portrait || this.#center
height / (target.height ?? blankHeight)) ? width / (target.width ?? blankWidth)
: Math.min( : width / ((left.width ?? blankWidth) + (right.width ?? blankWidth)))
width / ((left.width ?? blankWidth) + (right.width ?? blankWidth)), : (portrait || this.#center
height / Math.max( ? Math.min(
left.height ?? blankHeight, width / (target.width ?? blankWidth),
right.height ?? blankHeight)) height / (target.height ?? blankHeight))
: Math.min(
width / ((left.width ?? blankWidth) + (right.width ?? blankWidth)),
height / Math.max(
left.height ?? blankHeight,
right.height ?? blankHeight)))
const transform = frame => { const transform = frame => {
let { element, iframe, width, height, blank, onZoom } = frame let { element, iframe, width, height, blank, onZoom } = frame
@@ -128,6 +145,8 @@ export class FixedLayout extends HTMLElement {
height: `${(height ?? blankHeight) * scale}px`, height: `${(height ?? blankHeight) * scale}px`,
overflow: 'hidden', overflow: 'hidden',
display: 'block', display: 'block',
flexShrink: '0',
marginBlock: 'auto',
}) })
if (portrait && frame !== target) { if (portrait && frame !== target) {
element.style.display = 'none' element.style.display = 'none'