使用 Javascript 设置元素的宽度会产生意想不到的结果

Posted

技术标签:

【中文标题】使用 Javascript 设置元素的宽度会产生意想不到的结果【英文标题】:Setting width of element using Javascript gives unexpected results 【发布时间】:2018-11-06 00:07:24 【问题描述】:

我正在尝试为学校项目制作 javascript 图像轮播。我正处于制作的早期阶段,但是我已经遇到了问题。

代码如下:

class Carousel
		constructor(selector=".carousel")
			const number = 5;
			const autoscroll = 'off';
			const width = "100%";
			const height  = "200px";
			this.selector = document.querySelector(selector);
			this.number = (this.selector.dataset.viewNumber==undefined)? number : this.selector.dataset.viewNumber;
			this.autoScroll = (this.selector.dataset.autoscroll==undefined)? autoscroll : this.selector.dataset.autoscroll;
			this.width = (this.selector.dataset.width==undefined)? width : this.selector.dataset.width;
			this.height = (this.selector.dataset.height==undefined)? height : this.selector.dataset.height;
		
		makeCarousel()

			let srcList=[];
			let str = "<div class='previous'><p>&larr;</p></div><div class='rotater'>";
			let src;
			for (let i of this.selector.children)
				src = i.getAttribute("src");
				srcList.push(src);
				str= `$str<div class='carousel-img-holder'><img src=$src class='carousel-img' /></div>`;
			
			str=`$str</div><div class='next'><p>&rarr;</p></div>`;
			this.selector.innerhtml = str;
			const styler = this.selector.style;
			styler.width = this.width;
			styler.height = this.height;
			styler.display = "flex";
			const rotate = this.selector.childNodes[1];
			rotate.style.display = "flex";
			rotate.style.height = "100%";
			rotate.style.width = "100%";
			rotate.style.overflow = "scroll";
			for (let i of this.selector.childNodes[1].childNodes)
				let height = this.selector.getBoundingClientRect().height+"px";
				let width = (this.selector.getBoundingClientRect().width/this.number)+"px";
				i.setAttribute('style',`height: $height;width: $width`);
				i.childNodes[0].style.maxWidth = "100%";
				i.childNodes[0].style.maxWidth = "100%";
			
		

	

	const carousel = new Carousel("#carousel");
	carousel.makeCarousel();
	console.log("Width from getBoundingClientRect: "+document.querySelector(".carousel-img-holder").getBoundingClientRect().width)
  console.log("Width from css style: "+document.querySelector(".carousel-img-holder").style.width)
<body style="background: #444">
	<div id="carousel" data-view-number=7 data-autoscroll="on" data- data->
		<img src="https://swachhcoin.com/img/001.png">
		<img src="https://swachhcoin.com/img/002.png">
		<img src="https://swachhcoin.com/img/003.png">
		<img src="https://swachhcoin.com/img/004.png">
		<img src="https://swachhcoin.com/img/006.png">
		<img src="https://swachhcoin.com/img/007.png">
		<img src="https://swachhcoin.com/img/009.png">
		<img src="https://swachhcoin.com/img/010.png">
		<img src="https://swachhcoin.com/img/011.png">
		<img src="https://swachhcoin.com/img/012.png">
		<img src="https://swachhcoin.com/img/013.png">
		<img src="https://swachhcoin.com/img/014.png">
		<img src="https://swachhcoin.com/img/015.png">
	</div>
</body>

我试图一次只在一页上显示data-view-number 属性中提到的图像数量。所以我从getBoundingClientRect().width 计算外部div 的宽度,将其除以data-view-number 值并使用setAttribute 将其分配给样式属性。但是,它并没有按预期出现。所以我检查了物体的宽度。在谷歌开发工具中,显示样式已正确应用。所以我试图通过getBoundingClientRect() 得到它,它完全显示了不同的宽度。是因为我在父级上使用百分比宽度吗?我尝试将其更改为像素宽度,但它不起作用。

我在控制台中打印了两个宽度值。如您所见,这两个宽度并不相等。我不明白为什么。我不明白我做错了什么。任何指针表示赞赏。我不知道这在 jquery 中是否更容易,但我想避免它,因为我们的教授告诉我们尽可能避免使用 jquery。

【问题讨论】:

在 devtools 的 Computed 选项卡中检查宽度或使用 windows.getComputedStyle(DOMObject, propertyName)。这将显示是否有其他属性影响您的结果。 window.getComputedStyle(DOMObject).width 给了我宽度的值,但我不明白我应该如何使用它来调试@zer00ne 【参考方案1】:

