如何解决Scratch pad折叠后再次展开尺寸缩小的问题
Scratch Pad折叠后二次展开尺寸缩小问题
问题现象
实现折叠面板内嵌Scratch Pad手写板组件时,首次展开组件宽高显示正常,折叠后再次展开组件尺寸异常缩小:
- 首次展开正常效果:

- 折叠后再次展开异常效果:

原问题实现代码
var coll = document.getElementsByClassName("collapsible"); var i; for (i = 0; i < coll.length; i++) { coll[i].addEventListener("click", function() { this.classList.toggle("active"); var content = this.nextElementSibling; if (content.style.display === "block") { content.style.display = "none"; } else { content.style.display = "block"; } }) }
<head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <body> <h3 class="collapsible" style="padding-top: 2px;" > <span class="material-icons" >keyboard_arrow_right</span>Digital Signature </h3> <div class="signature-main-div"> <h4>Please provide your Signature below in the greenbox .</h4> <scratch-pad accept="c.accept" clear="clear" height="250" width="650" ng-readonly="c.submitted"></scratch-pad> </div> </body> </head>
原因分析
这个问题是display: none隐藏逻辑和Canvas类组件的渲染机制冲突导致的:
- 首次加载展开时,Scratch Pad组件初始化阶段可以正常读取标签上配置的
width="650" height="250"参数,也能获取父容器的有效布局尺寸,所以渲染正常。 - 折叠时给内容容器设置
display: none,会让元素直接从渲染树中移除,不占据任何布局空间。 - 再次展开把容器切回
display: block的瞬间,Scratch Pad内部的Canvas会自动触发尺寸重算,但此时DOM还没完成布局回流,组件拿不到有效的宽高参数,就会 fallback 到最小默认尺寸渲染,最终出现缩小异常。
解决方案
可根据业务场景任选一种方案修复:
- 方案1:替换折叠实现逻辑,不使用
display: none
改用max-height结合overflow的方式实现折叠,让内容容器始终存在于渲染树中,从根源避免组件拿不到布局尺寸的问题,还可以顺手加折叠过渡动画优化体验。参考代码:
对应JS逻辑把切换display的代码,改成切换内容容器的/* 默认折叠状态 */ .signature-main-div { max-height: 0; overflow: hidden; transition: max-height 0.2s ease; } /* 展开状态 */ .signature-main-div.expand { max-height: 500px; /* 设置为大于内容实际高度的固定值即可 */ }expand类名即可。 - 方案2:展开后手动触发组件重绘
如果要保留display: none的折叠逻辑,就在每次展开容器、DOM完成渲染后,手动触发组件的尺寸重算,改动量最小。参考修改后的JS代码:var coll = document.getElementsByClassName("collapsible"); for (let i = 0; i < coll.length; i++) { coll[i].addEventListener("click", function() { this.classList.toggle("active"); var content = this.nextElementSibling; if (content.style.display === "block") { content.style.display = "none"; } else { content.style.display = "block"; // 等DOM回流完成后触发全局重算事件 setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 30); } }) } - 方案3:给组件父容器设置固定宽高
给包裹Scratch Pad的父容器设置和组件匹配的固定宽高,这样组件重算尺寸时可以直接读取到父容器的确定尺寸,不会触发最小尺寸兜底逻辑:.signature-main-div { width: 650px; min-height: 300px; /* 预留标题高度,大于等于画布高度+标题高度即可 */ }
内容的提问来源于stack exchange,提问作者Selrac
相关产品推荐
相关产品推荐

