如何在更改后的Flexbox网格中获取Vue元素的更新CSS宽度?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在更改后的Flexbox网格中获取Vue元素的更新CSS宽度?相关的知识,希望对你有一定的参考价值。
这是我的头擦。也许我在Vue生命周期中没有看到应该考虑的东西。我将尝试使其尽可能简单。
我有一个自定义按钮组件,该组件正在由flex网格容器调整大小。网格看起来像这样:
<template>
<div class="component d-flex flex-column flex-grow-1" style="min-height: 0">
<div class="justify-center align-content-center"
style="display: grid; width: 100%; height: 100%; grid-gap: 1rem;
grid-template-columns: repeat(12, minmax(0, 1fr));
grid-template-rows: repeat(8, minmax(0, 1fr));">
<slot/>
</div>
</div>
</template>
我有一个看起来像这样的网格面板:
<template>
<v-card :style="cardStyle" v-bind="$attrs">
<slot></slot>
</v-card>
</template>
<script>
export default
computed:
cardStyle: function()
return 'grid-column: span ' + (this.columns || 2) +
'; grid-row: span ' + (this.rows || 2) + ';';
,
props:
columns: [Number, String],
rows: [Number, String],
</script>
“我的按钮”使用面板来像这样调整大小:
<template>
<grid-panel ref="elm" :columns='columns || 2' :rows='rows || 2' elevation="0">
<v-btn class="ma-0 align-stretch flex-column py-4"
width="100%" max-width="100%" height="100%" :color="color || 'rgba(0,0,0,0)'">
<div class="d-flex fill-height py-2" style="width:100%;">
<div ref="iconTest" class="fill-height">
<v-icon ref="icon" class="mb-0 flex-shrink-1 notransition py-0 pr-2" :color="iconColor" style="width:auto; height:auto"> icon </v-icon>
</div>
<div ref="text" class="flex-grow-1 d-flex align-center text-center">
<span ref="innerSpan" style="font-size: 1px" class="textFitted text-center d-inline-block notransition">
label
</span>
</div>
</div>
</v-btn>
</grid-panel>
</template>
我知道这看起来很烂,但是请耐心等待一秒钟。
我想要一种方法,以确保我放在此按钮中的任何文本或标签都不会被剪切。并不是说我会有大量的文本作为标签,但是与网络上的传统按钮不同,根据按钮在网格中的放置方式,这些按钮将具有固定的大小;网格将根据其显示的屏幕调整自身大小。为了解决此问题,我想自动调整文本大小以填充可用空间。因此,使用JS我想到了:
// Calculate height without padding.
innerHeight(el)
var style = window.getComputedStyle(el, null);
return el.clientHeight -
parseInt(style.getPropertyValue('padding-top'), 10) -
parseInt(style.getPropertyValue('padding-bottom'), 10);
,
// Calculate width without padding.
innerWidth(el)
var style = window.getComputedStyle(el, null);
return el.clientWidth -
parseInt(style.getPropertyValue('padding-left'), 10) -
parseInt(style.getPropertyValue('padding-right'), 10);
,
updateFontSize()
if (!this.isMounted || this.$refs.text == undefined)
return;
// Everything below here is taken from the textFit JS library
// https://github.com/STRML/textFit/blob/master/textFit.js
// By default - the library does not work well with Vue, and I had to modify it some
let el = this.$refs.text;
let innerSpan = this.$refs.innerSpan;
innerSpan.style.fontSize = '1px';
let originalWidth = this.innerWidth(el);
let originalHeight = this.innerHeight(el);
console.log(el);
console.log(originalWidth);
// Don't process if we can't find box dimensions
if (!originalWidth || !originalHeight)
throw new Error('Set a static width on the target element ' + el.outerhtml +
' before using textFit!');
let low = 4;
let high = 36;
let mid;
// Binary search for highest best fit
let size = low;
while (low <= high)
mid = (high + low) >> 1;
innerSpan.style.fontSize = mid + 'px';
if(innerSpan.scrollWidth <= originalWidth && innerSpan.clientHeight <= originalHeight)
size = mid;
low = mid + 1;
else
high = mid - 1;
// found, updating font if differs:
innerSpan.style.fontSize = size + 'px';
,
它相对容易理解,并且效果很好。所有这些操作都是查看div中包含文本的可用空间,由于使用了flexbox,该空间被设置为填充该空间,并增大文本直到溢出为止。
然后我想,我也可以对图标做同样的事情....?
好的,这就是我开始困惑的地方。
图标调整大小本身就可以了。编辑::实际上,我想我可能错了...我只是在玩这个,我发现了一些有趣的东西。请参阅下面的编辑。
我认为首先需要确定图标的大小,这将允许CSS增大和缩小2个flex项目,然后调整文本大小。这是用于调整图标大小的代码,您将看到一堆console.logs并注释掉了一些残骸,这些残骸是我拔掉头发的残余。
let widthOnly = this.rows != 1;
let heightOnly = this.rows == 1;
let el = this.$refs.iconTest;
let innerSpan = this.$refs.icon.$el;
let el2 = this.$refs.text;
console.log('text elem before:');
console.log(el2);
console.log(this.innerWidth(el2));
this.$refs.innerSpan.style.fontSize = '1px';
innerSpan.style.fontSize = '1px';
let originalWidth = this.innerWidth(el);
let originalHeight = this.innerHeight(el);
// Don't process if we can't find box dimensions
if (!originalWidth || !originalHeight)
throw new Error('Set a static width on the target element ' + el.outerHTML +
' before using textFit!');
console.log('text elem during 1:');
console.log(el2);
console.log(this.innerWidth(el2));
innerSpan.style.fontSize = originalHeight + 'px';
let low = 4;
let high = 80;
let mid;
// Binary search for highest best fit
let size = low;
while (low <= high)
mid = (high + low) >> 1;
innerSpan.style.fontSize = mid + 'px';
if((heightOnly || innerSpan.clientWidth <= originalWidth) && (widthOnly || innerSpan.clientHeight <= originalHeight))
size = mid;
low = mid + 1;
else
high = mid - 1;
// found, updating font if differs:
innerSpan.style.fontSize = size + 'px';
// this.iconSize = size + 'px';
// THIS IS WHERE HELL HAPPENS
console.log('text elem after:');
console.log(el2);
console.log(" BEFORE DELAY !!! ");
console.log(this.innerWidth(this.$refs.text)); // <-- This should be calculated after the icon has completely resized.
setTimeout(() =>
console.log(" AFTER DELAY !!!! ");
console.log(this.innerWidth(this.$refs.text)); // <-- This gets the correct value after a 2 second time out.
//this.updateFontSize();
, 2000);
this.$nextTick(this.$nextTick(() =>
console.log('text elem next:');
console.log(el2);
console.log(this.innerWidth(el2)); // <-- This outputs the same as before the delay
));
//this.updateFontSize();
正如我所说,调整图标大小的实际行为很好。上面的代码中的el2是对文本容器的引用。这里发生的事情是,文本容器的宽度花费了大量时间才能从CSS计算中获取更新的正确值。控制台输出如下所示:
text elem before:
60
text elem during 1:
74
text elem after:
BEFORE DELAY !!!
59
text elem next:
59
AFTER DELAY !!!!
48
59是修改图标大小后直接获得的值。在这种情况下,48是正确的值,但我只能通过在任意超时后进行设置来获得该值。我已经获得了正确的值,超时值低至121ms,但是在120时它又过时了。这里的问题是,使用正确的值,我的文本标签会正确调整大小,如下所示:
但是如果我很快运行updateFontSize并返回错误的宽度,则会得到以下信息:
使用$ nexttick不能解决它。
我已尽力在codesandbox上重新创建了此文件,但有点奇怪。也许看看是否需要更多背景信息:codesandbocklink
除了增加延迟之外,我没有其他想法。
旁注:这并非旨在作为一种响应式设计或类似的东西。这是针对信息亭类型的应用程序。调整大小的文本仅在安装的组件上发生一次。
编辑::好的,这有点奇怪。在玩了一些之后,尝试制作此按钮的方形版本。它看起来应该像这样:
但是相反,它像这样出来:
这是输出:
因为这是一个方形图标,所以结果应该是宽度与字体大小相同,如下所示:
所以我有了新的理论...页面加载后字体大小是否有可能改变?还是更确切地说,图标的宽度在已经计算之后就改变了?好吧,事实证明..是的!它是!我将图标替换为不需要加载任何外部字体的标准文本,并且:
成功!
Sooooo ......这完全取决于MDI图标包的加载时间...
所以我想这个问题的重点现在转移到了...
如何检测vdit中的mdi图标何时完成加载?
这是我的头擦。也许我在Vue生命周期中没有看到应该考虑的东西。我将尝试使其尽可能简单。我有一个自定义按钮...
也许您需要ResizeObserver。
确定这是字体无法快速加载的情况后,答案很简单:
以上是关于如何在更改后的Flexbox网格中获取Vue元素的更新CSS宽度?的主要内容,如果未能解决你的问题,请参考以下文章
如何获取 javascript 中用于 flexbox 和网格布局的行数和列数?