2

I've written a simple script in JS. When I put hit it into html document (at the bottom of body tag), it works fine. When I try to put it into external document and I link it, script runs but the canvas element disappears (just checked: it works when I put the script in the bottom, but not in head tag). This version works:

   var c = document.getElementById("canvasId");
   var ctx = c.getContext("2d"); 
   var text = "Nazwa pomiaru";
   var boxWidth = 200;
   var boxHeight = 200;
   var minValue = 0;
   var maxValue = 100;
   var midValue = (Math.abs(minValue) + Math.abs(maxValue))/2;
   var unit = "%";
   var indicWidth = 50;
   var indicHeight = 0.6 * boxHeight;
   var textPosition = 0.875;
   var leftMargin = 0.375;
   var topMargin = 0.15;
   var bottomMargin = 0.75;
   var value = Math.floor(Math.random() * 101);
   var warningTop = 90;
   var dangerTop = 95;
   var warningBottom = 10;
   var dangerBottom = 5;
   var thresholdTrasparency = 0.6;
   var strokeColor = "#CCCCCC";
   var valueColor = "#993333";
   var warningColor = "#ff6600";
   var dangerColor = "#cc0000";
   var textColor = "#000000";
   var textColor2 = "#ffffff";
   ctx.beginPath();
   ctx.fillText((maxValue + unit), (leftMargin * boxWidth - ctx.measureText(maxValue + unit).width-1), (topMargin * boxHeight + 3), (boxWidth / 4)); //draw a maxValue
   ctx.fillText((midValue + unit), (leftMargin * boxWidth - ctx.measureText(midValue + unit).width-1), ((topMargin + bottomMargin) / 2 * boxHeight + 3), (boxWidth / 4)); //draw a midValue
   ctx.fillText((minValue + unit), (leftMargin * boxWidth - ctx.measureText(minValue + unit).width-1), (bottomMargin * boxHeight + 3), (boxWidth / 4)); //draw a minValue  
   ctx.fillText(text, ((boxWidth - ctx.measureText(text).width) / 2), (textPosition * boxHeight), (textPosition * boxWidth)); //type a text
   ctx.lineWidth = "0";
   ctx.globalAlpha = thresholdTrasparency;
   if (warningTop !== 0 || warningBottom !== 0) {
    ctx.fillStyle = warningColor;
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight), indicWidth, ((100 - warningTop) * (indicHeight / 100))); //draw a warningTop
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight + (100 - warningBottom) * (indicHeight / 100)), indicWidth, (indicHeight - (100 - warningBottom) * (indicHeight / 100))); //draw a warningBottom 
   }
   if (dangerTop !== 0 || dangerBottom !== 0) {
    ctx.fillStyle = dangerColor;
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight), indicWidth, ((100 - dangerTop) * (indicHeight / 100))); //draw a dangerTop
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight + (100 - dangerBottom) * (indicHeight / 100)), indicWidth, (indicHeight - (100 - dangerBottom) * (indicHeight / 100))); //draw a dangerBottom 
   }
   ctx.beginPath();
   ctx.globalAlpha = 1;
   ctx.fillStyle = valueColor;
   ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight + (100 - value) * (indicHeight / 100)), indicWidth, (indicHeight - (100 - value) * (indicHeight / 100))); //draw a valueIndicator
   if (value <= 47) {
    ctx.fillStyle= textColor;
   }
   else {
    ctx.fillStyle = textColor2;
   }
   ctx.fillText(value, ((boxWidth - ctx.measureText(value).width) / 2), (boxHeight / 2));
   ctx.shadowBlur = 6;
   ctx.shadowColor = "#000000";
   ctx.lineWidth="2";
   ctx.strokeStyle = strokeColor;
   ctx.strokeRect((leftMargin * boxWidth), (topMargin * boxHeight), indicWidth, indicHeight); //draw a rectangle
   ctx.shadowBlur = 0;
   document.write(value); 
<!doctype html>
<html>
 <head>
  <title>Slider</title>
 </head>
 <body>
  <canvas id="canvasId" style="border: 3px solid; background: #ffffff;" width="200px" height="200px">
  No support.
  </canvas>
  <script src="canvas.js"></script>
 </body>
</html>

This version does not work:

