如何获得 div 顶部和当前字体顶部之间的高度(在 div 内)
How to get height between top of div and top of current word font (inside this div)
如何获得两条红线之间的高度(div 的顶部和 div 中当前字体的顶部)?
<div class="word">man</div>
.word {
font-size: ...
font-family: ...
}
我尝试创建 canvas 并使用 measureText 方法:
context.measureText(text);
但我无法在该结果中找到有用的信息...
你有什么想法吗?
您收到的 TextMetrics 对象实际上包含足够的信息让我们知道文本的宽度和高度。
在大多数简单的情况下,我们可以将此信息与父元素的边界框的信息结合起来,以获得 单行 文本的实际边界框。
function getWordBBox( element ) {
// store the context as a property of the function
if( !getWordBBox.ctx ) {
const canvas = document.createElement( "canvas" );
canvas.width = canvas.height = 0; // no need to use any memory
getWordBBox.ctx = canvas.getContext( "2d" );
}
const ctx = getWordBBox.ctx;
// grab computed styles from the element
const {
fontStyle, // copy font styles
fontWeight,
fontSize,
fontFamily,
paddingTop, // get inner offsets
paddingLeft,
borderTopWidth,
borderLeftWidth
} = getComputedStyle( element );
const elemBBox = element.getBoundingClientRect();
// set our context with these settings
ctx.font = [ fontStyle, fontWeight, fontSize, fontFamily ].join( " " );
ctx.textBaseline = "top";
ctx.textAlign = "start";
// grab our TextMetrics object
const metrics = ctx.measureText( element.textContent );
// the BBox
const elem_inner_left = elemBBox.left +
parseFloat( borderLeftWidth ) + parseFloat( paddingLeft );
const elem_inner_top = elemBBox.top +
parseFloat( borderTopWidth ) + parseFloat( paddingTop );
return {
left: metrics.actualBoundingBoxLeft * -1 + elem_inner_left,
top: metrics.actualBoundingBoxAscent * -1 + elem_inner_top,
width: metrics.actualBoundingBoxRight + metrics.actualBoundingBoxLeft,
height: metrics.actualBoundingBoxDescent + metrics.actualBoundingBoxAscent
};
}
const elem = document.querySelector( ".word" );
elem.oninput = (evt) => {
const bbox = getWordBBox( elem );
// simply to check we got the bbox of the text correctly
const box_elem = document.querySelector( ".box" );
box_elem.style.setProperty( "top", Math.floor( bbox.top ) + "px" );
box_elem.style.setProperty( "left", Math.floor( bbox.left ) + "px" );
box_elem.style.setProperty( "width", Math.ceil( bbox.width ) + "px" );
box_elem.style.setProperty( "height", Math.ceil( bbox.height ) + "px" );
const elemBBox = elem.getBoundingClientRect();
const distance_from_top = bbox.top - elemBBox.top;
const dist_elem = document.querySelector( ".vertical-dist" );
dist_elem.style.setProperty( "top", elemBBox.top + "px" );
dist_elem.style.setProperty( "left", elemBBox.left + "px" );
dist_elem.style.setProperty( "width", elemBBox.width - 1 + "px" );
dist_elem.style.setProperty( "height", distance_from_top + "px" );
console.clear();
console.log( "distance from top:", distance_from_top );
};
elem.oninput();
.word {
font-size: 30px;
font-family: sans-serif;
border: 2px solid red;
padding: 20px;
margin: 50px;
line-height: 1;
}
.box {
background: green;
position: absolute;
pointer-events: none;
opacity: 0.3;
}
.vertical-dist {
width: 100%;
position: absolute;
background-color: blue;
opacity: 0.3;
pointer-events: none;
}
<div class="word" contenteditable>man</div>
<div class="box"></div>
<div class="vertical-dist"></div>
但是再说一次,这只适用于最简单的情况,例如它不处理除 1
之外的任何 line-height
,它不支持转换元素和其他恶作剧,并且仅将 textContent 视为 单行文本 .
如何获得两条红线之间的高度(div 的顶部和 div 中当前字体的顶部)?
<div class="word">man</div>
.word {
font-size: ...
font-family: ...
}
我尝试创建 canvas 并使用 measureText 方法:
context.measureText(text);
但我无法在该结果中找到有用的信息...
你有什么想法吗?
您收到的 TextMetrics 对象实际上包含足够的信息让我们知道文本的宽度和高度。
在大多数简单的情况下,我们可以将此信息与父元素的边界框的信息结合起来,以获得 单行 文本的实际边界框。
function getWordBBox( element ) {
// store the context as a property of the function
if( !getWordBBox.ctx ) {
const canvas = document.createElement( "canvas" );
canvas.width = canvas.height = 0; // no need to use any memory
getWordBBox.ctx = canvas.getContext( "2d" );
}
const ctx = getWordBBox.ctx;
// grab computed styles from the element
const {
fontStyle, // copy font styles
fontWeight,
fontSize,
fontFamily,
paddingTop, // get inner offsets
paddingLeft,
borderTopWidth,
borderLeftWidth
} = getComputedStyle( element );
const elemBBox = element.getBoundingClientRect();
// set our context with these settings
ctx.font = [ fontStyle, fontWeight, fontSize, fontFamily ].join( " " );
ctx.textBaseline = "top";
ctx.textAlign = "start";
// grab our TextMetrics object
const metrics = ctx.measureText( element.textContent );
// the BBox
const elem_inner_left = elemBBox.left +
parseFloat( borderLeftWidth ) + parseFloat( paddingLeft );
const elem_inner_top = elemBBox.top +
parseFloat( borderTopWidth ) + parseFloat( paddingTop );
return {
left: metrics.actualBoundingBoxLeft * -1 + elem_inner_left,
top: metrics.actualBoundingBoxAscent * -1 + elem_inner_top,
width: metrics.actualBoundingBoxRight + metrics.actualBoundingBoxLeft,
height: metrics.actualBoundingBoxDescent + metrics.actualBoundingBoxAscent
};
}
const elem = document.querySelector( ".word" );
elem.oninput = (evt) => {
const bbox = getWordBBox( elem );
// simply to check we got the bbox of the text correctly
const box_elem = document.querySelector( ".box" );
box_elem.style.setProperty( "top", Math.floor( bbox.top ) + "px" );
box_elem.style.setProperty( "left", Math.floor( bbox.left ) + "px" );
box_elem.style.setProperty( "width", Math.ceil( bbox.width ) + "px" );
box_elem.style.setProperty( "height", Math.ceil( bbox.height ) + "px" );
const elemBBox = elem.getBoundingClientRect();
const distance_from_top = bbox.top - elemBBox.top;
const dist_elem = document.querySelector( ".vertical-dist" );
dist_elem.style.setProperty( "top", elemBBox.top + "px" );
dist_elem.style.setProperty( "left", elemBBox.left + "px" );
dist_elem.style.setProperty( "width", elemBBox.width - 1 + "px" );
dist_elem.style.setProperty( "height", distance_from_top + "px" );
console.clear();
console.log( "distance from top:", distance_from_top );
};
elem.oninput();
.word {
font-size: 30px;
font-family: sans-serif;
border: 2px solid red;
padding: 20px;
margin: 50px;
line-height: 1;
}
.box {
background: green;
position: absolute;
pointer-events: none;
opacity: 0.3;
}
.vertical-dist {
width: 100%;
position: absolute;
background-color: blue;
opacity: 0.3;
pointer-events: none;
}
<div class="word" contenteditable>man</div>
<div class="box"></div>
<div class="vertical-dist"></div>
但是再说一次,这只适用于最简单的情况,例如它不处理除 1
之外的任何 line-height
,它不支持转换元素和其他恶作剧,并且仅将 textContent 视为 单行文本 .