创建另外的函数,用于改变8个瓶子中的水位。

huangapple go评论65阅读模式
英文:

Create anothers functions with change the water level in 8 bottles

问题

Here is the translated code part you requested:

我有一个条件,当输入值大于100时,会添加另一个瓶子,但我不知道在哪里插入另一个函数,以便显示我需要的其他瓶子的水位,我想设置这个功能用于八个瓶子。我试图在addBottle函数和其他函数中添加一个新函数,但只得到了错误。

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->
    
let inputWaterLevel = document.querySelector('[name=water-level]');
let heightLiquid = +tubeLiquid.getAttribute('height');
let yLiquid = +tubeLiquid.getAttribute('y');
let liquidPercent = heightLiquid/100;

inputWaterLevel.addEventListener('input', updateWaterLevel);

function updateWaterLevel() {
  let value = +this.value;
  
  let height = liquidPercent * value;
  let y = yLiquid + (heightLiquid-height);
  
  tubeLiquid.setAttribute('height', liquidPercent * value )
  tubeLiquid.setAttribute('y', y )

}
    
let addBottle2 = () => {
    inputWaterLevel.id = 'inpId';
    let inpId = document.getElementById('inpId')
    inpId.addEventListener("input", () => {
        if (inpId.value > 100) {
            document.getElementById("bot2").style.display = 'block';
        }
        else if (inpId.value <= 100){
            document.getElementById("bot2").style.display = 'none';
        }
    });
}
addBottle2()
 
<!-- language: lang-css -->

 .cont{
     display: flex;
 }

 #bot2{
     display: none;
 }

<!-- language: lang-html -->

<input type="number" min="0" max="200" value="100" name="water-level" />

<div class="cont">
    <div class="bot1">
        <svg viewBox="0 0 300 300" width="150">
            <clipPath id="clip">
                <rect x="118" y="68" width="64" height="228" rx="20" ry="20" />
            </clipPath>
            <image width="300" xlink:href="https://i.ibb.co/HGFQYTj/bottle.png" />
            <rect clip-path="url(#clip)" id="tubeLiquid" x="115" y="58" width="70" height="233" fill="#74ccf4" />
        </svg>
    </div>

    <div id="bot2">
        <svg viewBox="0 0 300 300" width="150">
            <clipPath id="clip2">
                <rect x="118" y="68" width="64" height="228" rx="20" ry="20" />
            </clipPath>
            <image width="300" xlink:href="https://i.ibb.co/HGFQYTj/bottle.png" />
            <rect clip-path="url(#clip2)" id="tubeLiquid2" x="115" y="58" width="70" height="233" fill="#74ccf4" />
        </svg>
    </div>

</div>

<!-- end snippet -->

Please note that I've translated the code part you provided, as per your request. If you have any specific questions or need further assistance with this code, feel free to ask.

英文:

