Polymer组件中clientWidth为0,peaks.js初始化失败求助
解决Polymer中Peaks.js容器宽度为0的问题
这个问题的核心原因很明确:当你的overlay-dialog处于关闭状态时,它内部的#container元素并没有被浏览器渲染出实际的布局尺寸。浏览器对于隐藏元素(比如display: none的元素)不会计算其宽高,所以clientWidth会是0,而Peaks.js初始化时必须依赖容器的实际宽度来生成波形。
下面是具体的修复步骤和代码调整建议:
1. 延迟Peaks.js的初始化时机
不要在ready、attached或者_mediaChanged里直接初始化Peaks,而是等到overlay-dialog完全打开并完成布局后再执行初始化。我们可以监听iron-overlay-opened事件,或者在showAudioDialog里用async方法等待布局完成。
2. 调整组件逻辑
- 先在
_mediaChanged里保存好媒体资源的配置,不要立即初始化Peaks - 在dialog打开后,确保容器已经有了实际宽度,再调用
peaks.init() - 可选:在dialog关闭时销毁Peaks实例,避免内存泄漏
修改后的脚本部分代码示例:
Polymer({ is: 'audiowaveform-dialog', properties: { isOpened: { type: Boolean, value: false }, mediaType: { type: String, value: 'audio/mp3' }, mediaSrc: { type: String, }, options: { type: Object, value: function() { return { container: null, mediaElement: null, dataUri: { arraybuffer: 'sample_21.dat' }, zoomLevels : [8], flags: { segFlag : true, segCallback : function(cb) { // 你的回调逻辑 }, loopFlag : false, loopCallback :function(cb) { var times = cb(); console.log(times); } }, keyboard: false } } }, peaksInstance: { type: Object, value: null } }, observers: [ '_mediaChanged(mediaSrc)' ], ready: function() { this.options.container = Polymer.dom(this.root).querySelector('#container'); this.options.mediaElement = Polymer.dom(this.root).querySelector('audio'); // 监听dialog打开事件 this.$.dialog.addEventListener('iron-overlay-opened', this._onDialogOpened.bind(this)); }, showAudioDialog: function() { if(!this.isOpened) { this.$.dialog.opened = true; this.isOpened = true; } else { console.log("Dialog already opened"); } }, closeDialog: function() { this.$.dialog.opened = false; this.isOpened = false; }, closePerformed: function(e) { // 关闭时销毁Peaks实例 if (this.peaksInstance) { this.peaksInstance.destroy(); this.peaksInstance = null; } }, _mediaChanged: function(mediaSrc) { console.log("_mediaChanged"); // 更新媒体元素的src if (mediaSrc) { this.options.mediaElement.src = mediaSrc; } }, _onDialogOpened: function() { // 用async等待浏览器完成布局计算 this.async(function() { console.log("容器宽度:", this.options.container.clientWidth); if (this.options.container.clientWidth > 0 && !this.peaksInstance) { this.peaksInstance = peaks.init(this.options); } }, 100); // 100ms足够浏览器完成布局,可根据实际调整 } });
3. 额外注意点
- 确保你的
overlay-dialog在打开时是可见的(没有被设置为display: none或者visibility: hidden),Polymer的IronOverlayBehavior默认会在打开时正确处理元素的显示状态 - 如果你的媒体资源是动态加载的,记得在
_mediaChanged里更新options.dataUri和音频元素的src,避免使用固定的sample_21.dat和sample_21.wav
这样调整后,Peaks.js就能获取到容器的实际宽度,顺利初始化波形了。
内容的提问来源于stack exchange,提问作者Sudipta Roy
相关产品推荐
相关产品推荐

