如何获得 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 视为 单行文本 .