function draw () {
   var c = document.getElementById("canvasId");
   var ctx = c.getContext("2d"); 
   var text = "Nazwa pomiaru";
   var boxWidth = 200;
   var boxHeight = 200;
   var minValue = 0;
   var maxValue = 100;
   var midValue = (Math.abs(minValue) + Math.abs(maxValue))/2;
   var unit = "%";
   var indicWidth = 50;
   var indicHeight = 0.6 * boxHeight;
   var textPosition = 0.875;
   var leftMargin = 0.375;
   var topMargin = 0.15;
   var bottomMargin = 0.75;
   var value = Math.floor(Math.random() * 101);
   var warningTop = 90;
   var dangerTop = 95;
   var warningBottom = 10;
   var dangerBottom = 5;
   var thresholdTrasparency = 0.6;
   var strokeColor = "#CCCCCC";
   var valueColor = "#993333";
   var warningColor = "#ff6600";
   var dangerColor = "#cc0000";
   var textColor = "#000000";
   var textColor2 = "#ffffff";
   ctx.beginPath();
   ctx.fillText((maxValue + unit), (leftMargin * boxWidth - ctx.measureText(maxValue + unit).width-1), (topMargin * boxHeight + 3), (boxWidth / 4)); //draw a maxValue
   ctx.fillText((midValue + unit), (leftMargin * boxWidth - ctx.measureText(midValue + unit).width-1), ((topMargin + bottomMargin) / 2 * boxHeight + 3), (boxWidth / 4)); //draw a midValue
   ctx.fillText((minValue + unit), (leftMargin * boxWidth - ctx.measureText(minValue + unit).width-1), (bottomMargin * boxHeight + 3), (boxWidth / 4)); //draw a minValue  
   ctx.fillText(text, ((boxWidth - ctx.measureText(text).width) / 2), (textPosition * boxHeight), (textPosition * boxWidth)); //type a text
   ctx.lineWidth = "0";
   ctx.globalAlpha = thresholdTrasparency;
   if (warningTop !== 0 || warningBottom !== 0) {
    ctx.fillStyle = warningColor;
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight), indicWidth, ((100 - warningTop) * (indicHeight / 100))); //draw a warningTop
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight + (100 - warningBottom) * (indicHeight / 100)), indicWidth, (indicHeight - (100 - warningBottom) * (indicHeight / 100))); //draw a warningBottom 
   }
   if (dangerTop !== 0 || dangerBottom !== 0) {
    ctx.fillStyle = dangerColor;
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight), indicWidth, ((100 - dangerTop) * (indicHeight / 100))); //draw a dangerTop
    ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight + (100 - dangerBottom) * (indicHeight / 100)), indicWidth, (indicHeight - (100 - dangerBottom) * (indicHeight / 100))); //draw a dangerBottom 
   }
   ctx.beginPath();
   ctx.globalAlpha = 1;
   ctx.fillStyle = valueColor;
   ctx.fillRect((leftMargin * boxWidth), (topMargin * boxHeight + (100 - value) * (indicHeight / 100)), indicWidth, (indicHeight - (100 - value) * (indicHeight / 100))); //draw a valueIndicator
   if (value <= 47) {
    ctx.fillStyle= textColor;
   }
   else {
    ctx.fillStyle = textColor2;
   }
   ctx.fillText(value, ((boxWidth - ctx.measureText(value).width) / 2), (boxHeight / 2));
   ctx.shadowBlur = 6;
   ctx.shadowColor = "#000000";
   ctx.lineWidth="2";
   ctx.strokeStyle = strokeColor;
   ctx.strokeRect((leftMargin * boxWidth), (topMargin * boxHeight), indicWidth, indicHeight); //draw a rectangle
   ctx.shadowBlur = 0;
   document.write(value); 
};

window.onload = draw;
<!doctype html>
<html>
 <head>
  <title>Slider</title>
 </head>
 <body>
  <canvas id="canvasId" style="border: 3px solid; background: #ffffff;" width="200px" height="200px">
  No support.
  </canvas>
  <script src="canvas.js"></script>
 </body>
</html>

The second version someway hides canvas tag but the text appears (so the script works).

Is there any solution for this?

x--
  • 25
  • 5

3 Answers3

3

The reason why your canvas (and the entire document, for that matter) disappears is because you are using document.write. In the first snippet, you're writing to the document before it closes the stream. In the case of the second snippet, you're only executing that code after window.onLoad, at which point the document stream is closed.

Note: as document.write writes to the document stream, calling document.write on a closed (loaded) document automatically calls document.open which will clear the document. - https://developer.mozilla.org/en-US/docs/Web/API/Document/write

The solution(s) would be:

1) Don't use document.write - If you need to write to the document, place an HTML element on the page, then write to that element:

 // html:
 <html>
    ...
    <body>
       <p id="output"></p>
    </body>
 </html>

 // Javascript
 // ...
 var el = document.getDocumentById('output');
 el.textContent = value

2) Don't call document.write after page has loaded (as you do in your first snippet)

Personally, I would never use document.write, as you might run into issues such as what you describe.

rodrigo-silveira
  • 10,557
  • 9
  • 55
  • 98
3

The problem is the document.write(value) that is overwriting all body.

Why?

Source

Note: as document.write writes to the document stream, calling document.write on a closed (loaded) document automatically calls document.open which will clear the document.

So, on your second you are doing it on window.onload calling document.open and clearing the document. While on your first version you don't call it onload.

Joel Almeida
  • 7,399
  • 3
  • 22
  • 50
2

Note: as document.write writes to the document stream, calling document.write on a closed (loaded) document automatically calls document.open which will clear the document

Source: Document.write()

Why is document.write considered a “bad practice”?

Community
  • 1
  • 1
w35l3y
  • 7,389
  • 2
  • 35
  • 49