Skip to content

Commit

Permalink
fix: 🐛 make adjustText() to correctly work even on small display devices
Browse files Browse the repository at this point in the history
  • Loading branch information
ttskch committed Jun 28, 2021
1 parent ceacd98 commit 6f1b68f
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 14 deletions.
19 changes: 15 additions & 4 deletions dist/svg-paper.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/svg-paper.min.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions js/src/adjust-text.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

export default (selector, config) => {
export default (selector, config, paperPixelRatio = 1) => {
const $this = document.querySelector(selector)

if (!$this) {
Expand All @@ -13,7 +13,7 @@ export default (selector, config) => {
// @see https://developer.mozilla.org/ja/docs/Web/API/Element/clientWidth
$this.style.display = 'block'

if ($this.clientWidth > config.textLength) {
if ($this.getBoundingClientRect().width * paperPixelRatio > config.textLength) {
$this.querySelector('tspan').setAttribute('textLength', config.textLength)
$this.querySelector('tspan').setAttribute('lengthAdjust', 'spacingAndGlyphs')

Expand Down
11 changes: 10 additions & 1 deletion js/src/svg-paper.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,19 @@ export default class SvgPaper {
}

this.adjustTextQueries.forEach(query => {
// if viewBox is specified, Element.clientWidth and Element.getBoundingClientRect() return different values
// clientWidth: ???
// getBoundingClientRect(): pure pixel value
// so this library uses getBoundingClientRect() and pre-calculated ratio to specify the width of some elements
// @see https://stackoverflow.com/questions/15335926/how-to-use-the-svg-viewbox-attribute
const $svg = document.querySelector(this.selector)
const viewBoxWidth = $svg.getAttribute('viewBox')?.split(/ +/)[2] ?? null
const paperPixelRatio = viewBoxWidth ? parseFloat(viewBoxWidth) / $svg.getBoundingClientRect().width : 1

adjustText(query.selector, {
textLength: query.textLength,
'text-anchor': query.textAnchor,
})
}, paperPixelRatio)
})

// initialize
Expand Down
8 changes: 4 additions & 4 deletions js/tests/adjust-text.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import adjustText from '../src/adjust-text'
test('only textLength will be set', () => {
document.body.innerHTML = '<svg><text><tspan>test</tspan></text></svg>'

jest.spyOn(document.querySelector('text'), 'clientWidth', 'get').mockImplementation(() => 10)
jest.spyOn(document.querySelector('text'), 'getBoundingClientRect').mockImplementation(() => ({width: 10}))
adjustText('text', {textLength: 9})

expect(document.body.innerHTML).toEqual('<svg><text style="display: block;" textLength="9" lengthAdjust="spacingAndGlyphs"><tspan textLength="9" lengthAdjust="spacingAndGlyphs">test</tspan></text></svg>')
Expand All @@ -15,15 +15,15 @@ test('only text-anchor will be set', () => {
// transform exists
document.body.innerHTML = '<svg><text transform="translate(10 20)"><tspan>test</tspan></text></svg>'

jest.spyOn(document.querySelector('text'), 'clientWidth', 'get').mockImplementation(() => 10)
jest.spyOn(document.querySelector('text'), 'getBoundingClientRect').mockImplementation(() => ({width: 10}))
adjustText('text', {textLength: 10, 'text-anchor': 'middle'})

expect(document.body.innerHTML).toEqual('<svg><text transform="translate(15 20)" style="display: block;" text-anchor="middle"><tspan>test</tspan></text></svg>')

// transform doesn't exist
document.body.innerHTML = '<svg><text><tspan x="10" y="20">test</tspan></text></svg>'

jest.spyOn(document.querySelector('text'), 'clientWidth', 'get').mockImplementation(() => 10)
jest.spyOn(document.querySelector('text'), 'getBoundingClientRect').mockImplementation(() => ({width: 10}))
adjustText('text', {textLength: 10, 'text-anchor': 'middle'})

expect(document.body.innerHTML).toEqual('<svg><text style="display: block;" transform="translate(5 0)" text-anchor="middle"><tspan x="10" y="20">test</tspan></text></svg>')
Expand All @@ -32,7 +32,7 @@ test('only text-anchor will be set', () => {
test('both textLength and text-anchor will be set', () => {
document.body.innerHTML = '<svg><text transform="translate(10 20)"><tspan>test</tspan></text></svg>'

jest.spyOn(document.querySelector('text'), 'clientWidth', 'get').mockImplementation(() => 10)
jest.spyOn(document.querySelector('text'), 'getBoundingClientRect').mockImplementation(() => ({width: 10}))
adjustText('text', {textLength: 9, 'text-anchor': 'middle'})

expect(document.body.innerHTML).toEqual('<svg><text transform="translate(14.5 20)" style="display: block;" textLength="9" lengthAdjust="spacingAndGlyphs" text-anchor="middle"><tspan textLength="9" lengthAdjust="spacingAndGlyphs">test</tspan></text></svg>')
Expand Down
2 changes: 1 addition & 1 deletion js/tests/real-world.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function doTest(pathToOriginalSvg, pathToOutputSvg, pathToOutputHtml, pathToExpe
// actually, Element.clientWidth returns always 0 in test.
// so mock Element.clientWidth only for vendorName elements, which have overflowing contents, and re-apply adjustText() to document
for (const i of [...Array(26)].keys()) {
jest.spyOn(document.querySelector(`#_vendorName_${i}_`), 'clientWidth', 'get').mockImplementation(() => 424)
jest.spyOn(document.querySelector(`#_vendorName_${i}_`), 'getBoundingClientRect').mockImplementation(() => ({width: 424}))
paper.adjustText(`#_vendorName_${i}_`, 200)
}
paper.apply()
Expand Down

0 comments on commit 6f1b68f

Please sign in to comment.