I'm trying to create a simple app that draws rectangles within the Canvas tag. I've got the Canvas resizing to fullscreen, but whenever I resize the viewport, Canvas clears. I'm trying to prevent it from clearing and just keeping the content thats within it. Any ideas?
http://mediajux.com/experiments/canvas/drawing/
Thanks!
/*
* This is the primary class used for the application
* @author Alvin Crespo
*/
var app = (function(){
var domBod = document.body;
var canvas = null;
var canvasWidth = null;
var canvasHeight = null;
return {
//Runs after the DOM has achieved an onreadystatechange of "complete"
initApplication: function()
{
//setup envrionment variables
canvas = document.getElementById('canvas') || null;
//we need to resize the canvas at the start of the app to be the full window
this.windowResized();
//only set the canvas height and width if it is not false/null
if(canvas)
{
canvasWidth = canvas.offsetWidth;
canvasHeight = canvas.offsetHeight;
}
//add window events
window.onresize = this.windowResized;
circles.canvas = canvas;
circles.canvasWidth = canvasWidth;
circles.canvasHeight = canvasHeight;
circles.generateCircles(10);
setInterval(function(){
circles.animateCircles();
}, 50);
},
/**
* Executes Resizing procedures on the canvas element
*/
windowResized: function()
{
(this.domBod === null) ? 'true' : 'false';
try{
console.log(canvas);
canvas.setAttribute('width', document.body.clientWidth);
canvas.setAttribute('height', document.body.clientHeight);
}catch(e) {
console.log(e.name + " :: " + e.message);
}
},
/**
* Returns the canvas element
* @returns canvas
*/
getCanvas: function()
{
return canvas;
}
};
})();
I believe you have implement a listener for screen resize and redraw the canvas content when that listener fires.
Setting the canvas width attribute will clear the canvas. If you resize the style width (e.g. canvas.style.visibility), it will scale (usually not in such a pretty way). If you want to make the canvas bigger but keep the elements in it as they are, i would suggest storing the canvas as an image -- e.g. call the toDataURL method to get the image, then draw that to the resized canvas with drawImage().
Here's how I solved this problem with JS3.
Internally, I store the main canvas and context as _canvas and _context respectively.
function resize(w, h){
// create a temporary canvas obj to cache the pixel data //
var temp_cnvs = document.createElement('canvas');
var temp_cntx = temp_cnvs.getContext('2d');
// set it to the new width & height and draw the current canvas data into it //
temp_cnvs.width = w;
temp_cnvs.height = h;
temp_cntx.fillStyle = _background; // the original canvas's background color
temp_cntx.fillRect(0, 0, w, h);
temp_cntx.drawImage(_canvas, 0, 0);
// resize & clear the original canvas and copy back in the cached pixel data //
_canvas.width = w;
_canvas.height = h;
_context.drawImage(temp_cnvs, 0, 0);
}
JS3 also provides an autoSize flag which will automatically resize your canvas to the browser window or the dimensions of its parent div.
Set canvas size with style (css) and do not change attributes.
After resize to fullscreen
Canvas will be resized and not cleared, but will be scaled, than to prevent scale - you need rescale after resize, here is math:
var oldWidth = $("canvas").css("width").replace("px", "");
var oldHeight = $("canvas").css("height").replace("px", "");
$("canvas").css({
"width" : window.innerWidth,
"height": window.innerHeight
});
var ratio1 = oldWidth/window.innerWidth;
var ratio2 = oldHeight/window.innerHeight;
canvas.ctx.scale(ratio1, ratio2);
Please note, that I made copy paste from my code and do some changes with ids and vars names for fast, so could have some small mistkaes like "canvas.ctx" or dom calls.
one way I solved this was:
const canvas = document.getElementById('ctx')
const ctx = canvas.getContext('2d')
var W = canvas.width, H = canvas.height
function resize() {
let temp = ctx.getImageData(0,0,W,H)
ctx.canvas.width = window.innerWidth - 99;
ctx.canvas.height = window.innerHeight - 99;
W = canvas.width, H = canvas.height
ctx.putImageData(temp,0,0)
}
the only issue is that on zooming back out you lose the data that was outside the canvas
I had the same issue with my canvas and I have resolved that issue. Please refer the below code. I hope you will resolved the issue using this.
Note : Set alwaysDraw: true
in the parameters
HTML
<div id="top-wraper">
<div id="canvas"></div>
</div>
<!-- div used to create our plane -->
<div class="plane" data-vs-id="plane-vs" data-fs-id="plane-fs">
<!-- image that will be used as a texture by our plane -->
<img src="texture-img.png" alt="Leo Music - Music from the heart of a Lion"/>
</div>
JS
<script>
function loadAnimation() {
// set up our WebGL context and append the canvas to our wrapper
var webGLCurtain = new Curtains("canvas");
webGLCurtain.width = 50;
// if there's any error during init, we're going to catch it here
webGLCurtain.onError(function () {
// we will add a class to the document body to display original images
document.body.classList.add("no-curtains");
});
// get our plane element
var planeElement = document.getElementsByClassName("plane")[0];
// set our initial parameters (basic uniforms)
var params = {
vertexShaderID: "plane-vs", // our vertex shader ID
fragmentShaderID: "plane-fs", // our framgent shader ID
alwaysDraw: true,
//crossOrigin: "", // codepen specific
uniforms: {
time: {
name: "uTime", // uniform name that will be passed to our shaders
type: "1f", // this means our uniform is a float
value: 0,
},
}
}
// create our plane mesh
var plane = webGLCurtain.addPlane(planeElement, params);
// if our plane has been successfully created
// we use the onRender method of our plane fired at each requestAnimationFrame call
plane && plane.onRender(function () {
plane.uniforms.time.value++; // update our time uniform value
});
}
window.onload = function () {
loadAnimation();
}
</script>
<script id="plane-vs" type="x-shader/x-vertex">
#ifdef GL_ES
precision mediump float;
#endif
// those are the mandatory attributes that the lib sets
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
// those are mandatory uniforms that the lib sets and that contain our model view and projection matrix
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
// our texture matrix uniform (this is the lib default name, but it could be changed)
uniform mat4 uTextureMatrix0;
// if you want to pass your vertex and texture coords to the fragment shader
varying vec3 vVertexPosition;
varying vec2 vTextureCoord;
void main() {
vec3 vertexPosition = aVertexPosition;
gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);
// set the varyings
// thanks to the texture matrix we will be able to calculate accurate texture coords
// so that our texture will always fit our plane without being distorted
vTextureCoord = (uTextureMatrix0 * vec4(aTextureCoord, 0.0, 1.0)).xy;
vVertexPosition = vertexPosition;
}
</script>
<script id="plane-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
// get our varyings
varying vec3 vVertexPosition;
varying vec2 vTextureCoord;
// the uniform we declared inside our javascript
uniform float uTime;
// our texture sampler (default name, to use a different name please refer to the documentation)
uniform sampler2D uSampler0;
void main() {
// get our texture coords
vec2 textureCoord = vTextureCoord;
// displace our pixels along both axis based on our time uniform and texture UVs
// this will create a kind of water surface effect
// try to comment a line or change the constants to see how it changes the effect
// reminder : textures coords are ranging from 0.0 to 1.0 on both axis
// const float PI = 3.141592;
const float PI = 2.0;
textureCoord.x += (
sin(textureCoord.x * 10.0 + ((uTime * (PI / 3.0)) * 0.031))
+ sin(textureCoord.y * 10.0 + ((uTime * (PI / 2.489)) * 0.017))
) * 0.0075;
textureCoord.y += (
sin(textureCoord.y * 20.0 + ((uTime * (PI / 2.023)) * 0.00))
+ sin(textureCoord.x * 20.0 + ((uTime * (PI / 3.1254)) * 0.0))
) * 0.0125;
gl_FragColor = texture2D(uSampler0, textureCoord);
}
</script>
<script src="https://www.curtainsjs.com/build/curtains.min.js" ></script>
来源:https://stackoverflow.com/questions/5517783/preventing-canvas-clear-when-resizing-window