Getting sliders to update HTML canvas

Viewed 458

I'm trying to make a colour selector in JavaScript, so far it works (in Firefox, not chrome) if you select a value in the slider and then refresh the page - displaying the colour in a HTML tag.

However, I want it to refresh the colour real-time, so that the canvas changes colour as you adjust the sliders. I imagine I've made a really simple error, but I just can't figure it out - I would very much appreciate any help/advice!

Example of code on my web page.

I've messed around with using .onchange etc, plus declaring "outputR.value" in the rbg() call, but none of this works. I imagine I need an update function - but I'm not sure where to even start on that.

var sliderR = document.getElementById("myRangeR");
var sliderG = document.getElementById("myRangeG");
var sliderB = document.getElementById("myRangeB");
var outputR = document.getElementById("demoR"); 
var outputG = document.getElementById("demoG"); 
var outputB = document.getElementById("demoB"); 

sliderR.oninput = function() { 
  outputR.innerHTML = this.value;
}
sliderG.oninput = function() {
  outputG.innerHTML = this.value;
}
sliderB.oninput = function() {
  outputB.innerHTML = this.value;
}

outputR.innerHTML = sliderR.value;
outputG.innerHTML = sliderG.value;
outputB.innerHTML = sliderB.value;

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb("+sliderR.value+","+sliderG.value+","+sliderB.value+")";
ctx.fillRect(0, 0, 80, 80);
<p>
  <div class="slidecontainer">
    <p>Red: <span id="demoR"></span>/255</p>
    <input type="range" min="0" max="255" value="128" class="slider" id="myRangeR">

    <p>Green: <span id="demoG"></span>/255</p>
    <input type="range" min="0" max="255" value="128" class="slider" id="myRangeG">

    <p>Blue: <span id="demoB"></span>/255</p>
    <input type="range" min="0" max="255" value="128" class="slider" id="myRangeB">
  <canvas id="myCanvas"></canvas>
  </div>
</p>
<script src="js/canvastest.js"></script>

Expected: HTML canvas element changes colour when sliders are moved.

Actual: Colours only change when page is refreshed (in Firefox), or not at all (chrome).

2 Answers

I'm not seeing a point in which you update the canvas itself. You would want to update the canvas when the value changes such as:

ctx.fillStyle = "rgb(" + [outputR, outputG, outputB].join(', ') + ")";

then rerender with ctx.fillRect(0, 0, 80, 80);.

This would give you something like the following:

var sliderR = document.getElementById("myRangeR");
var sliderG = document.getElementById("myRangeG");
var sliderB = document.getElementById("myRangeB");
var outputR = document.getElementById("demoR"); 
var outputG = document.getElementById("demoG"); 
var outputB = document.getElementById("demoB"); 

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

sliderR.oninput = function() { 
  outputR.innerHTML = this.value;
  updateRect();
}
sliderG.oninput = function() {
  outputG.innerHTML = this.value;
  updateRect();
}
sliderB.oninput = function() {
  outputB.innerHTML = this.value;
  updateRect();
}

outputR.innerHTML = sliderR.value;
outputG.innerHTML = sliderG.value;
outputB.innerHTML = sliderB.value;

function updateRect() {
  ctx.fillStyle = "rgb(" + [outputR, outputG, outputB].map(i => i.innerHTML).join(', ') + ")";
  ctx.fillRect(0, 0, 80, 80);
}

updateRect();
st.js

First things first, you should not enclose your div or another p inside <p> tag. It's wrong structurally.

Now coming to your question, it is not re-rendering as the script is only getting executed on page load.

Try something like this:

var sliderR = document.getElementById("myRangeR");
var sliderG = document.getElementById("myRangeG");
var sliderB = document.getElementById("myRangeB");
var outputR = document.getElementById("demoR"); 
var outputG = document.getElementById("demoG"); 
var outputB = document.getElementById("demoB");
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

myfunc = () => {
  outputR.innerHTML = sliderR.value;
  outputG.innerHTML = sliderG.value;
  outputB.innerHTML = sliderB.value;

  ctx.fillStyle = "rgb("+sliderR.value+","+sliderG.value+","+sliderB.value+")";
  ctx.fillRect(0, 0, 80, 80);
}
myfunc(); // for initialising values on first load
<div>
  <div class="slidecontainer">
    <p>Red: <span id="demoR"></span>/255</p>
    <input type="range" min="0" max="255" value="128" class="slider" id="myRangeR" oninput="myfunc()" >

    <p>Green: <span id="demoG"></span>/255</p>
    <input type="range" min="0" max="255" value="128" class="slider" id="myRangeG" oninput="myfunc()">

    <p>Blue: <span id="demoB"></span>/255</p>
    <input type="range" min="0" max="255" value="128" class="slider" id="myRangeB" oninput="myfunc()">
  <canvas id="myCanvas"></canvas>
  </div>
</div>

Hope it helps!

Related