Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #157 #170

Open
wants to merge 3 commits into
base: gh-pages
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 134 additions & 31 deletions src/wordcloud2.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ if (!window.clearImmediate) {
}

(function (global) {
var debug = false

// Check if WordCloud can run on this browser
var isSupported = (function isSupported () {
var canvas = document.createElement('canvas')
Expand All @@ -104,6 +106,9 @@ if (!window.clearImmediate) {
if (!ctx.fillText) {
return false
}
// if (!ctx.measureText('Test').actualBoundingBoxAscent) {
// return false
// }
Comment on lines +109 to +111
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these


if (!Array.prototype.some) {
return false
Expand Down Expand Up @@ -510,7 +515,6 @@ if (!window.clearImmediate) {
// calculate the acutal font size
// fontSize === 0 means weightFactor function wants the text skipped,
// and size < minSize means we cannot draw the text.
var debug = false
var fontSize = settings.weightFactor(weight)
if (fontSize <= settings.minSize) {
return false
Expand Down Expand Up @@ -544,12 +548,26 @@ if (!window.clearImmediate) {
fctx.font = fontWeight + ' ' +
(fontSize * mu).toString(10) + 'px ' + settings.fontFamily

var measurements = fctx.measureText(word)
var fillTextAscent, fillTextDescent, htmlInfo

if (typeof measurements.actualBoundingBoxAscent === 'number') {
fillTextAscent = measurements.actualBoundingBoxAscent
fillTextDescent = measurements.actualBoundingBoxDescent
} else {
// not as accurate but seems to work ok as a fallback where browser support is lacking...
htmlInfo = getHtmlTextInfo(settings.fontFamily, fontSize, word);
fillTextAscent = htmlInfo.ascent;
fillTextDescent = htmlInfo.descent;
}

// Estimate the dimension of the text with measureText().
var fw = fctx.measureText(word).width / mu
var fh = Math.max(fontSize * mu,
fctx.measureText('m').width,
fctx.measureText('\uFF37').width
) / mu
var fw = measurements.width / mu
var fh = (fillTextAscent + fillTextDescent) / mu // assumed / mu necessary? fontSize is first multiplied below
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have problem with mu try to set the minimum font size in the browser inspect the rendering.

// var fh = Math.max(fontSize * mu,
// fctx.measureText('m').width,
// fctx.measureText('\uFF37').width
// ) / mu
Comment on lines +567 to +570
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these?


// Create a boundary box that is larger than our estimates,
// so text don't get cut of (it sill might)
Expand All @@ -565,10 +583,9 @@ if (!window.clearImmediate) {

// This is simply half of the width.
var fillTextOffsetX = -fw / 2
// Instead of moving the box to the exact middle of the preferred
// position, for Y-offset we move 0.4 instead, so Latin alphabets look
// vertical centered.
var fillTextOffsetY = -fh * 0.4

// This is the distance from the baseline to the centre of the text.
var fillTextOffsetY = (fillTextAscent - fillTextDescent) / mu / 2 // again, assumed / mu necessary?

// Calculate the actual dimension of the canvas, considering the rotation.
var cgh = Math.ceil((boxWidth * Math.abs(Math.sin(rotateDeg)) +
Expand Down Expand Up @@ -602,13 +619,11 @@ if (!window.clearImmediate) {
// XXX: We cannot because textBaseline = 'top' here because
// Firefox and Chrome uses different default line-height for canvas.
// Please read https://bugzil.la/737852#c6.
// Here, we use textBaseline = 'middle' and draw the text at exactly
// 0.5 * fontSize lower.
fctx.fillStyle = '#000'
fctx.textBaseline = 'middle'
fctx.textBaseline = 'alphabetic' // i.e. text baseline (default)
fctx.fillText(
word, fillTextOffsetX * mu,
(fillTextOffsetY + fontSize * 0.5) * mu
fillTextOffsetY * mu
)

// Get the pixels of the text
Expand All @@ -622,8 +637,19 @@ if (!window.clearImmediate) {
// Draw the box of the original estimation
fctx.strokeRect(
fillTextOffsetX * mu,
fillTextOffsetY, fw * mu, fh * mu
fillTextOffsetY - fillTextAscent, fw * mu, fh * mu
)

// Draw the effective point of rotation, i.e. (hopefully) centre of canvas and text
fctx.beginPath()
fctx.arc(0, 0, 4, 0, 2 * Math.PI)
fctx.fillStyle = 'red'
fctx.fill()
fctx.beginPath()
fctx.arc(0, 0, 8, 0, 2 * Math.PI)
fctx.strokeStyle = 'red'
fctx.stroke()
Comment on lines +643 to +651
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap in if (debug)?


fctx.restore()
}

Expand Down Expand Up @@ -693,7 +719,10 @@ if (!window.clearImmediate) {
fillTextOffsetY: fillTextOffsetY,
fillTextWidth: fw,
fillTextHeight: fh,
fontSize: fontSize
fillTextAscent: fillTextAscent,
fillTextDescent: fillTextDescent,
fontSize: fontSize,
htmlInfo: htmlInfo
}
}

Expand Down Expand Up @@ -774,47 +803,45 @@ if (!window.clearImmediate) {
// XXX: We cannot because textBaseline = 'top' here because
// Firefox and Chrome uses different default line-height for canvas.
// Please read https://bugzil.la/737852#c6.
// Here, we use textBaseline = 'middle' and draw the text at exactly
// 0.5 * fontSize lower.
ctx.textBaseline = 'middle'
ctx.textBaseline = 'alphabetic' // default (text baseline)
ctx.fillText(
word, info.fillTextOffsetX * mu,
(info.fillTextOffsetY + fontSize * 0.5) * mu
info.fillTextOffsetY * mu
)

// The below box is always matches how <span>s are positioned
/* ctx.strokeRect(info.fillTextOffsetX, info.fillTextOffsetY,
info.fillTextWidth, info.fillTextHeight) */
if (debug) {
// The below box is always matches how <span>s are positioned
ctx.strokeRect(info.fillTextOffsetX, info.fillTextOffsetY - info.fillTextAscent,
info.fillTextWidth, info.fillTextHeight)
}

// Restore the state.
ctx.restore()
} else {
// drawText on DIV element
var span = document.createElement('span')
var transformRule = ''
var htmlInfo = info.htmlInfo || getHtmlTextInfo(settings.fontFamily, fontSize, word, info)
transformRule = 'rotate(' + (-rotateDeg / Math.PI * 180) + 'deg) '
if (info.mu !== 1) {
transformRule +=
'translateX(-' + (info.fillTextWidth / 4) + 'px) ' +
'scale(' + (1 / info.mu) + ')'
}
var transformOriginY = ((htmlInfo.baseline - info.fillTextOffsetY) / htmlInfo.height * 100).toString() + '%'
var styleRules = {
position: 'absolute',
display: 'block',
font: fontWeight + ' ' +
(fontSize * info.mu) + 'px ' + settings.fontFamily,
left: ((gx + info.gw / 2) * g + info.fillTextOffsetX) + 'px',
top: ((gy + info.gh / 2) * g + info.fillTextOffsetY) + 'px',
width: info.fillTextWidth + 'px',
height: info.fillTextHeight + 'px',
lineHeight: fontSize + 'px',
top: ((gy + info.gh / 2) * g + info.fillTextOffsetY - htmlInfo.baseline) + 'px',
whiteSpace: 'nowrap',
transform: transformRule,
webkitTransform: transformRule,
msTransform: transformRule,
transformOrigin: '50% 40%',
webkitTransformOrigin: '50% 40%',
msTransformOrigin: '50% 40%'
transformOrigin: '50% ' + transformOriginY,
webkitTransformOrigin: '50% ' + transformOriginY,
msTransformOrigin: '50% ' + transformOriginY,
}
if (color) {
styleRules.color = color
Expand All @@ -836,6 +863,82 @@ if (!window.clearImmediate) {
})
}

var getHtmlTextInfo = function getTextHeight(font, size, text, info) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var getHtmlTextInfo = function getTextHeight(font, size, text, info) {
var getHtmlTextInfo = function getHTMLTextInfo(font, size, text, info) {

info = info || {};

var container = document.createElement('div')
var inline = document.createElement('span')
var block = document.createElement('div')
var ascender, descender

container.style.position = 'relative'
// make it look a little prettier if debugging...
container.style.marginTop = '0.8rem'
container.style.marginBottom = '1rem'
// necessary when size is smaller than default/computed size...
container.style.lineHeight = '0'
container.style.fontSize = '0px'
// ensure longer entries don't wrap...
container.style.whiteSpace = 'nowrap'

inline.style.position = 'relative'
inline.style.zIndex = '100'
inline.textContent = text
inline.style.fontFamily = font
inline.style.fontSize = size + 'px'
inline.style.lineHeight = 'normal' // equivlent to wordcloud

block.style.display = 'inline-block'
block.style.width = '1px'
block.style.height = '0px'
block.style.verticalAlign = 'baseline'

container.appendChild(inline)
container.appendChild(block)

document.body.appendChild(container)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the container be the child of the "canvas" <div> so that it would inherit the style?


var baseline = block.offsetTop
var width = inline.offsetWidth
var height = container.offsetHeight
// a rough estimation if not already defined/TextMetrics support lacking...
var ascent = (typeof info.fillTextAscent === 'number') ? info.fillTextAscent : block.offsetTop - inline.offsetTop
var descent = (typeof info.fillTextDescent === 'number') ? info.fillTextDescent : inline.offsetHeight - ascent

if (debug) {
ascender = document.createElement('div')
ascender.style.position = 'absolute'
ascender.style.left = '0'
ascender.style.width = '100%'
ascender.style.top = baseline - ascent + 'px'
ascender.style.height = ascent + 'px'
ascender.style.backgroundColor = 'rgba(0, 255, 0, 0.5)'

descender = document.createElement('div')
descender.style.position = 'absolute'
descender.style.left = '0'
descender.style.width = '100%'
descender.style.top = baseline + 'px'
descender.style.height = descent + 'px'
descender.style.backgroundColor = 'rgba(255, 0, 0, 0.5)'

container.style.backgroundColor = 'rgba(0, 0, 255, 0.5)'

container.appendChild(ascender)
container.appendChild(descender)
} else {
document.body.removeChild(container)
}

return {
baseline: baseline,
width: width,
height: height,
ascent: ascent,
descent: descent
}
}

/* Help function to updateGrid */
var fillGridAt = function fillGridAt (x, y, drawMask, dimension, item) {
if (x >= ngx || y >= ngy || x < 0 || y < 0) {
Expand Down