I have a condition that when the input value is greater than 100, another bottle is added, but I don't know where to insert another functions so that the anothers bottles displays the water level I need, i want set this for eight bottles. I was trying to add a new function to a function addBottle ans others function, but only got errors

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let inputWaterLevel = document.querySelector(&#39;[name=water-level]&#39;);
let heightLiquid = +tubeLiquid.getAttribute(&#39;height&#39;);
let yLiquid = +tubeLiquid.getAttribute(&#39;y&#39;);
let liquidPercent = heightLiquid/100;
inputWaterLevel.addEventListener(&#39;input&#39;, updateWaterLevel);
function updateWaterLevel() {
let value = +this.value;
let height = liquidPercent * value;
let y = yLiquid + (heightLiquid-height);
tubeLiquid.setAttribute(&#39;height&#39;, liquidPercent * value )
tubeLiquid.setAttribute(&#39;y&#39;, y )
}
let addBottle2 = () =&gt; {
inputWaterLevel.id = &#39;inpId&#39;;
let inpId = document.getElementById(&#39;inpId&#39;)
inpId.addEventListener(&quot;input&quot;, () =&gt; {
if (inpId.value &gt; 100) {
document.getElementById(&quot;bot2&quot;).style.display = &#39;block&#39;;
}
else if (inpId.value &lt;= 100){
document.getElementById(&quot;bot2&quot;).style.display = &#39;none&#39;;
}
});
}
addBottle2()

<!-- language: lang-css -->

 .cont{
display: flex;
}
#bot2{
display: none;
}

<!-- language: lang-html -->

&lt;p&gt;&lt;input type=&quot;number&quot; min=&quot;0&quot; max=&quot;200&quot; value=&quot;100&quot; name=&quot;water-level&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;cont&quot;&gt;
&lt;div class=&quot;bot1&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip)&quot; id=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div id=&quot;bot2&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip2&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip2)&quot; id=&quot;tubeLiquid2&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

答案1

得分: 1

以下是您要翻译的内容:

"你可以做的是重新使用代码来填充第一个瓶子,但使用参数来告诉它要更新哪个瓶子,以及从总百分比中减去多少值,类似这样:"

"理论上,您可以只使用一个事件监听器来更新第二个瓶子,但我不想更改您的代码太多。当您可以时,不要在同一个输入上添加2个监听器,可以将代码放在一个监听器中,这样代码更易于阅读。"

"此外,您的函数addBottle2没有正确命名,因为它并不是添加第二个瓶子,它只是为其设置监听器,然后不应该被调用两次。"

"还有一些可以进行的小优化。请注意,现在的代码不支持不同大小的瓶子,因为该函数使用为第一个瓶子计算的值来计算高度。"

英文:

What you can do is re-use the code to fill the first bottle, but with parameters telling which bottle to update, and which value to subtract from the total percentage, something like this:

<!-- begin snippet: js hide: false console: true babel: null -->

<!-- language: lang-js -->

let inputWaterLevel = document.querySelector(&#39;[name=water-level]&#39;);
let heightLiquid = +tubeLiquid.getAttribute(&#39;height&#39;);
let yLiquid = +tubeLiquid.getAttribute(&#39;y&#39;);
let liquidPercent = heightLiquid/100;
//tell this code to update bottle 1 without offset
inputWaterLevel.addEventListener(&#39;input&#39;, function(){
updateWaterLevel(&#39;tubeLiquid&#39;, 0);
});
function updateWaterLevel(tubeLiquidId, offset) {
let value = +inputWaterLevel.value - offset; //using input variable because &quot;this&quot; will be not be the input anymore now the call has changed / sutract offset
let height = liquidPercent * value;
let y = yLiquid + (heightLiquid-height);
let tubeLiquid = document.getElementById(tubeLiquidId); //get dynamically liquid to update
tubeLiquid.setAttribute(&#39;height&#39;, liquidPercent * value )
tubeLiquid.setAttribute(&#39;y&#39;, y )
}
let addBottle2 = () =&gt; {
//those 2 lines are useless, you already have access to &quot;inputWaterLevel&quot; from outer scope, just use it
//inputWaterLevel.id = &#39;inpId&#39;;
//let inpId = document.getElementById(&#39;inpId&#39;)
inputWaterLevel.addEventListener(&quot;input&quot;, () =&gt; {
if (inputWaterLevel.value &gt; 100) {
document.getElementById(&quot;bot2&quot;).style.display = &#39;block&#39;;
updateWaterLevel(&#39;tubeLiquid2&#39;, 100); //the call to update bottle 2 telling the function to remove 100
}
else if (inputWaterLevel.value &lt;= 100){
document.getElementById(&quot;bot2&quot;).style.display = &#39;none&#39;;
//no need to update bottle 2 if we&#39;re going to hide it
}
});
}
addBottle2()

<!-- language: lang-css -->

 .cont{
display: flex;
}
#bot2{
display: none;
}

<!-- language: lang-html -->

&lt;p&gt;&lt;input type=&quot;number&quot; min=&quot;0&quot; max=&quot;200&quot; value=&quot;100&quot; name=&quot;water-level&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;cont&quot;&gt;
&lt;div class=&quot;bot1&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip)&quot; id=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div id=&quot;bot2&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip2&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip2)&quot; id=&quot;tubeLiquid2&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

In theory you could update the second bottle using only one event listener, but I didn't want to modifiy your code more than necessary. When you can, don't add 2 listeners to the same input when you can put your code in a single one, it makes the code easier to read

Also your function addBottle2 is not properly named, as it doesn't add a second bottle, it just sets the listener to it, and then shouldn't be called twice.

You have also minor optimisations that can be done. Note also that as it is, the code won't support different size bottles, as the function uses the values calculated for the first bottle's height

答案2

得分: 1

首先,不要直接使用元素的id作为变量来引用它。请参考这个帖子。始终使用适当的方法从DOM中获取元素。

其次,addBottle2函数是多余的。

inputWaterLevel.id = 'inpId';
let inpId = document.getElementById('inpId');

这两行是多余的,因为您已经在inputWaterLevel中获取了输入元素。更改其id并再次通过id获取它不会产生任何有用的效果。只需直接使用它。

inpId.addEventListener("input", () => {...});

这也是多余的,因为您已经添加了事件侦听器updateWaterLevel。您可以简单地在updateWaterLevel中添加代码。

请注意,我只提供了代码部分的翻译,不包括问题的回答或其他内容。

英文:

First, don't refer to the element using its id directly as an variable. See this post. Always use proper method to get the element from the DOM.

Second, the addBottle2 function is redundant.

inputWaterLevel.id = &#39;inpId&#39;;
let inpId = document.getElementById(&#39;inpId&#39;)

These two lines are redundant because you have already get the input element in inputWaterLevel. Changing its id and get it again by id do nothing useful. Just use it as is.

inpId.addEventListener(&quot;input&quot;, () =&gt; {...

This is also redundant because you have already added the event listener updateWaterLevel. You can simply add code in updateWaterLevel

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let inputWaterLevel = document.querySelector(&#39;[name=water-level]&#39;);
//get tubLiquid properly
let tubeLiquid = document.getElementById(&quot;tubeLiquid&quot;);
let heightLiquid = +tubeLiquid.getAttribute(&#39;height&#39;);
let yLiquid = +tubeLiquid.getAttribute(&#39;y&#39;);
let liquidPercent = heightLiquid/100;
//duplicate for second bottle, unless assuming two bottle always have the same size hardcoded.
let tubeLiquid2 = document.getElementById(&quot;tubeLiquid2&quot;);
let heightLiquid2 = +tubeLiquid2.getAttribute(&#39;height&#39;);
let yLiquid2 = +tubeLiquid2.getAttribute(&#39;y&#39;);
let liquidPercent2 = heightLiquid2/100;
let bot2 = document.getElementById(&quot;bot2&quot;);
inputWaterLevel.addEventListener(&#39;input&#39;, updateWaterLevel);
function updateWaterLevel() {
let value = +this.value;
let height = liquidPercent * value;
let y = yLiquid + (heightLiquid-height);
tubeLiquid.setAttribute(&#39;height&#39;, liquidPercent * value );
tubeLiquid.setAttribute(&#39;y&#39;, y );
//bottle2
if(value &gt; 100)
{
let value2 = value - 100;
let height2 = liquidPercent2 * value2;
let y2 = yLiquid2 + (heightLiquid2-height2);
tubeLiquid2.setAttribute(&#39;height&#39;, liquidPercent2 * value2 );
tubeLiquid2.setAttribute(&#39;y&#39;, y2 );
bot2.style.display = &quot;block&quot;;
}  
else
{
bot2.style.display = &quot;none&quot;;
}
}

<!-- language: lang-css -->

.cont{
display: flex;
}
#bot2{
display: none;
}

<!-- language: lang-html -->

&lt;p&gt;&lt;input type=&quot;number&quot; min=&quot;0&quot; max=&quot;200&quot; value=&quot;100&quot; name=&quot;water-level&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;cont&quot;&gt;
&lt;div class=&quot;bot1&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip)&quot; id=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div id=&quot;bot2&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip2&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip2)&quot; id=&quot;tubeLiquid2&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

答案3

得分: 1

你不需要第二个 function 来实现这个。

您可以检查:当输入值大于100时,基于剩余值(value - 100)计算 tubeLiquid2 的高度和位置,然后显示 bot2 div。

let inputWaterLevel = document.querySelector('[name=water-level]');
let tubeLiquid = document.getElementById('tubeLiquid');
let tubeLiquid2 = document.getElementById('tubeLiquid2');
let bottle2 = document.getElementById('bot2');
let liquidPercent = tubeLiquid.getAttribute('height') / 100;
let yLiquid = +tubeLiquid.getAttribute('y')
let heightLiquid = +tubeLiquid.getAttribute('height');
inputWaterLevel.addEventListener('input', updateWaterLevel);
function updateWaterLevel() {
let value = +this.value;
if (value <= 100) {
let height = liquidPercent * value;
let y = yLiquid + (heightLiquid - height);
tubeLiquid.setAttribute('height', height);
tubeLiquid.setAttribute('y', y);
tubeLiquid2.setAttribute('height', 0);
bottle2.style.display = 'none';
} else {
let height1 = liquidPercent * 100;
let y1 = yLiquid + (heightLiquid - height1);
let height2 = liquidPercent * (value - 100);
let y2 = yLiquid + (heightLiquid - height2);
tubeLiquid.setAttribute('height', height1);
tubeLiquid.setAttribute('y', y1);
tubeLiquid2.setAttribute('height', height2);
tubeLiquid2.setAttribute('y', y2);
bottle2.style.display = 'block';
}
}

更新:

在下面的示例中,我们创建了一个动态的水瓶装液体器。

  1. 我们使用 Math.max(Math.ceil(value / 100), 1) 计算 numBottles 变量。这个计算确保即使输入值为0,也至少有一个瓶子存在。我们使用 Math.ceil(value / 100) 将除法结果向上舍入到最接近的整数,表示所需的瓶数。但是,我们取这个结果和 1 的最大值,以确保始终至少有一个瓶子。

  2. for 循环创建所需数量的 div 元素,每个代表一个瓶子。循环从 i = 1 运行到 i <= numBottles。我们使用 bottleDiv.id = bot${i} 动态设置每个 div 元素的 id。在循环内,我们使用与原始代码类似的结构为每个瓶子创建一个 SVG 元素。

  3. 第二个 for 循环遍历 tubeLiquidElements 数组,其中包含每个瓶子的所有液体矩形。在循环内,我们通过从输入值中减去 (i * 100) 计算出每个瓶子的 bottleValue。这个调整后的值确保每个瓶子表示正确的水位,而不会在100的倍数处重复空/满的模式。

  4. 为防止负高度,我们在计算液体高度时添加了 Math.max(bottleValue, 0)。这确保高度始终为0或更高,即使 bottleValue 为负数(对于小于100的值在后续瓶子中)。

简而言之,我们确保第一个瓶子始终存在,即使输入值达到0,而后续的瓶子根据输入值准确表示水位。这里的最大瓶数是6(正如您在评论部分中要求的),因为 input 的属性 max600

let inputWaterLevel = document.querySelector('[name=water-level]');
let container = document.querySelector('.cont');

inputWaterLevel.addEventListener('input', updateWaterLevel);

function updateWaterLevel() {
    // 获取输入值
    let value = +this.value;
    // 计算所需的瓶数,至少为1
    let numBottles = Math.max(Math.ceil(value / 100), 1);
    // 清空容器
    container.innerHTML = '';

    for (let i = 1; i <= numBottles; i++) {
        let bottleDiv = document.createElement('div');
        bottleDiv.id = `bot${i}`;
        bottleDiv.innerHTML = `
        <svg viewBox="0 0 300 300" width="150">
            <clipPath id="clip${i}">
            <rect x="118" y="68" width="64" height="228" rx="20" ry="20" />
            </clipPath>
            <image width="300" xlink:href="https://i.ibb.co/HGFQYTj/bottle.png" />
            <rect clip-path="url(#clip${i})" class="tubeLiquid" x="115" y="58" width="70" height="233" fill="#74ccf4" />
        </svg>`;
        container.appendChild(bottleDiv);
    }

    let tubeLiquidElements = document.querySelectorAll('.tubeLiquid');
    let liquidPercent = tubeLiquidElements[0].getAttribute('height') / 100;
    let yLiquid = +tubeLiquidElements[0].getAttribute('y');
    let heightLiquid = +tubeLiquidElements[0].getAttribute('height');

    for (let i = 0; i < numBottles; i++) {
        let tubeLiquid = tubeLiquidElements[i];
        // 调整后的每个瓶子的值
        let bottleValue = (value - (i * 100));
        let height = (bottleValue >= 100) ? liquidPercent * 100 : liquidPercent * bottleValue;
        let y = yLiquid + (heightLiquid - height);

        tubeLiquid.setAttribute('height', height);
        tubeLiquid.setAttribute('y', y);
    }
}

CSS 部分:

.cont {
    display: flex;
    flex-wrap: wrap;
}

HTML 部分:

<input type="number" min="0" max="600" value="100" name="water-level" />

<div class="cont">
  <!-- 这里是瓶子的容器 -->
</div>
英文:

You don't need a second function to achieve that.

You can check: when the input value is greater than 100, the height and position of tubeLiquid2 are calculated based on the remaining value (value - 100), and the bot2 div is displayed.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let inputWaterLevel = document.querySelector(&#39;[name=water-level]&#39;);
let tubeLiquid = document.getElementById(&#39;tubeLiquid&#39;);
let tubeLiquid2 = document.getElementById(&#39;tubeLiquid2&#39;);
let bottle2 = document.getElementById(&#39;bot2&#39;);
let liquidPercent = tubeLiquid.getAttribute(&#39;height&#39;) / 100;
let yLiquid = +tubeLiquid.getAttribute(&#39;y&#39;)
let heightLiquid = +tubeLiquid.getAttribute(&#39;height&#39;);
inputWaterLevel.addEventListener(&#39;input&#39;, updateWaterLevel);
function updateWaterLevel() {
let value = +this.value;
if (value &lt;= 100) {
let height = liquidPercent * value;
let y = yLiquid + (heightLiquid - height);
tubeLiquid.setAttribute(&#39;height&#39;, height);
tubeLiquid.setAttribute(&#39;y&#39;, y);
tubeLiquid2.setAttribute(&#39;height&#39;, 0);
bottle2.style.display = &#39;none&#39;;
} else {
let height1 = liquidPercent * 100;
let y1 = yLiquid + (heightLiquid - height1);
let height2 = liquidPercent * (value - 100);
let y2 = yLiquid + (heightLiquid - height2);
tubeLiquid.setAttribute(&#39;height&#39;, height1);
tubeLiquid.setAttribute(&#39;y&#39;, y1);
tubeLiquid2.setAttribute(&#39;height&#39;, height2);
tubeLiquid2.setAttribute(&#39;y&#39;, y2);
bottle2.style.display = &#39;block&#39;;
}
}

<!-- language: lang-css -->

.cont{
display: flex;
}
#bot2{
display: none;
}

<!-- language: lang-html -->

&lt;p&gt;&lt;input type=&quot;number&quot; min=&quot;0&quot; max=&quot;200&quot; value=&quot;100&quot; name=&quot;water-level&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;cont&quot;&gt;
&lt;div id=&quot;bot1&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip)&quot; id=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div id=&quot;bot2&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip2&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip2)&quot; id=&quot;tubeLiquid2&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

UPDATE

In the example below, we create a dynamic water bottles filler.

  1. We calculate the numBottles variable using Math.max(Math.ceil(value / 100), 1). This calculation ensures that at least one bottle is present, even when the input value is 0. We use Math.ceil(value / 100) to round up the division result to the nearest integer, indicating the number of bottles required. However, we take the maximum of this result and 1 to ensure that there's always at least one bottle.

  2. The for loop creates the required number of div elements, each representing a bottle. The loop runs from i = 1 to i &lt;= numBottles. We set the id of each div element dynamically using bottleDiv.id = bot${i}.
    Inside the loop, we create an SVG element for each bottle using a similar structure to the original code.

  3. The second for loop iterates through the tubeLiquidElements array, which contains all the liquid rectangles for each bottle. Inside the loop, we calculate the bottleValue for each bottle by subtracting (i * 100) from the input value. This adjusted value ensures that each bottle represents the correct amount of water without repeating the empty/filled pattern at multiples of 100.

  4. To prevent negative heights, we added Math.max(bottleValue, 0) when calculating the height of the liquid. This makes sure that the height is always 0 or greater, even if the bottleValue is negative (for values less than 100 in subsequent bottles).

In short, we ensure that the first bottle is always present, even when the input reaches 0, and the subsequent bottles accurately represent the water level based on the input value. The maximum number of bottles here is 6 (as you asked for in the comments section), since the attribute max of the input is 600.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let inputWaterLevel = document.querySelector(&#39;[name=water-level]&#39;);
let container = document.querySelector(&#39;.cont&#39;);
inputWaterLevel.addEventListener(&#39;input&#39;, updateWaterLevel);
function updateWaterLevel() {
// Get input value
let value = +this.value;
// Calculate the number of bottles required, minimum 1
let numBottles = Math.max(Math.ceil(value / 100), 1); 
// Clear the container
container.innerHTML = &#39;&#39;; 
for (let i = 1; i &lt;= numBottles; i++) {
let bottleDiv = document.createElement(&#39;div&#39;);
bottleDiv.id = `bot${i}`;
bottleDiv.innerHTML = `
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip${i}&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip${i})&quot; class=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;`;
container.appendChild(bottleDiv);
}
let tubeLiquidElements = document.querySelectorAll(&#39;.tubeLiquid&#39;);
let liquidPercent = tubeLiquidElements[0].getAttribute(&#39;height&#39;) / 100;
let yLiquid = +tubeLiquidElements[0].getAttribute(&#39;y&#39;);
let heightLiquid = +tubeLiquidElements[0].getAttribute(&#39;height&#39;);
for (let i = 0; i &lt; numBottles; i++) {
let tubeLiquid = tubeLiquidElements[i];
// Adjusted value for each bottle
let bottleValue = (value - (i * 100)); 
let height = (bottleValue &gt;= 100) ? liquidPercent * 100 : liquidPercent * bottleValue;
let y = yLiquid + (heightLiquid - height);
tubeLiquid.setAttribute(&#39;height&#39;, height);
tubeLiquid.setAttribute(&#39;y&#39;, y);
}
}

<!-- language: lang-css -->

.cont {
display: flex; 
flex-wrap: wrap;
}

<!-- language: lang-html -->

&lt;input type=&quot;number&quot; min=&quot;0&quot; max=&quot;600&quot; value=&quot;100&quot; name=&quot;water-level&quot; /&gt;
&lt;div class=&quot;cont&quot;&gt;
&lt;div class=&quot;bottle&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip)&quot; class=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

答案4

得分: 1

创建第二个函数来管理第二个瓶子的水位。让我们称这个新函数为 updateWaterLevel2()。我们将使用与 updateWaterLevel() 非常相似的逻辑,但它将在 tubeLiquid2 元素上操作。

updateWaterLevel 中,当值超过 100 时,我将添加一个条件检查,并调用 updateWaterLevel2() 来处理超出的部分。在 updateWaterLevel2() 函数内部,我们将调整 tubeLiquid2heighty 属性,就像在 tubeLiquid 中一样。

此外,您需要从 DOM 中选择 tubeLiquid2 元素并获取初始的 heighty 变量值。这些值需要用于计算第二个瓶子内部液体的新 heighty 位置。

// 这是用于更新第一个瓶子内部水位的函数
function updateWaterLevel() {
  let value = +this.value;

  let height = liquidPercent * value;
  let y = yLiquid + (heightLiquid - height);

  // 设置第一个 SVG 元素的新属性
  tubeLiquid.setAttribute('height', liquidPercent * value);
  tubeLiquid.setAttribute('y', y);

  // 检查值是否大于 100 并更新第二个瓶子的值
  if (value > 100) {
    updateWaterLevel2(value - 100);
  } else {
    tubeLiquid2.setAttribute('height', 0);
  }
}

// 用于更新第二个瓶子内部水位的函数
function updateWaterLevel2(value) {
  let height = liquidPercent2 * value;
  let y = yLiquid2 + (heightLiquid2 - height);

  // 设置第二个 SVG 元素的新属性
  tubeLiquid2.setAttribute('height', liquidPercent2 * value);
  tubeLiquid2.setAttribute('y', y);
}

请注意,这是您代码中的一部分,我已经提供了翻译。如果您需要更多帮助或有其他问题,请随时提出。

英文:

<h3> Water Level Task </h3>

Create a second function to manage the water level of the second bottle. Lets call the new function updateWaterLevel2(). We will use a very similar logic to updateWaterLevel(), however it will operate on tubeLiquid2 element instead.

In updateWaterLevel I will add a conditional check when the value goes over 100 and call updateWaterLevel2() with the excess amount. Inside the updateWaterLevel2() function, we will adjust the height and y attributes of tubeLiquid2 just like in tubeLiquid.

Also you need to select the tubeLiquid2 element from the DOM and get the initial height and y variable values. Those values are needed to calculate the new height and y positions of the liquid inside the second bottle.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

// Select elements from the DOM
let inputWaterLevel = document.querySelector(&#39;[name=water-level]&#39;);
let tubeLiquid = document.querySelector(&#39;#tubeLiquid&#39;);
let tubeLiquid2 = document.querySelector(&#39;#tubeLiquid2&#39;);
// Get the initial attributes from the first SVG element
let heightLiquid = +tubeLiquid.getAttribute(&#39;height&#39;);
let yLiquid = +tubeLiquid.getAttribute(&#39;y&#39;);
let liquidPercent = heightLiquid / 100;
// Get the initial attributes from the second SVG element
let heightLiquid2 = +tubeLiquid2.getAttribute(&#39;height&#39;);
let yLiquid2 = +tubeLiquid2.getAttribute(&#39;y&#39;);
let liquidPercent2 = heightLiquid2 / 100;
// Add an event listener to your input field
inputWaterLevel.addEventListener(&#39;input&#39;, updateWaterLevel);
// This is the function to update the water level inside the first bottle
function updateWaterLevel() {
let value = +this.value;
let height = liquidPercent * value;
let y = yLiquid + (heightLiquid - height);
// Set new attributes to first SVG element
tubeLiquid.setAttribute(&#39;height&#39;, liquidPercent * value)
tubeLiquid.setAttribute(&#39;y&#39;, y)
// Check if value is greater than 100 and update second bottle value
if (value &gt; 100) {
updateWaterLevel2(value - 100);
} else {
tubeLiquid2.setAttribute(&#39;height&#39;, 0);
}
}
// The function to update water level inside the second bottle
function updateWaterLevel2(value) {
let height = liquidPercent2 * value;
let y = yLiquid2 + (heightLiquid2 - height);
// Set the new attributes to the second SVG element
tubeLiquid2.setAttribute(&#39;height&#39;, liquidPercent2 * value)
tubeLiquid2.setAttribute(&#39;y&#39;, y)
}
// Function to show or hide the second bottle depending on the input
let addBottle2 = () =&gt; {
inputWaterLevel.id = &#39;inpId&#39;;
let inpId = document.getElementById(&#39;inpId&#39;)
inpId.addEventListener(&quot;input&quot;, () =&gt; {
if (inpId.value &gt; 100) {
document.getElementById(&quot;bot2&quot;).style.display = &#39;block&#39;;
} else {
document.getElementById(&quot;bot2&quot;).style.display = &#39;none&#39;;
}
});
}
// Call function to initialize bottle display
addBottle2();

<!-- language: lang-css -->

.cont {
display: flex;
}
#bot2 {
display: none;
}

<!-- language: lang-html -->

&lt;p&gt;&lt;input type=&quot;number&quot; min=&quot;0&quot; max=&quot;200&quot; value=&quot;100&quot; name=&quot;water-level&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;cont&quot;&gt;
&lt;div class=&quot;bot1&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip)&quot; id=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;div id=&quot;bot2&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip2&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip2)&quot; id=&quot;tubeLiquid2&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

答案5

得分: 1

这是一个脚本,根据输入的值和最大值创建"bottlesOnTheWall"个瓶子,并显示并填充它们,直到达到最大值。

  1. 它创建所有的瓶子,并在需要时显示和隐藏它们。
  2. 它会更新所有瓶子的高度,因为我们可以输入任意数量。
  3. 它不会多次将SVG从DOM中添加或移除。

要将瓶子数量从6个更改为8个,请将最大值更改为800。

const inputWaterLevel = document.querySelector('[name=water-level]');
const div = document.querySelector(".cont");
const svgContainer = document.querySelector('.bot');
const bottlesOnTheWall = Math.floor(inputWaterLevel.max / inputWaterLevel.value);
const bottleCapacity = inputWaterLevel.value;
const totalAmount = inputWaterLevel.max;
const firstTube = svgContainer.querySelector(".tubeLiquid");
const fullHeight = +firstTube.getAttribute('height');
const fullY = +firstTube.getAttribute('y');
const liquidPercent = fullHeight / 100;

const cloneSVG = (svgContainer, idx) => {
  // 克隆svgContainer
  const clone = svgContainer.cloneNode(true);
  // 创建id
  const id = `clip-${idx}`;
  clone.querySelector('clipPath').id = id;
  // 将矩形的剪切路径设置为id
  const rect = clone.querySelector('.tubeLiquid');
  rect.setAttribute('clip-path', `url(#${id})`);
  return clone;
};

Array.from({
  length: bottlesOnTheWall
}).forEach((_, i) => {
  const svgClone = cloneSVG(svgContainer, ++i); // 创建瓶子id=1,id=2
  // 然后将svgClone附加到.cont
  div.appendChild(svgClone);
});

const allBottles = document.querySelectorAll(".bot");

const fillBottles = () => {
  let totalAmount = +inputWaterLevel.value;
  // 满瓶数量
  let fullBottles = Math.floor(totalAmount / bottleCapacity);
  // 计算最后一瓶的剩余量
  let remainder = totalAmount % bottleCapacity;
  if (fullBottles >= bottlesOnTheWall) {
    fullBottles = bottlesOnTheWall;
    remainder = totalAmount - (bottleCapacity * (bottlesOnTheWall - 1));
  }
  let height = liquidPercent * remainder;
  let y = fullY + (fullHeight - height);
  allBottles.forEach((bottle, i) => {
    const tubeLiquid = bottle.querySelector(".tubeLiquid");
    const show = i == 0 || i < fullBottles || (i === (fullBottles) && remainder); // 显示或不显示
    bottle.hidden = !show;
    tubeLiquid.setAttribute('height', (i < fullBottles) ? fullHeight : height);
    tubeLiquid.setAttribute('y', (i < fullBottles) ? fullY : y);
  });
};

inputWaterLevel.addEventListener('input', fillBottles);
fillBottles();
.cont {
  display: flex;
}
<p><input type="number" min="0" max="600" value="100" name="water-level" /></p>

<div class="cont">
  <div class="bot">
    <svg viewBox="0 0 300 300" width="150">
      <clipPath id="clip-0">
        <rect x="118" y="68" width="64" height="228" rx="20" ry="20" />
      </clipPath>
      <image width="300" xlink:href="https://i.ibb.co/HGFQYTj/bottle.png" />
      <rect clip-path="url(#clip-0)" class="tubeLiquid" x="115" y="58" width="70" height="233" fill="#74ccf4" />
    </svg>
  </div>
</div>
英文:

Here is a script that takes the value and max from the input to create bottlesOnTheWall bottles and shows and fills them until max is reached

  1. It creates all the bottles and shows and hides them when needed
  2. It does update ALL the bottles' height since we can enter any amount
  3. it does NOT add or removed the SVGs from the DOM more than once

To change from 6 to 8 bottles, change the max to 800

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const inputWaterLevel = document.querySelector(&#39;[name=water-level]&#39;);
const div = document.querySelector(&quot;.cont&quot;);
const svgContainer = document.querySelector(&#39;.bot&#39;);
const bottlesOnTheWall = Math.floor(inputWaterLevel.max / inputWaterLevel.value);
const bottleCapacity = inputWaterLevel.value;
const totalAmount = inputWaterLevel.max;
const firstTube = svgContainer.querySelector(&quot;.tubeLiquid&quot;);
const fullHeight = +firstTube.getAttribute(&#39;height&#39;);
const fullY = +firstTube.getAttribute(&#39;y&#39;);
const liquidPercent = fullHeight / 100;
console.log(bottlesOnTheWall, bottleCapacity)
const cloneSVG = (svgContainer, idx) =&gt; {
// clone the svgContainer
const clone = svgContainer.cloneNode(true);
// create id
const id = `clip-${idx}`;
clone.querySelector(&#39;clipPath&#39;).id = id;
// set the rect&#39;s clip-path url to the  id
const rect = clone.querySelector(&#39;.tubeLiquid&#39;);
rect.setAttribute(&#39;clip-path&#39;, `url(#${id})`);
return clone;
};
Array.from({
length: bottlesOnTheWall
}).forEach((_, i) =&gt; {
const svgClone = cloneSVG(svgContainer, ++i); // creates bottle id=1, id=2
// then append svgClone to the .cont 
div.appendChild(svgClone);
});
const allBottles = document.querySelectorAll(&quot;.bot&quot;);
const fillBottles = () =&gt; {
let totalAmount = +inputWaterLevel.value
// Number of full bottles
let fullBottles = Math.floor(totalAmount / bottleCapacity);
// Calculate the remainder for the last bottle
let remainder = totalAmount % bottleCapacity;
if (fullBottles &gt;= bottlesOnTheWall) {
fullBottles = bottlesOnTheWall;
remainder = totalAmount - (bottleCapacity * (bottlesOnTheWall - 1));
}
let height = liquidPercent * remainder;
let y = fullY + (fullHeight - height);
allBottles.forEach((bottle, i) =&gt; {
const tubeLiquid = bottle.querySelector(&quot;.tubeLiquid&quot;);
const show = i == 0 || i &lt; fullBottles || (i === (fullBottles) &amp;&amp; remainder); // show or not
bottle.hidden = !show;
tubeLiquid.setAttribute(&#39;height&#39;, (i &lt; fullBottles) ? fullHeight : height)
tubeLiquid.setAttribute(&#39;y&#39;, (i &lt; fullBottles) ? fullY : y)
});
};
inputWaterLevel.addEventListener(&#39;input&#39;, fillBottles)
fillBottles();

<!-- language: lang-css -->

.cont {
display: flex;
}

<!-- language: lang-html -->

&lt;p&gt;&lt;input type=&quot;number&quot; min=&quot;0&quot; max=&quot;600&quot; value=&quot;100&quot; name=&quot;water-level&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;cont&quot;&gt;
&lt;div class=&quot;bot&quot;&gt;
&lt;svg viewBox=&quot;0 0 300 300&quot; width=&quot;150&quot;&gt;
&lt;clipPath id=&quot;clip-0&quot;&gt;
&lt;rect x=&quot;118&quot; y=&quot;68&quot; width=&quot;64&quot; height=&quot;228&quot; rx=&quot;20&quot; ry=&quot;20&quot; /&gt;
&lt;/clipPath&gt;
&lt;image width=&quot;300&quot; xlink:href=&quot;https://i.ibb.co/HGFQYTj/bottle.png&quot; /&gt;
&lt;rect clip-path=&quot;url(#clip-0)&quot; class=&quot;tubeLiquid&quot; x=&quot;115&quot; y=&quot;58&quot; width=&quot;70&quot; height=&quot;233&quot; fill=&quot;#74ccf4&quot; /&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月26日 16:41:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76554981.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定