使用 JavaScript 动态更改背景颜色

Change the background color dynamically of the with JavaScript

我想学习WebGL,我开发了一个项目。

这些数字改变了我的输入值。我写了这段代码。但我想用红-绿-模糊滑块值更改数字颜色。

<script id="fragment-shader" type="x-shader/x-fragment">

precision mediump float;

float myred = 1.0, mygreen = 0.0, myblue = 0.0;
myred = 
void main()
{   
    gl_FragColor = vec4(myred, mygreen, myblue, 1.0 );
}
</script>

我的片段着色器和

的代码
<div>
            R: 0<input id="redSlider" type="range" min="0" max="1" step="0.1" value="1" oninput=redChange(this.value)/>1</div> 
            <div>
            G: 0<input id="greenSlider" type="range" min="0" max="1" step="0.1" value="0" onChange="greensliderChange(this.value)"/>1</div> 
            <div>
            B: 0<input id="blueSlider" type="range" min="0" max="1" step="0.1" value="0" onChange="changeColor(this.value, 2);"/>1</div>
            <br>

我的 HTML 页面中的代码。

我的 JavaScript 页面我添加了滑块值。但是我不能改变片段着色器的值。如何更改 JavaScript 页面上的 HTML 值?

    document.getElementById("redSlider").oninput = function(event) {
//red value
            alert(redSlider);
        };
        document.getElementById("greenSlider").oninput = function(event) {
//green value
        };
        document.getElementById("blueSlider").oninput = function(event) {
//blue value
        };

有时很难找到答案。我只看了 "input range" 上的大约 15 页,但没有一页显示实际如何使用它的示例。所以我明白为什么很难找到一个例子而且我也可以看到不幸的是虽然我将在下面提供一个例子它不会被发现因为这个问题不是关于 "input range"

无论如何,您首先需要知道的是如何使用<input type="range">。您需要添加一个事件侦听器来侦听 'input' event。新值将位于滑块的 value 属性中。

const redSlider = document.querySelector("#redSlider");
redSlider.addEventListener('input', updateRed);

function updateRed {
  console.log(redSlider.value);
}
<input id="redSlider" type="range" min="0" max="1" step="0.1" value="1">

接下来查看您想要在每个滑块左侧显示值的示例。为此,我们必须在 HTML 中更新该值。我发现为此制作一个元素是最简单的。我将使用 <span> 并将其 textContent 属性 设置为滑块的值。

const redSlider = document.querySelector("#redSlider");
const redValueElem = document.querySelector("#redValue");
redSlider.addEventListener('input', updateRed);

function updateRed() {
  redValueElem.textContent = redSlider.value;
};
<div>
R: <span id="redValue"></span>
<input id="redSlider" type="range" min="0" max="1" step="0.1" value="1">
</div>

现在的问题是因为值改变了宽度,例如“0”它不像“0.5”那么宽,输入类型="range" 元素被移动了。为了解决这个问题,我们需要添加一些 CSS 来为值元素提供固定宽度

const redSlider = document.querySelector("#redSlider");
const redValueElem = document.querySelector("#redValue");
redSlider.addEventListener('input', updateRed);

function updateRed() {
  redValueElem.textContent = redSlider.value;
};
.slider>span {
  /* because span defaults to inline it can't have a width */
  display: inline-block;  
  width: 2em;
}
<div class="slider">
R: <span id="redValue"></span>
<input id="redSlider" type="range" min="0" max="1" step="0.1" value="1">
</div>

所以现在您应该可以让您的 3 个滑块正常工作了。

接下来,为了能够将值传递到着色器中,您需要将它们作为 uniforms

传递
precision mediump float;

uniform float myred;
uniform float mygreen;
uniform float myblue;

void main()
{   
    gl_FragColor = vec4(myred, mygreen, myblue, 1.0 );
}

然后您需要查找这些制服的位置并将它们设置为您想要的颜色,然后调用绘制函数。

解释如何使用 WebGL 是一个很大的话题。我建议您阅读 these tutorials.

我还想我应该提一下,您最好将颜色编辑为值数组。

const myColor = [1, 0, 0];

这样可以更轻松地编写更可重用的代码。它还可以更容易地将其传递到 WebGL

uniform vec3 mycolor;

...

  gl_FragColor = vec4(myColor, 1);

function setupRGBSliders(id, color, callback) {
  const ranges = document.querySelectorAll(id + ' input');
  const values = document.querySelectorAll(id + ' span');
  ranges.forEach((rangeElem, ndx) => {
    rangeElem.addEventListener('input', () => {
       const value = rangeElem.value;
       color[ndx] = value;
       update();
       callback();
    });
  });
  
  function update() {
    ranges.forEach((rangeElem, ndx) => {
      rangeElem.value = color[ndx];
      values[ndx].textContent = color[ndx];
    });
  }
  
  update();
  
  return update;
}
  
const myColor = [1, 0.5, 0.3];
setupRGBSliders('#mycolor', myColor, render);

const vs = `
void main() {
  gl_Position = vec4(0, 0, 0, 1);
  gl_PointSize = 100.0;
}
`;

const fs = `
precision mediump float;
uniform vec3 mycolor;
void main() {
  gl_FragColor = vec4(mycolor, 1);
}
`;

const gl = document.querySelector("canvas").getContext("webgl");
const program = twgl.createProgram(gl, [vs, fs]);  // using a helper because too much code
const mycolorLoc = gl.getUniformLocation(program, "mycolor");

render();

function render() {
  gl.useProgram(program);
  gl.uniform3fv(mycolorLoc, myColor);
  const offset = 0;
  const count = 1;
  gl.drawArrays(gl.POINTS, offset, count);
}
.rgb span {
  display: inline-block;  
  width: 2em;
}
<div id="mycolor" class="rgb">
  <div>
    R: <span></span>
    <input type="range" min="0" max="1" step="0.1" value="1">
  </div>
  <div>
    G: <span></span>
    <input type="range" min="0" max="1" step="0.1" value="1">
  </div>
  <div>
    B: <span></span>
    <input type="range" min="0" max="1" step="0.1" value="1">
  </div>
</div>
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>