UNPKG

@visactor/vrender-core

Version:
196 lines (176 loc) 8.18 kB
import { application } from "../../application"; import { createColor } from "../../common/canvas-utils"; import { DEFAULT_TEXT_FONT_FAMILY } from "../../constants"; export const DIRECTION_KEY = { horizontal: { width: "width", height: "height", left: "left", top: "top", x: "x", y: "y", bottom: "bottom" }, vertical: { width: "height", height: "width", left: "top", top: "left", x: "y", y: "x", bottom: "right" } }; const defaultFormatting = { fontSize: 16, fontFamily: DEFAULT_TEXT_FONT_FAMILY, fill: !0, stroke: !1, fontWeight: "normal", lineHeight: "normal", fontStyle: "normal", textDecoration: "none", textAlign: "left", script: "normal" }, nbsp = String.fromCharCode(160); export const regLetter = /\w|\(|\)|-/; const regPunctuation = /[.?!,;:/,。?!、;:]/; export const regFirstSpace = /\S/; const setTextStyle = (ctx, character) => { let fontSize = character.fontSize || 16; switch (character.script) { case "super": case "sub": fontSize *= .8; } ctx.setTextStyle({ textAlign: "left", textBaseline: character.textBaseline || "alphabetic", fontStyle: character.fontStyle || "", fontWeight: character.fontWeight || "", fontSize: fontSize, fontFamily: character.fontFamily }); }; export function applyFillStyle(ctx, character, b) { const fillStyle = character && character.fill || defaultFormatting.fill; if (!fillStyle) return void (ctx.globalAlpha = 0); const {fillOpacity: fillOpacity = 1, opacity: opacity = 1} = character; ctx.globalAlpha = fillOpacity * opacity, ctx.fillStyle = b ? createColor(ctx, fillStyle, { AABBBounds: b }) : fillStyle, setTextStyle(ctx, character); } export function applyStrokeStyle(ctx, character) { const strokeStyle = character && character.stroke || defaultFormatting.stroke; if (!strokeStyle) return void (ctx.globalAlpha = 0); const {strokeOpacity: strokeOpacity = 1, opacity: opacity = 1} = character; ctx.globalAlpha = strokeOpacity * opacity, ctx.lineWidth = character && "number" == typeof character.lineWidth ? character.lineWidth : 1, ctx.strokeStyle = strokeStyle, setTextStyle(ctx, character); } export function prepareContext(ctx) { ctx.setTextStyle({ textAlign: "left", textBaseline: "bottom" }); } export function getStrByWithDom(desc, width, style, guessIndex, needTestLetter) { desc = desc.replace(/\s/g, nbsp); const span = document.createElement("span"); span.setAttribute("style", style), span.style.visibility = "hidden", span.style.whiteSpace = "nowrap", document.body.appendChild(span); let index = guessIndex, temp = desc.slice(0, index); span.innerText = temp; let tempWidth = span.offsetWidth, tempNext = desc.slice(0, index + 1); span.innerText = tempNext; let tempWidthNext = span.offsetWidth; for (;tempWidth > width || tempWidthNext <= width; ) tempWidth > width ? index-- : index++, temp = desc.slice(0, index), span.innerText = temp, tempWidth = span.offsetWidth, tempNext = desc.slice(0, index + 1), span.innerText = tempNext, tempWidthNext = span.offsetWidth; return needTestLetter && (index = testLetter(desc, index)), document.body.removeChild(span), index; } export function getStrByWithCanvas(desc, width, character, guessIndex, needTestLetter) { if (!width || width <= 0) return 0; const textMeasure = application.graphicUtil.textMeasure; let index = guessIndex, temp = desc.slice(0, index), tempWidth = Math.floor(textMeasure.measureText(temp, character).width), tempNext = desc.slice(0, index + 1), tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character).width); for (;tempWidth > width || tempWidthNext <= width; ) { if (tempWidth > width ? index-- : index++, index > desc.length) { index = desc.length; break; } if (index < 0) { index = 0; break; } temp = desc.slice(0, index), tempWidth = Math.floor(textMeasure.measureText(temp, character).width), tempNext = desc.slice(0, index + 1), tempWidthNext = Math.floor(textMeasure.measureText(tempNext, character).width); } return needTestLetter && (index = testLetter(desc, index)), index; } export function getWordStartEndIdx(string, index) { let startIdx = index; for (;(regLetter.test(string[startIdx - 1]) && regLetter.test(string[startIdx]) || regPunctuation.test(string[startIdx])) && (startIdx--, !(startIdx <= 0)); ) ; let endIdx = index; for (;(regLetter.test(string[endIdx + 1]) && regLetter.test(string[endIdx]) || regPunctuation.test(string[endIdx])) && (endIdx++, !(endIdx >= string.length)); ) ; return endIdx = Math.min(endIdx + 1, string.length), { startIdx: startIdx, endIdx: endIdx }; } export function testLetter(string, index, negativeWrongMatch = !1) { let i = index; for (;regLetter.test(string[i - 1]) && regLetter.test(string[i]) || regPunctuation.test(string[i]); ) if (i--, i <= 0) return negativeWrongMatch ? testLetter2(string, index) : index; return i; } export function testLetter2(string, index) { let i = index; for (;regLetter.test(string[i + 1]) && regLetter.test(string[i]) || regPunctuation.test(string[i]); ) if (i++, i >= string.length) return i; return i + 1; } export function measureTextDom(text, style) { var _a; let div; const span = document.createElement("span"), block = document.createElement("div"); div = document.createElement("div"), block.style.display = "inline-block", block.style.width = "1px", block.style.height = "0", div.style.visibility = "hidden", div.style.position = "absolute", div.style.top = "0", div.style.left = "0", div.style.width = "500px", div.style.height = "200px", div.style.whiteSpace = "nowrap", div.appendChild(span), div.appendChild(block), document.body.appendChild(div); const result = {}; try { span.setAttribute("style", style), span.style.whiteSpace = "nowrap", span.style.display = "inline-block", span.innerHTML = "", span.appendChild(document.createTextNode(text.replace(/\s/g, nbsp))), block.style.verticalAlign = "baseline", result.ascent = block.offsetTop - span.offsetTop, block.style.verticalAlign = "bottom", result.height = block.offsetTop - span.offsetTop, result.descent = result.height - result.ascent, result.width = span.offsetWidth; } finally { null === (_a = div.parentNode) || void 0 === _a || _a.removeChild(div), div = null; } return result; } export function measureTextCanvas(text, character, mode = "actual") { const measurement = application.graphicUtil.textMeasure.measureText(text, character), result = { ascent: 0, height: 0, descent: 0, width: 0 }, ascent = "actual" === mode ? measurement.actualBoundingBoxAscent : measurement.fontBoundingBoxAscent, descent = "actual" === mode ? measurement.actualBoundingBoxDescent : measurement.fontBoundingBoxDescent; return "number" != typeof ascent || "number" != typeof descent ? (result.width = Math.floor(measurement.width), result.height = character.fontSize || 0, result.ascent = result.height, result.descent = 0) : (result.width = Math.floor(measurement.width), result.height = Math.floor(ascent + descent), result.ascent = Math.floor(ascent), result.descent = result.height - result.ascent), result; } export function getFontString(character, ctx) { let fontSize = character && character.fontSize || defaultFormatting.fontSize; if (character) switch (character.script) { case "super": case "sub": fontSize *= .8; } return (character && character.fontStyle || "") + " " + (character && character.fontWeight || "") + " " + (fontSize || 12) + "px " + (character && character.fontFamily || defaultFormatting.fontFamily); } //# sourceMappingURL=utils.js.map