one-screen-scale 1.0.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +181 -38
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +78 -2
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/react.cjs.js +1 -1
- package/dist/react.cjs.js.map +1 -1
- package/dist/react.d.ts +30 -0
- package/dist/react.esm.js +1 -1
- package/dist/react.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/baseStyles.js +91 -0
- package/src/compensate.js +320 -0
- package/src/composables.js +69 -67
- package/src/core.js +185 -24
- package/src/directives.js +126 -16
- package/src/index.d.ts +78 -2
- package/src/index.js +21 -2
- package/src/react.d.ts +30 -0
- package/src/react.js +110 -17
package/src/index.js
CHANGED
|
@@ -4,11 +4,30 @@ export {
|
|
|
4
4
|
applyScale,
|
|
5
5
|
getPageScale,
|
|
6
6
|
getInverseScale,
|
|
7
|
-
createScaler
|
|
7
|
+
createScaler,
|
|
8
|
+
applyBaseStyles,
|
|
9
|
+
removeBaseStyles,
|
|
10
|
+
applyCompensateStyles,
|
|
11
|
+
removeCompensateStyles,
|
|
12
|
+
ensureBaseStyleSheet,
|
|
13
|
+
BASE_CLASS,
|
|
14
|
+
SCALE_CHANGE_EVENT,
|
|
8
15
|
} from './core.js'
|
|
9
16
|
|
|
17
|
+
// ---- 组件反缩放补偿(仅抵消页面 scale) ----
|
|
18
|
+
export {
|
|
19
|
+
resolvePageScale,
|
|
20
|
+
applyCompensateTransform,
|
|
21
|
+
clearCompensateTransform,
|
|
22
|
+
resizeCanvasUnder,
|
|
23
|
+
resizeEchartsUnder,
|
|
24
|
+
createCompensate,
|
|
25
|
+
setCompensateEcharts,
|
|
26
|
+
CANVAS_RESIZE_EVENT,
|
|
27
|
+
} from './compensate.js'
|
|
28
|
+
|
|
10
29
|
// ---- Vue 指令 ----
|
|
11
|
-
export { vFitScreen } from './directives.js'
|
|
30
|
+
export { vFitScreen, vCompensate, vFitCompensate } from './directives.js'
|
|
12
31
|
|
|
13
32
|
// ---- Vue Composable ----
|
|
14
33
|
export { useFitScreen } from './composables.js'
|
package/src/react.d.ts
CHANGED
|
@@ -7,6 +7,25 @@ export interface ScalerOptions {
|
|
|
7
7
|
visualWidth?: number
|
|
8
8
|
origin?: string
|
|
9
9
|
autoResize?: boolean
|
|
10
|
+
/**
|
|
11
|
+
* 是否自动注入模式所需基础样式(默认 true)
|
|
12
|
+
* - contain: width:100vw; min-height:100vh/100dvh
|
|
13
|
+
* - fixed-width: 暂不注入(宽高由 refresh 行内补偿)
|
|
14
|
+
*/
|
|
15
|
+
injectBaseStyles?: boolean
|
|
16
|
+
/**
|
|
17
|
+
* 内容尺寸变化时自动重算(默认 true)
|
|
18
|
+
*/
|
|
19
|
+
observeContent?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface CompensateOptions {
|
|
23
|
+
/** 补偿后通知子树 canvas 重绘(ECharts / Chart.js / 自定义事件) */
|
|
24
|
+
resizeCanvas?: boolean
|
|
25
|
+
/** @deprecated 请用 resizeCanvas */
|
|
26
|
+
echarts?: boolean | { getInstanceByDom?: (el: Element) => { resize: (opts?: object) => void } | undefined }
|
|
27
|
+
echartsLib?: { getInstanceByDom?: (el: Element) => { resize: (opts?: object) => void } | undefined }
|
|
28
|
+
onRefresh?: (detail: { scale: number; inverseScale: number; el: HTMLElement }) => void
|
|
10
29
|
}
|
|
11
30
|
|
|
12
31
|
export function useFitScreen(
|
|
@@ -17,3 +36,14 @@ export function useFitScreen(
|
|
|
17
36
|
inverseScale: number
|
|
18
37
|
refresh: () => void
|
|
19
38
|
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 对应 Vue `v-compensate`:抵消页面 scale 的组件反缩放。
|
|
42
|
+
* 节点晚于首次 effect 出现时会自动补挂;`resizeCanvas` 变化会重建监听。
|
|
43
|
+
*/
|
|
44
|
+
export function useCompensate(
|
|
45
|
+
targetRef: RefObject<HTMLElement | null> | HTMLElement,
|
|
46
|
+
options?: CompensateOptions
|
|
47
|
+
): {
|
|
48
|
+
refresh: () => void
|
|
49
|
+
}
|
package/src/react.js
CHANGED
|
@@ -1,36 +1,86 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* React
|
|
2
|
+
* React hooks
|
|
3
3
|
* useFitScreen(ref, options) → { scale, inverseScale, refresh }
|
|
4
|
+
* useCompensate(ref, options) → { refresh } // 对应 Vue v-compensate
|
|
4
5
|
*/
|
|
5
6
|
import { useRef, useState, useEffect, useCallback } from 'react'
|
|
6
|
-
import { createScaler } from './core.js'
|
|
7
|
+
import { createScaler, SCALE_CHANGE_EVENT } from './core.js'
|
|
8
|
+
import { createCompensate } from './compensate.js'
|
|
9
|
+
|
|
10
|
+
function resolveElement(targetRef) {
|
|
11
|
+
if (!targetRef) return null
|
|
12
|
+
if (typeof HTMLElement !== 'undefined' && targetRef instanceof HTMLElement) return targetRef
|
|
13
|
+
if (targetRef.current instanceof HTMLElement) return targetRef.current
|
|
14
|
+
if (targetRef.value instanceof HTMLElement) return targetRef.value
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** ref 第一次 effect 时可能还是空的,等到节点出现再挂。卸载时停掉等待 */
|
|
19
|
+
function waitForElement(targetRef, onReady) {
|
|
20
|
+
let raf = 0
|
|
21
|
+
let timer = 0
|
|
22
|
+
let frames = 0
|
|
23
|
+
let settled = false
|
|
24
|
+
|
|
25
|
+
const finish = () => {
|
|
26
|
+
settled = true
|
|
27
|
+
cancelAnimationFrame(raf)
|
|
28
|
+
clearInterval(timer)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const tick = () => {
|
|
32
|
+
if (settled) return
|
|
33
|
+
const el = resolveElement(targetRef)
|
|
34
|
+
if (el) {
|
|
35
|
+
finish()
|
|
36
|
+
onReady(el)
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
frames += 1
|
|
40
|
+
if (frames < 60) raf = requestAnimationFrame(tick)
|
|
41
|
+
else if (!timer) timer = setInterval(tick, 200)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
tick()
|
|
45
|
+
return finish
|
|
46
|
+
}
|
|
7
47
|
|
|
8
48
|
export function useFitScreen(targetRef, options = {}) {
|
|
9
49
|
const [scale, setScale] = useState(1)
|
|
10
50
|
const [inverseScale, setInverseScale] = useState(1)
|
|
11
51
|
const scalerRef = useRef(null)
|
|
52
|
+
const optionsRef = useRef(options)
|
|
53
|
+
optionsRef.current = options
|
|
12
54
|
|
|
13
55
|
useEffect(() => {
|
|
14
|
-
|
|
15
|
-
|
|
56
|
+
let detach = () => {}
|
|
57
|
+
let disposed = false
|
|
16
58
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const onResize = () => {
|
|
24
|
-
const s = scaler.getScale()
|
|
59
|
+
const cancelWait = waitForElement(targetRef, (el) => {
|
|
60
|
+
if (disposed) return
|
|
61
|
+
const scaler = createScaler(el, optionsRef.current)
|
|
62
|
+
scalerRef.current = scaler
|
|
63
|
+
const s = scaler.start()
|
|
25
64
|
setScale(s)
|
|
26
65
|
setInverseScale(s > 0 ? 1 / s : 1)
|
|
27
|
-
|
|
28
|
-
|
|
66
|
+
|
|
67
|
+
const onScale = (event) => {
|
|
68
|
+
if (event.detail?.el !== el) return
|
|
69
|
+
setScale(event.detail.scale)
|
|
70
|
+
setInverseScale(event.detail.inverseScale)
|
|
71
|
+
}
|
|
72
|
+
window.addEventListener(SCALE_CHANGE_EVENT, onScale)
|
|
73
|
+
detach = () => {
|
|
74
|
+
window.removeEventListener(SCALE_CHANGE_EVENT, onScale)
|
|
75
|
+
scaler.stop()
|
|
76
|
+
scalerRef.current = null
|
|
77
|
+
}
|
|
78
|
+
})
|
|
29
79
|
|
|
30
80
|
return () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
81
|
+
disposed = true
|
|
82
|
+
cancelWait()
|
|
83
|
+
detach()
|
|
34
84
|
}
|
|
35
85
|
}, [targetRef])
|
|
36
86
|
|
|
@@ -44,3 +94,46 @@ export function useFitScreen(targetRef, options = {}) {
|
|
|
44
94
|
|
|
45
95
|
return { scale, inverseScale, refresh }
|
|
46
96
|
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 第三方组件反缩放补偿(对应 Vue `v-compensate`)。
|
|
100
|
+
* 挂在槽位内层 ref 上;父槽位需有明确宽高。
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* const innerRef = useRef(null)
|
|
104
|
+
* useCompensate(innerRef, { resizeCanvas: true })
|
|
105
|
+
*/
|
|
106
|
+
export function useCompensate(targetRef, options = {}) {
|
|
107
|
+
const apiRef = useRef(null)
|
|
108
|
+
const optionsRef = useRef(options)
|
|
109
|
+
optionsRef.current = options
|
|
110
|
+
const resizeFlag = Boolean(options?.resizeCanvas || options?.echarts || options?.echartsLib)
|
|
111
|
+
const lib =
|
|
112
|
+
(options && typeof options.echarts === 'object' && options.echarts) ||
|
|
113
|
+
options?.echartsLib ||
|
|
114
|
+
null
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
let api = null
|
|
118
|
+
let disposed = false
|
|
119
|
+
|
|
120
|
+
const cancelWait = waitForElement(targetRef, (el) => {
|
|
121
|
+
if (disposed) return
|
|
122
|
+
api = createCompensate(el, () => optionsRef.current || {})
|
|
123
|
+
apiRef.current = api
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
return () => {
|
|
127
|
+
disposed = true
|
|
128
|
+
cancelWait()
|
|
129
|
+
api?.stop()
|
|
130
|
+
apiRef.current = null
|
|
131
|
+
}
|
|
132
|
+
}, [targetRef, resizeFlag, lib])
|
|
133
|
+
|
|
134
|
+
const refresh = useCallback(() => {
|
|
135
|
+
apiRef.current?.refresh()
|
|
136
|
+
}, [])
|
|
137
|
+
|
|
138
|
+
return { refresh }
|
|
139
|
+
}
|