react-book-reader 1.1.7 → 1.1.8
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/lib/overlayer.js +175 -0
- package/lib/react-book-reader.es.js +6588 -918
- package/package.json +65 -64
- package/lib/comic-book-D8f_Cc7Q.js +0 -25
- package/lib/epub-vizLT02-.js +0 -681
- package/lib/fb2-DCqZtzQ5.js +0 -258
- package/lib/fflate-CExlDunL.js +0 -139
- package/lib/fixed-layout-CMyaX9h8.js +0 -195
- package/lib/mobi-CikMBloG.js +0 -960
- package/lib/paginator-CpnI4Urk.js +0 -748
- package/lib/pdf-D5_pBBCO.js +0 -109
- package/lib/search-aqQXTfxz.js +0 -72
- package/lib/tts-UQB-k9b_.js +0 -212
- package/lib/view-Ht0IwIBs.js +0 -774
- package/lib/zip-Bw0cufIw.js +0 -1509
package/lib/overlayer.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
const createSVGElement = tag =>
|
|
2
|
+
document.createElementNS('http://www.w3.org/2000/svg', tag)
|
|
3
|
+
|
|
4
|
+
export class Overlayer {
|
|
5
|
+
#svg = createSVGElement('svg')
|
|
6
|
+
#map = new Map()
|
|
7
|
+
constructor() {
|
|
8
|
+
Object.assign(this.#svg.style, {
|
|
9
|
+
position: 'absolute', top: '0', left: '0',
|
|
10
|
+
width: '100%', height: '100%',
|
|
11
|
+
pointerEvents: 'none',
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
get element() {
|
|
15
|
+
return this.#svg
|
|
16
|
+
}
|
|
17
|
+
add(key, range, draw, options) {
|
|
18
|
+
if (this.#map.has(key)) this.remove(key)
|
|
19
|
+
if (typeof range === 'function') range = range(this.#svg.getRootNode())
|
|
20
|
+
const rects = range.getClientRects()
|
|
21
|
+
const element = draw(rects, options)
|
|
22
|
+
this.#svg.append(element)
|
|
23
|
+
this.#map.set(key, { range, draw, options, element, rects })
|
|
24
|
+
}
|
|
25
|
+
remove(key) {
|
|
26
|
+
if (!this.#map.has(key)) return
|
|
27
|
+
this.#svg.removeChild(this.#map.get(key).element)
|
|
28
|
+
this.#map.delete(key)
|
|
29
|
+
}
|
|
30
|
+
redraw() {
|
|
31
|
+
for (const obj of this.#map.values()) {
|
|
32
|
+
const { range, draw, options, element } = obj
|
|
33
|
+
this.#svg.removeChild(element)
|
|
34
|
+
const rects = range.getClientRects()
|
|
35
|
+
const el = draw(rects, options)
|
|
36
|
+
this.#svg.append(el)
|
|
37
|
+
obj.element = el
|
|
38
|
+
obj.rects = rects
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
hitTest({ x, y }) {
|
|
42
|
+
const arr = Array.from(this.#map.entries())
|
|
43
|
+
// loop in reverse to hit more recently added items first
|
|
44
|
+
for (let i = arr.length - 1; i >= 0; i--) {
|
|
45
|
+
const [key, obj] = arr[i]
|
|
46
|
+
for (const { left, top, right, bottom } of obj.rects)
|
|
47
|
+
if (top <= y && left <= x && bottom > y && right > x)
|
|
48
|
+
return [key, obj.range]
|
|
49
|
+
}
|
|
50
|
+
return []
|
|
51
|
+
}
|
|
52
|
+
static underline(rects, options = {}) {
|
|
53
|
+
const { color = 'red', width: strokeWidth = 2, writingMode } = options
|
|
54
|
+
const g = createSVGElement('g')
|
|
55
|
+
g.setAttribute('fill', color)
|
|
56
|
+
if (writingMode === 'vertical-rl' || writingMode === 'vertical-lr')
|
|
57
|
+
for (const { right, top, height } of rects) {
|
|
58
|
+
const el = createSVGElement('rect')
|
|
59
|
+
el.setAttribute('x', right - strokeWidth)
|
|
60
|
+
el.setAttribute('y', top)
|
|
61
|
+
el.setAttribute('height', height)
|
|
62
|
+
el.setAttribute('width', strokeWidth)
|
|
63
|
+
g.append(el)
|
|
64
|
+
}
|
|
65
|
+
else for (const { left, bottom, width } of rects) {
|
|
66
|
+
const el = createSVGElement('rect')
|
|
67
|
+
el.setAttribute('x', left)
|
|
68
|
+
el.setAttribute('y', bottom - strokeWidth)
|
|
69
|
+
el.setAttribute('height', strokeWidth)
|
|
70
|
+
el.setAttribute('width', width)
|
|
71
|
+
g.append(el)
|
|
72
|
+
}
|
|
73
|
+
return g
|
|
74
|
+
}
|
|
75
|
+
static strikethrough(rects, options = {}) {
|
|
76
|
+
const { color = 'red', width: strokeWidth = 2, writingMode } = options
|
|
77
|
+
const g = createSVGElement('g')
|
|
78
|
+
g.setAttribute('fill', color)
|
|
79
|
+
if (writingMode === 'vertical-rl' || writingMode === 'vertical-lr')
|
|
80
|
+
for (const { right, left, top, height } of rects) {
|
|
81
|
+
const el = createSVGElement('rect')
|
|
82
|
+
el.setAttribute('x', (right + left) / 2)
|
|
83
|
+
el.setAttribute('y', top)
|
|
84
|
+
el.setAttribute('height', height)
|
|
85
|
+
el.setAttribute('width', strokeWidth)
|
|
86
|
+
g.append(el)
|
|
87
|
+
}
|
|
88
|
+
else for (const { left, top, bottom, width } of rects) {
|
|
89
|
+
const el = createSVGElement('rect')
|
|
90
|
+
el.setAttribute('x', left)
|
|
91
|
+
el.setAttribute('y', (top + bottom) / 2)
|
|
92
|
+
el.setAttribute('height', strokeWidth)
|
|
93
|
+
el.setAttribute('width', width)
|
|
94
|
+
g.append(el)
|
|
95
|
+
}
|
|
96
|
+
return g
|
|
97
|
+
}
|
|
98
|
+
static squiggly(rects, options = {}) {
|
|
99
|
+
const { color = 'red', width: strokeWidth = 2, writingMode } = options
|
|
100
|
+
const g = createSVGElement('g')
|
|
101
|
+
g.setAttribute('fill', 'none')
|
|
102
|
+
g.setAttribute('stroke', color)
|
|
103
|
+
g.setAttribute('stroke-width', strokeWidth)
|
|
104
|
+
const block = strokeWidth * 1.5
|
|
105
|
+
if (writingMode === 'vertical-rl' || writingMode === 'vertical-lr')
|
|
106
|
+
for (const { right, top, height } of rects) {
|
|
107
|
+
const el = createSVGElement('path')
|
|
108
|
+
const n = Math.round(height / block / 1.5)
|
|
109
|
+
const inline = height / n
|
|
110
|
+
const ls = Array.from({ length: n },
|
|
111
|
+
(_, i) => `l${i % 2 ? -block : block} ${inline}`).join('')
|
|
112
|
+
el.setAttribute('d', `M${right} ${top}${ls}`)
|
|
113
|
+
g.append(el)
|
|
114
|
+
}
|
|
115
|
+
else for (const { left, bottom, width } of rects) {
|
|
116
|
+
const el = createSVGElement('path')
|
|
117
|
+
const n = Math.round(width / block / 1.5)
|
|
118
|
+
const inline = width / n
|
|
119
|
+
const ls = Array.from({ length: n },
|
|
120
|
+
(_, i) => `l${inline} ${i % 2 ? block : -block}`).join('')
|
|
121
|
+
el.setAttribute('d', `M${left} ${bottom}${ls}`)
|
|
122
|
+
g.append(el)
|
|
123
|
+
}
|
|
124
|
+
return g
|
|
125
|
+
}
|
|
126
|
+
static highlight(rects, options = {}) {
|
|
127
|
+
const { color = 'red' } = options
|
|
128
|
+
const g = createSVGElement('g')
|
|
129
|
+
g.setAttribute('fill', color)
|
|
130
|
+
g.style.opacity = 'var(--overlayer-highlight-opacity, .3)'
|
|
131
|
+
g.style.mixBlendMode = 'var(--overlayer-highlight-blend-mode, normal)'
|
|
132
|
+
for (const { left, top, height, width } of rects) {
|
|
133
|
+
const el = createSVGElement('rect')
|
|
134
|
+
el.setAttribute('x', left)
|
|
135
|
+
el.setAttribute('y', top)
|
|
136
|
+
el.setAttribute('height', height)
|
|
137
|
+
el.setAttribute('width', width)
|
|
138
|
+
g.append(el)
|
|
139
|
+
}
|
|
140
|
+
return g
|
|
141
|
+
}
|
|
142
|
+
static outline(rects, options = {}) {
|
|
143
|
+
const { color = 'red', width: strokeWidth = 3, radius = 3 } = options
|
|
144
|
+
const g = createSVGElement('g')
|
|
145
|
+
g.setAttribute('fill', 'none')
|
|
146
|
+
g.setAttribute('stroke', color)
|
|
147
|
+
g.setAttribute('stroke-width', strokeWidth)
|
|
148
|
+
for (const { left, top, height, width } of rects) {
|
|
149
|
+
const el = createSVGElement('rect')
|
|
150
|
+
el.setAttribute('x', left)
|
|
151
|
+
el.setAttribute('y', top)
|
|
152
|
+
el.setAttribute('height', height)
|
|
153
|
+
el.setAttribute('width', width)
|
|
154
|
+
el.setAttribute('rx', radius)
|
|
155
|
+
g.append(el)
|
|
156
|
+
}
|
|
157
|
+
return g
|
|
158
|
+
}
|
|
159
|
+
// make an exact copy of an image in the overlay
|
|
160
|
+
// one can then apply filters to the entire element, without affecting them;
|
|
161
|
+
// it's a bit silly and probably better to just invert images twice
|
|
162
|
+
// (though the color will be off in that case if you do heu-rotate)
|
|
163
|
+
static copyImage([rect], options = {}) {
|
|
164
|
+
const { src } = options
|
|
165
|
+
const image = createSVGElement('image')
|
|
166
|
+
const { left, top, height, width } = rect
|
|
167
|
+
image.setAttribute('href', src)
|
|
168
|
+
image.setAttribute('x', left)
|
|
169
|
+
image.setAttribute('y', top)
|
|
170
|
+
image.setAttribute('height', height)
|
|
171
|
+
image.setAttribute('width', width)
|
|
172
|
+
return image
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|