您没有考虑下一个和上一个 div 的宽度。你也应该从轮播的宽度中减去它。

基本上逻辑应该是

widthOfImg = (Totalwidth - Width of previous div - Width of next div )/this.number

同时添加如下样式

body 
    margin :0;

也改了这一行

rotate.style.width = "calc(100% - 32px)";

另外,不要对图像应用 max-width,而是对要添加到 carousel-img-holder div 的图像应用相同的宽度

i.childNodes[0].style.width= width ;

查看下面的更新代码

class Carousel
		constructor(selector="#carousel")
			const number = 5;
			const autoscroll = 'off';
			const width = "100%";
			const height  = "200px";
			this.selector = document.querySelector(selector);
			this.number = (this.selector.dataset.viewNumber==undefined)? number : this.selector.dataset.viewNumber;
			this.autoScroll = (this.selector.dataset.autoscroll==undefined)? autoscroll : this.selector.dataset.autoscroll;
			this.width = (this.selector.dataset.width==undefined)? width : this.selector.dataset.width;
			this.height = (this.selector.dataset.height==undefined)? height : this.selector.dataset.height;
		
		makeCarousel()

			let srcList=[];
			let str = "<div class='previous'><p>&larr;</p></div><div class='rotater'>";
			let src;
			for (let i of this.selector.children)
				src = i.getAttribute("src");
				srcList.push(src);
				str= `$str<div class='carousel-img-holder'><img src=$src class='carousel-img' /></div>`;
			
			str=`$str</div><div class='next'><p>&rarr;</p></div>`;
			this.selector.innerHTML = str;
			const styler = this.selector.style;
			styler.width = this.width;
			styler.height = this.height;
			styler.display = "flex";
			const rotate = this.selector.childNodes[1];
			rotate.style.display = "flex";
			rotate.style.height = "100%";
			rotate.style.width = "calc(100% - 32px)";
			for (let i of this.selector.childNodes[1].childNodes)
				let height = this.selector.getBoundingClientRect().height+"px";
				let width = ( (this.selector.getBoundingClientRect().width - document.getElementsByClassName('next')[0].getBoundingClientRect().width - document.getElementsByClassName('previous')[0].getBoundingClientRect().width ) /this.number)+"px";

				i.setAttribute('style',`height: $height;width: $width`);
				i.childNodes[0].style.width= width ;
				i.childNodes[0].style.width= width ;
			
		

	

	const carousel = new Carousel("#carousel");
	carousel.makeCarousel();
<body style="background: #444;margin:0;">
	<div id="carousel" data-view-number=7 data-autoscroll="on" data- data->
		<img src="https://swachhcoin.com/img/001.png">
		<img src="https://swachhcoin.com/img/002.png">
		<img src="https://swachhcoin.com/img/003.png">
		<img src="https://swachhcoin.com/img/004.png">
		<img src="https://swachhcoin.com/img/006.png">
		<img src="https://swachhcoin.com/img/007.png">
		<img src="https://swachhcoin.com/img/009.png">
		<img src="https://swachhcoin.com/img/010.png">
		<img src="https://swachhcoin.com/img/011.png">
		<img src="https://swachhcoin.com/img/012.png">
		<img src="https://swachhcoin.com/img/013.png">
		<img src="https://swachhcoin.com/img/014.png">
		<img src="https://swachhcoin.com/img/015.png">
	</div>
</body>

【讨论】:

这并不能解决您的 sn-p 中显示的问题。 实际上还没有修复。从 getClientBoundingRect() 检查宽度和从 style.width 检查宽度是非常不同的。我的最终目标是仅在视口中显示 this.number 中指定的图像数量。如果您有更好的方法来做到这一点,那也会很有帮助。 已更新答案,请检查这是否是您想要的...? 是的,这正是我所需要的。谢谢你。如果可能的话,您能否详细说明您的答案,以解释您做了哪些更改? 已更新答案,请查收。

以上是关于使用 Javascript 设置元素的宽度会产生意想不到的结果的主要内容,如果未能解决你的问题,请参考以下文章

滚动条挤占内容宽度,影响布局

获取没有jquery的元素的宽度

高度塌陷问题的解决方案

怎么设置textarea的大小

怎么设置textarea的大小

在标准模式下设置元素宽度或高度