From 6cecc8d8c8569bc640c2ec2772a4cf540a3b397a Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 24 Jan 2019 16:16:04 +0700 Subject: [PATCH 1/5] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BD=D0=B0=D0=B4=20=D0=B8=D0=B7=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=D0=BC=20=D0=BE=D1=82=20=D0=BA=D0=B0=D0=BD?= =?UTF-8?q?=D0=B2=D0=B0=D1=81=D0=B0=20=D0=B2=20=D1=81=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=BE=D0=BD=D1=83=20=D0=B2=D0=B5=D1=80=D1=81=D1=82=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B4=D0=B8=D0=B2=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Reader/TextPage/DrawHelper.js | 8 +- .../components/Reader/TextPage/TextPage.vue | 144 ++++++++---------- client/components/Reader/share/BookParser.js | 10 +- 3 files changed, 73 insertions(+), 89 deletions(-) diff --git a/client/components/Reader/TextPage/DrawHelper.js b/client/components/Reader/TextPage/DrawHelper.js index 5242e01d..85e7a404 100644 --- a/client/components/Reader/TextPage/DrawHelper.js +++ b/client/components/Reader/TextPage/DrawHelper.js @@ -67,5 +67,11 @@ export default class DrawHelper { } } - + fillText(text, x, y, font) { + /*this.context1.textAlign = 'left'; + this.context2.textAlign = 'left'; + this.context1.textBaseline = 'bottom'; + this.context2.textBaseline = 'bottom';*/ + return `
${text}
`; + } } \ No newline at end of file diff --git a/client/components/Reader/TextPage/TextPage.vue b/client/components/Reader/TextPage/TextPage.vue index 90ad6a61..9ee988fa 100644 --- a/client/components/Reader/TextPage/TextPage.vue +++ b/client/components/Reader/TextPage/TextPage.vue @@ -1,15 +1,22 @@ @@ -33,6 +40,8 @@ export default @Component({ }) class TextPage extends Vue { activeCanvas = false; + page1 = null; + page2 = null; lastBook = null; bookPos = 0; @@ -68,8 +77,7 @@ class TextPage extends Vue { } mounted() { - this.canvas1 = this.$refs.canvas1; - this.canvas2 = this.$refs.canvas2; + this.context = this.$refs.offscreenCanvas.getContext('2d'); } hex2rgba(hex, alpha = 1) { @@ -78,36 +86,12 @@ class TextPage extends Vue { } async calcDrawProps() { - this.context1 = this.canvas1.getContext('2d'); - this.context2 = this.canvas2.getContext('2d'); - this.realWidth = this.$refs.main.clientWidth; this.realHeight = this.$refs.main.clientHeight; - let ratio = window.devicePixelRatio; - if (ratio) { - this.canvas1.width = this.realWidth*ratio; - this.canvas1.height = this.realHeight*ratio; - this.canvas1.style.width = this.$refs.main.clientWidth + 'px'; - this.canvas1.style.height = this.$refs.main.clientHeight + 'px'; - this.context1.scale(ratio, ratio); + this.$refs.layoutEvents.style.width = this.realWidth + 'px'; + this.$refs.layoutEvents.style.height = this.realHeight + 'px'; - this.canvas2.width = this.realWidth*ratio; - this.canvas2.height = this.realHeight*ratio; - this.canvas2.style.width = this.$refs.main.clientWidth + 'px'; - this.canvas2.style.height = this.$refs.main.clientHeight + 'px'; - this.context2.scale(ratio, ratio); - } else { - this.canvas1.width = this.realWidth; - this.canvas1.height = this.realHeight; - this.canvas2.width = this.realWidth; - this.canvas2.height = this.realHeight; - } - - this.context1.textAlign = 'left'; - this.context2.textAlign = 'left'; - this.context1.textBaseline = 'bottom'; - this.context2.textBaseline = 'bottom'; this.activeCanvas = false; this.w = this.realWidth - 2*this.indent; @@ -120,8 +104,7 @@ class TextPage extends Vue { this.parsed.w = this.w;// px, ширина текста this.parsed.font = this.font; this.parsed.wordWrap = this.wordWrap; - this.parsed.context = this.context1; - this.parsed.fontByStyle = this.fontByStyle; + this.parsed.measureText = this.measureText; } this.statusBarColor = this.hex2rgba(this.textColor, this.statusBarColorAlpha); @@ -137,6 +120,11 @@ class TextPage extends Vue { this.drawHelper.fontName = this.fontName; } + measureText(text, style) {// eslint-disable-line no-unused-vars + this.context.font = this.fontByStyle(style); + return this.context.measureText(text).width; + } + async loadFonts() { let loaded = await Promise.all(this.fontList.map(font => document.fonts.check(font))); if (loaded.some(r => !r)) { @@ -213,7 +201,7 @@ class TextPage extends Vue { await this.loadFonts(); this.draw(); - this.refreshTime(); + //this.refreshTime(); })(); } } @@ -231,22 +219,6 @@ class TextPage extends Vue { return `${style.italic ? 'italic' : ''} ${style.bold ? 'bold' : ''} ${this.fontSize}px ${this.fontName}`; } - get context() { - return (this.activeCanvas ? this.context1 : this.context2); - } - - get canvas() { - return (this.activeCanvas ? this.canvas1 : this.canvas2); - } - - get canvasStyle1() { - return (this.activeCanvas ? {'z-index': 11} : {'z-index': 10}); - } - - get canvasStyle2() { - return (this.activeCanvas ? {'z-index': 10} : {'z-index': 11}); - } - draw(immediate) { if (this.book && this.bookPos > 0 && this.bookPos >= this.parsed.textLength) { this.doEnd(); @@ -254,12 +226,15 @@ class TextPage extends Vue { } this.activeCanvas = !this.activeCanvas; - const context = this.context; - if (immediate) { - this.drawPage(context, this.bookPos); + immediate = true; + if (immediate) { + if (this.activeCanvas) + this.page1 = this.drawPage(this.bookPos); + else + this.page2 = this.drawPage(this.bookPos); } else { - if (this.pageChangeDirectionDown && this.pagePrepared && this.bookPos == this.bookPosPrepared) { + /*if (this.pageChangeDirectionDown && this.pagePrepared && this.bookPos == this.bookPosPrepared) { this.linesDown = this.linesDownNext; this.linesUp = this.linesUpNext; this.pagePrepared = false; @@ -268,7 +243,7 @@ class TextPage extends Vue { this.drawPage(context, this.bookPos); this.pagePrepared = false; this.debouncedPrepareNextPage(); - } + }*/ if (this.currentTransition) { //this.currentTransition @@ -284,19 +259,19 @@ class TextPage extends Vue { } } - drawPage(context, bookPos, nextChangeLines) { + drawPage(bookPos, nextChangeLines) { if (!this.lastBook) return; - context.fillStyle = this.backgroundColor; - context.fillRect(0, 0, this.realWidth, this.realHeight); + let out = `
`; - if (!this.book || !this.parsed.textLength) - return; + if (!this.book || !this.parsed.textLength) { + out += '
'; + return out; + } - context.font = this.font; - context.fillStyle = this.textColor; - const spaceWidth = context.measureText(' ').width; + const spaceWidth = this.measureText(' ', {}); const lines = this.parsed.getLines(bookPos, 2*this.pageLineCount); if (!nextChangeLines) { @@ -328,13 +303,15 @@ class TextPage extends Vue { }*/ let indent = this.indent + (line.first ? this.p : 0); - y += this.lineHeight; let lineText = ''; let center = false; + let centerStyle = {}; for (const part of line.parts) { lineText += part.text; center = center || part.style.center; + if (part.style.center) + centerStyle = part.style.center; } let filled = false; @@ -349,13 +326,13 @@ class TextPage extends Vue { let x = indent; for (const part of line.parts) { - context.font = this.fontByStyle(part.style); + const font = this.fontByStyle(part.style); let partWords = part.text.split(' '); for (let i = 0; i < partWords.length; i++) { let word = partWords[i]; - context.fillText(word, x, y); - x += context.measureText(word).width + (i < partWords.length - 1 ? space : 0); + out += this.drawHelper.fillText(word, x, y, font); + x += this.measureText(word, part.style) + (i < partWords.length - 1 ? space : 0); } } filled = true; @@ -365,20 +342,24 @@ class TextPage extends Vue { // просто выводим текст if (!filled) { let x = indent; - x = (center ? this.indent + (this.w - context.measureText(lineText).width)/2 : x); + x = (center ? this.indent + (this.w - this.measureText(lineText, centerStyle))/2 : x); for (const part of line.parts) { let text = part.text; - context.font = this.fontByStyle(part.style); - context.fillText(text, x, y); - x += context.measureText(text).width; + const font = this.fontByStyle(part.style); + out += this.drawHelper.fillText(text, x, y, font); + x += this.measureText(text, part.style); } } + y += this.lineHeight; } - this.drawStatusBar(context, lines); + out += ''; + + //this.drawStatusBar(context, lines); + return out; } - drawStatusBar(context, lines) { + /*drawStatusBar(context, lines) { if (!lines) lines = this.linesDown; @@ -404,7 +385,7 @@ class TextPage extends Vue { this.timeRefreshing = false; this.refreshTime(); } - } + }*/ prepareNextPage() { // подготовка следующей страницы заранее @@ -622,10 +603,7 @@ class TextPage extends Vue { onMouseClick(event) { if (this.showStatusBar && this.book) { - const pointX = event.pageX - this.canvas.offsetLeft; - const pointY = event.pageY - this.canvas.offsetTop; - - if (this.checkPointInStatusBar(pointX, pointY)) { + if (this.checkPointInStatusBar(event.offsetX, event.offsetY)) { window.open(this.meta.url, '_blank'); return false; } @@ -695,9 +673,15 @@ class TextPage extends Vue { position: relative; } -.canvas { +.layout { margin: 0; padding: 0; position: absolute; + z-index: 10; +} + +.events { + z-index: 20; + background-color: rgba(0,0,0,0); } diff --git a/client/components/Reader/share/BookParser.js b/client/components/Reader/share/BookParser.js index 62174a39..a9faa271 100644 --- a/client/components/Reader/share/BookParser.js +++ b/client/components/Reader/share/BookParser.js @@ -8,15 +8,9 @@ export default class BookParser { this.w = 300;// px, ширина страницы this.wordWrap = false;// перенос по слогам + //заглушка this.measureText = (text, style) => {// eslint-disable-line no-unused-vars - if (this.context) { - this.context.save(); - this.context.font = this.fontByStyle(style); - const w = this.context.measureText(text).width; - this.context.restore(); - return w; - } else - return 0; + return text.length*20; }; } From 2b755e534e8ae1ac1d91e3eff83c7798b3d24d27 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 24 Jan 2019 16:42:47 +0700 Subject: [PATCH 2/5] =?UTF-8?q?=D0=9A=20=D0=BF=D1=80=D0=B5=D0=B4=D1=8B?= =?UTF-8?q?=D0=B4=D1=83=D1=89=D0=B5=D0=BC=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/components/Reader/TextPage/TextPage.vue | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/client/components/Reader/TextPage/TextPage.vue b/client/components/Reader/TextPage/TextPage.vue index 9ee988fa..6ddb06f4 100644 --- a/client/components/Reader/TextPage/TextPage.vue +++ b/client/components/Reader/TextPage/TextPage.vue @@ -227,23 +227,25 @@ class TextPage extends Vue { this.activeCanvas = !this.activeCanvas; - immediate = true; if (immediate) { if (this.activeCanvas) this.page1 = this.drawPage(this.bookPos); else this.page2 = this.drawPage(this.bookPos); } else { - /*if (this.pageChangeDirectionDown && this.pagePrepared && this.bookPos == this.bookPosPrepared) { + if (this.pageChangeDirectionDown && this.pagePrepared && this.bookPos == this.bookPosPrepared) { this.linesDown = this.linesDownNext; this.linesUp = this.linesUpNext; this.pagePrepared = false; this.debouncedPrepareNextPage(); } else { - this.drawPage(context, this.bookPos); + if (this.activeCanvas) + this.page1 = this.drawPage(this.bookPos); + else + this.page2 = this.drawPage(this.bookPos); this.pagePrepared = false; this.debouncedPrepareNextPage(); - }*/ + } if (this.currentTransition) { //this.currentTransition @@ -408,8 +410,10 @@ class TextPage extends Vue { if (i >= 0 && this.linesDown.length > i) { this.bookPosPrepared = this.linesDown[i].begin; - const ctx = (!this.activeCanvas ? this.context1 : this.context2); - this.drawPage(ctx, this.bookPosPrepared, true); + if (this.activeCanvas) + this.page2 = this.drawPage(this.bookPosPrepared, true);//наоборот + else + this.page1 = this.drawPage(this.bookPosPrepared, true); this.pagePrepared = true; } From fc4b4dc8d7137d76b46035da03f79085799cd986 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 24 Jan 2019 19:16:21 +0700 Subject: [PATCH 3/5] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B2=D0=B5=D0=BB?= =?UTF-8?q?=20=D1=81=D1=82=D0=B0=D1=82=D1=83=D1=81-=D0=B1=D0=B0=D1=80=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B4=D0=B8=D0=B2=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Reader/TextPage/DrawHelper.js | 70 +++++++++++-------- .../components/Reader/TextPage/TextPage.vue | 43 ++++++++---- 2 files changed, 70 insertions(+), 43 deletions(-) diff --git a/client/components/Reader/TextPage/DrawHelper.js b/client/components/Reader/TextPage/DrawHelper.js index 85e7a404..5b18efda 100644 --- a/client/components/Reader/TextPage/DrawHelper.js +++ b/client/components/Reader/TextPage/DrawHelper.js @@ -3,75 +3,85 @@ export default class DrawHelper { return `${size}px ${this.fontName}`; } - drawPercentBar(context, x, y, w, h, bookPos, textLength) { + drawPercentBar(x, y, w, h, font, bookPos, textLength) { const pad = 3; const fh = h - 2*pad; const fh2 = fh/2; const t1 = `${Math.floor((bookPos + 1)/1000)}k/${Math.floor(textLength/1000)}k`; - const w1 = context.measureText(t1).width + fh2; + const w1 = this.measureTextFont(t1, font) + fh2; const read = (bookPos + 1)/textLength; const t2 = `${(read*100).toFixed(2)}%`; - const w2 = context.measureText(t2).width; + const w2 = this.measureTextFont(t2, font); let w3 = w - w1 - w2; + let out = ''; if (w1 + w2 <= w) - context.fillText(t1, x, y + h - 2); + out += this.fillText(t1, x, y, font); if (w1 + w2 + w3 <= w && w3 > (10 + fh2)) { const barWidth = w - w1 - w2 - fh2; - context.strokeRect(x + w1, y + pad + 1, barWidth, fh - 2); - context.fillRect(x + w1 + 2, y + pad + 3, (barWidth - 4)*read, fh - 6); + out += this.strokeRect(x + w1, y + pad - 2, barWidth, fh - 4, this.statusBarColor); + out += this.fillRect(x + w1 + 2, y + pad, (barWidth - 4)*read, fh - 6, this.statusBarColor); } if (w1 <= w) - context.fillText(t2, x + w1 + w3, y + h - 2); + out += this.fillText(t2, x + w1 + w3, y, font); + + return out; } - async drawStatusBar(context, statusBarTop, statusBarHeight, statusBarColor, bookPos, textLength, title) { - const y = (statusBarTop ? 1 : this.realHeight - statusBarHeight); + drawStatusBar(statusBarTop, statusBarHeight, bookPos, textLength, title) { - context.fillStyle = this.backgroundColor; - context.fillRect(0, y, this.realWidth, statusBarHeight); + let out = `
`; - context.font = 'bold ' + this.fontBySize(statusBarHeight - 6); - context.fillStyle = statusBarColor; - context.strokeStyle = statusBarColor; + const fontSize = statusBarHeight - 6; + const font = 'bold ' + this.fontBySize(fontSize); - context.fillRect(0, (statusBarTop ? statusBarHeight : y), this.realWidth, 1); + out += this.fillRect(0, (statusBarTop ? statusBarHeight : 1), this.realWidth, 1, this.statusBarColor); const date = new Date(); - const time = ` ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')} `; - const timeW = context.measureText(time).width; - context.fillText(time, this.realWidth - timeW, y + statusBarHeight - 2); + const time = `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`; + const timeW = this.measureTextFont(time, font); + out += this.fillText(time, this.realWidth - timeW - fontSize, 3, font); - title = ' ' + title; - context.fillText(this.fittingString(context, title, this.realWidth/2 - 3), 0, y + statusBarHeight - 2); + out += this.fillText(this.fittingString(title, this.realWidth/2 - fontSize - 3, font), fontSize, 3, font); - this.drawPercentBar(context, this.realWidth/2, y, this.realWidth/2 - timeW, statusBarHeight, bookPos, textLength); + out += this.drawPercentBar(this.realWidth/2, 3, this.realWidth/2 - timeW - 2*fontSize, statusBarHeight, font, bookPos, textLength); + + out += '
'; + return out; } - fittingString(context, str, maxWidth) { - let w = context.measureText(str).width; + fittingString(str, maxWidth, font) { + let w = this.measureTextFont(str, font); const ellipsis = '…'; - const ellipsisWidth = context.measureText(ellipsis).width; + const ellipsisWidth = this.measureTextFont(ellipsis, font); if (w <= maxWidth || w <= ellipsisWidth) { return str; } else { let len = str.length; while (w >= maxWidth - ellipsisWidth && len-- > 0) { str = str.substring(0, len); - w = context.measureText(str).width; + w = this.measureTextFont(str, font); } return str + ellipsis; } } fillText(text, x, y, font) { - /*this.context1.textAlign = 'left'; - this.context2.textAlign = 'left'; - this.context1.textBaseline = 'bottom'; - this.context2.textBaseline = 'bottom';*/ - return `
${text}
`; + return `
${text}
`; + } + + fillRect(x, y, w, h, color) { + return `
`; + } + + strokeRect(x, y, w, h, color) { + return `
`; } } \ No newline at end of file diff --git a/client/components/Reader/TextPage/TextPage.vue b/client/components/Reader/TextPage/TextPage.vue index 6ddb06f4..0326be15 100644 --- a/client/components/Reader/TextPage/TextPage.vue +++ b/client/components/Reader/TextPage/TextPage.vue @@ -6,6 +6,9 @@
+
+
+
+
@@ -47,6 +44,7 @@ class TextPage extends Vue { page1 = null; page2 = null; statusBar = null; + statusBarClickable = null; lastBook = null; bookPos = 0; @@ -134,6 +132,8 @@ class TextPage extends Vue { this.$refs.statusBar.style.left = '0px'; this.$refs.statusBar.style.top = (this.statusBarTop ? 1 : this.realHeight - this.statusBarHeight) + 'px'; + + this.statusBarClickable = this.drawHelper.statusBarClickable(this.statusBarTop, this.statusBarHeight); } measureText(text, style) {// eslint-disable-line no-unused-vars @@ -169,7 +169,7 @@ class TextPage extends Vue { this.fontShifts = {//% ReaderDefault: 0, Arial: 5, - ComicSansMS: -10, + ComicSansMS: -12, OpenSans: 0, Roboto: 0, ArialNarrow: 0, @@ -623,27 +623,8 @@ class TextPage extends Vue { } } - checkPointInStatusBar(pointX, pointY) { - let titleBar = {x1: 0, y1: 0, x2: this.realWidth/2, y2: this.statusBarHeight + 1}; - if (!this.statusBarTop) { - titleBar.y1 += this.realHeight - this.statusBarHeight + 1; - titleBar.y2 += this.realHeight - this.statusBarHeight + 1; - } - - if (pointX >= titleBar.x1 && pointX <= titleBar.x2 && - pointY >= titleBar.y1 && pointY <= titleBar.y2) { - return true; - } - return false; - } - - onMouseClick(event) { - if (this.showStatusBar && this.book) { - if (this.checkPointInStatusBar(event.offsetX, event.offsetY)) { - window.open(this.meta.url, '_blank'); - return false; - } - } + onStatusBarClick() { + window.open(this.meta.url, '_blank'); } handleClick(pointX, pointY) { @@ -653,12 +634,6 @@ class TextPage extends Vue { 100: {30: 'PgUp', 100: 'PgDown'} }; - if (this.showStatusBar && this.book) { - if (this.checkPointInStatusBar(pointX, pointY)) { - return false; - } - } - const w = pointX/this.realWidth*100; const h = pointY/this.realHeight*100;