如何让我的窗口大小随屏幕大小自动调整?

时间:2021-06-19 17:03:54

标签: javascript html canvas

首先,我正在制作一个交互式个人网站,让人们可以通过绕着小火箭飞行并通过不同的门户来查看我简历的不同部分。

这是我的 HTML 代码,

    <!DOCTYPE html>
<html>
  <head>
    <title>Space Ship</title>
    <style type="text/css">
        canvas{
            border: 1px solid black;
        }
        body{
            margin: 0;
        }
    </style>
  </head>
  <body>
    
    <canvas id="game"></canvas>
    <script src="game.js"></script>
    
  </body>
</html>

这是javascript代码,

const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth
canvas.height = window.innerHeight;
ctx.font = "30px Arial";
ctx.shadowColor = "rgba(255,255,255,.6)";

// Constants in objects doesnt work cause objects passing as reference and will by modified!
// If you want constant constant, use primitives
const SPACESHIP_SIZE = { width: 15, height: 25 };
const SPACESHIP_POSITION = { x: window.innerWidth/2, y: window.innerHeight/2};
const GRAVITY = 1;
const HOVER_TICKS = 20;
//Update thrust constant
const THRUST = 15;

const Systems = {
    'main': {
        holes:[
            {x: window.innerWidth/8, y: window.innerHeight/3, size: 40, dest: 'Education'},
            {x: window.innerWidth/8, y: window.innerHeight/1.15, size: 40, dest: 'Technical Skills'},
            {x: window.innerWidth/2, y: window.innerHeight/3, size: 40, dest: 'Experience1'},
            {x: window.innerWidth/2, y: window.innerHeight/1.15, size: 40, dest: 'Experience2'},
            {x: window.innerWidth/1.1, y: window.innerHeight/3, size: 40, dest: 'Contact Me'},
        ]
        
    },
    'Education': {holes:[{x: window.innerWidth-100, y: window.innerHeight-100, size: 40, dest: 'main'}]},
    
    'Technical Skills': {holes:[{x: window.innerWidth-100, y: window.innerHeight-100, size: 40, dest: 'main'}]},
    
    'Experience1': {holes:[{x: window.innerWidth-100, y: window.innerHeight-100, size: 40, dest: 'main'}]},
    
    'Experience2': {holes:[{x: window.innerWidth-100, y: window.innerHeight-100, size: 40, dest: 'main'}]},

    'Personal Projects': {holes:[{x: window.innerWidth-100, y: window.innerHeight-100, size: 40, dest: 'main'}]},
    
    'Contact Me': {holes:[{x: window.innerWidth-100, y: window.innerHeight-100, size: 40, dest: 'main'}]},
    
};

let spaceShip;
let currentSystem = 'main';
const spaceObjects = [];

class SpaceObject {
    constructor(size, position, color = 'black', angle = 0) {
        this.color = color;
        this.size = size;
        this.position = position;
        this.angle = angle;
        spaceObjects.push(this);
    }
    tick() {
        this.update();
        this.draw();
    }
    update() {}
    draw() {}
    isAbove({x, y}) {
        return Math.abs(this.position.x - x) < this.size && Math.abs(this.position.y - y) < this.size;
    }
    destroy() {
        spaceObjects.splice(spaceObjects.indexOf(this), 1);
    }
}

class SpaceShip extends SpaceObject {
    constructor(size, position) {
        super(size, position, 'yellow');
        this.aboveHole = 0;
        this.engineOn = false;
        this.rotatingLeft = false;
        this.rotatingRight = false;
        this.velocity = {x: 0, y: 0};
    }

    draw() {
        const triangleCenterX = this.position.x + 0.5 * this.size.width;
        const triangleCenterY = this.position.y + 0.5 * this.size.height;
        ctx.shadowBlur = 0;
        ctx.save();
        ctx.translate(triangleCenterX, triangleCenterY);
        ctx.rotate(this.angle);
        ctx.lineWidth = 5;
        ctx.beginPath();
        // Triangle
        ctx.moveTo(0, -this.size.height / 2);
        ctx.lineTo(-this.size.width / 2, this.size.height / 2);
        ctx.lineTo(this.size.width / 2, this.size.height / 2);
        ctx.closePath();

        ctx.strokeStyle = this.color;
        ctx.stroke();

        ctx.fillStyle = "red";
        ctx.fill();

        // Flame for engine
        if (this.engineOn) {
            const fireYPos = this.size.height / 2 + 4;
            const fireXPos = this.size.width * 0.25;
            ctx.beginPath();
            ctx.moveTo(-fireXPos, fireYPos);
            ctx.lineTo(fireXPos, fireYPos);
            ctx.lineTo(0, fireYPos + Math.random() * 100);
            ctx.lineTo(-fireXPos, fireYPos);
            ctx.closePath();
            ctx.fillStyle = 'orange';
            ctx.fill();
        }
        ctx.restore();
    }

    update() {
        this.moveSpaceShip();
        this.checkAboveHole();
    }

    moveSpaceShip() {
        // Angle has to be in radians
        const degToRad = Math.PI / 180;
        // Change the position based on velocity
        this.position.x += this.velocity.x;
        this.position.y += this.velocity.y;
        // Move spaceship to other side when leaving screen
        this.position.x = (canvas.width + this.position.x) % canvas.width;
        this.position.y = (canvas.height + this.position.y) % canvas.height;
        /*
         Adding floating point numbers to the end of the
         rotaion handling to make roation faster
         */
        if (this.rotatingLeft) this.angle -= (degToRad+.15);
        if (this.rotatingRight) this.angle += (degToRad+.15);


        // Acceleration
        if (this.engineOn) {
            this.velocity.x += (THRUST / 100) * Math.sin(this.angle);
            this.velocity.y -= (THRUST / 100) * Math.cos(this.angle);
        }
        // Update the velocity depending on gravity
        this.velocity.y += GRAVITY / 2500;
    }

    checkAboveHole() {
        const hole = spaceObjects.find(spaceObject => spaceObject !== this && spaceObject.isAbove(this.position));
        if(hole) {
            this.aboveHole++;
            if(this.aboveHole > HOVER_TICKS) {
                confirm(`Jump to system ${hole.dest}?`) && jump(hole);
                this.aboveHole = 0;
            }
        } else {
            this.aboveHole = 0;
        }
    }
}


const circle = (ctx, x, y, radius, color = 'white') => {
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI*2, false);
    ctx.fillStyle = color;
    ctx.fill();
    ctx.stroke();
    ctx.closePath();
};

class BlackHole extends SpaceObject {
    constructor(size, position, dest) {
        super(size, position);
        this.dest = dest;
    }
    update() {
        // Spin?
        this.angle+=.01;
    }
    draw() {
        // Shadow
        ctx.shadowBlur = this.size >>> 2;
        circle(ctx, this.position.x, this.position.y, this.size + 1, `rgba(255, 255, 255, .6)`);
        // Hole
        circle(ctx, this.position.x, this.position.y, this.size, this.color);
        // Spinning view
        circle(ctx, this.position.x + (this.size * Math.sin(this.angle) - 1), this.position.y + (this.size * Math.cos(this.angle) - 1), 2, 'gray');
        circle(ctx, this.position.x - (this.size * Math.sin(this.angle) - 1), this.position.y - (this.size * Math.cos(this.angle) - 1), 2, 'gray');
    }
}

function handleKeyInput(event) {
    const { keyCode, type } = event;
    const isKeyDown = type === 'keydown' ? true : false;

    if (keyCode === 37) spaceShip.rotatingLeft = isKeyDown;
    if (keyCode === 39) spaceShip.rotatingRight = isKeyDown;
    if (keyCode === 38) spaceShip.engineOn = isKeyDown;
}

function jump({dest}) {
    currentSystem = dest || 'main';
    while(spaceObjects.length) spaceObjects[0].destroy();
    Systems[currentSystem].holes.forEach(hole => new BlackHole(hole.size, {x: hole.x, y: hole.y}, hole.dest));
    spaceShip = new SpaceShip(SPACESHIP_SIZE, SPACESHIP_POSITION);
    
}

function draw() {
    // Clear screen
    ctx.fillStyle = 'rgb(0, 10, 60)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = 'rgb(150, 150, 150)';
    ctx.fillText(`--> You are in ${currentSystem}`, 40, 40);
    ctx.fillText(`--> Use the arrow keys to guide the rocket into different portals`, 40, 60);
    ctx.fillText(`--> Refresh the page if you resize your window`, 40, 80);
    
    
    //Adding section/system text information
    if(currentSystem=='main'){
        ctx.font ='bolder 20px Courier New'
        ctx.fillText('Education Portal', window.innerWidth/9, window.innerHeight/4);
        ctx.fillText('Technical Skills Portal', window.innerWidth/9.2, window.innerHeight/1.27);
        ctx.fillText('Experience Portal', window.innerWidth/2, window.innerHeight/4);
        ctx.fillText('Experience Portal', window.innerWidth/2, window.innerHeight/1.27);
        ctx.fillText('Contact Me', window.innerWidth/1.25, window.innerHeight/4);

    }
    if(currentSystem=='Education'){  
        //College
        ctx.font = 'italic 20px Courier New';
        ctx.fillText('Binghamton University, State University of New York, ', 50, 150);
        ctx.fillText('Thomas J. Watson College of Engineering and Applied Science', 50, 170);
        ctx.fillText('Bachelor of Science in Computer Science', 50, 190);
        
        ctx.font = '20px Courier New';
        ctx.fillText('Overall GPA: 3.92', 50, 210);
        ctx.fillText('Major GPA: 4.0', 50, 230);

        ctx.fillText('Relevant Coursework: Programming and Hardware Fundamentals,', 50, 270);
        ctx.fillText('Professional Skills, Ethics, and CS Trends,', 50, 290)
        ctx.fillText('Data Structures and Algorithms, Programming with Objects and Data Structures,', 50, 310);
        ctx.fillText('Architecture from a Programmer Perspective (By Fall 2021)', 50, 330);

        //High School
        ctx.font = 'italic 20px Courier New';
        ctx.fillText('Islip High School', 50, 430);
        ctx.fillText('STEM Academy Honors', 50, 450);
        ctx.font = '20px Courier New';
        ctx.fillText('Overall GPA: 100.77, Top 5% of class', 50, 470);

        ctx.fillText('Return', window.innerWidth-135 , window.innerHeight-155);

    }


    if(currentSystem=='Technical Skills'){
        ctx.font = '20px Courier New';
        ctx.fillText('Languages: Python, Java, HTML, CSS, JavaScript, C++',50 , 150);
        ctx.fillText('Software and OS: VS Code, Eclipse, Sublime Text, Git, Logisim, Anaconda,',50 , 190);
        ctx.fillText('Spyder, Microsoft Office, Linux, MacOS',50 , 210);
        ctx.fillText('Additional: Familiar with MySQL, Arduino',50 , 250);

        ctx.fillText('Return', window.innerWidth-135 , window.innerHeight-155);
    }


    if(currentSystem=='Experience1'){
        ctx.font = '20px Courier New';
        ctx.fillText('Binghamton University Rover Team, Software Engineer | Binghamton, NY',50 , 150);
        ctx.fillText('October 2020 - Prestent',50 , 170);
        
        ctx.fillText('-->Designed networks and code bases using C++ to maximize the efficiency',50 , 190);
        ctx.fillText('   and performance of a model mars rover for The Mars Society University',50 , 210);
        ctx.fillText('   Rover Challenge which takes place yearly', 50, 230);
        
        ctx.fillText('-->Built a custom username/password page by interfacing Google Firebase', 50, 250);
        ctx.fillText('   with a HTML, CSS, and JavaScript page which allowed for user', 50, 270);     
        ctx.fillText('   authentication, permitting members of the team to view classified documents', 50, 290);
        
        ctx.fillText('-->Prepared rover data by implementing Python script from scratch', 50, 310);
        ctx.fillText('   using Matplotlib and NumPy which led to data visualization to be analyzed', 50, 330);

        ctx.fillText('-->Constructed the GUI for the base station computer in C++ so', 50, 350);
        ctx.fillText('   that all the components of the rover could be viewed in the most effective way', 50, 370);
        

        ctx.fillText('JPMorgan Chase, Software Engineering Virtual Experience Program | Remote Role',50 , 460);
        ctx.fillText('July 2020 - September 2020',50 , 480);
        ctx.fillText('-->Modified an interface with a stock price data feed using Python 3 so that the system/data could be analyzed',50 , 500);
        ctx.fillText('-->Implemented the perspective open-source code in preparation for data visualization',50 , 520);
        ctx.fillText('-->Received certificate of completion by end of program',50 , 540);

        ctx.fillText('Return', window.innerWidth-135 , window.innerHeight-155);
    }


    if(currentSystem=='Experience2'){
        ctx.font = '20px Courier New';
        ctx.fillText('Google CSSI, Coursera, Software Engineering Student | Remote Role',50 , 150);
        ctx.fillText('June 2020 - August 2020', 50, 170);
        ctx.fillText('-->Selected to take part in an invite-only Google Tech Student Development program', 50, 190);
        ctx.fillText('-->Developed/designed personal web pages through CodePen using HTML, CSS, and JavaScript', 50, 210);
        ctx.fillText('-->Reviewed, designed, and implemented a green screen algorithm in JavaScript', 50, 230);
        ctx.fillText(' to transform images on our developed web pages', 50, 250);
        ctx.fillText('-->Learned to hide data in images through the use of steganography', 50, 270);
        ctx.fillText('-->Received certificate of completion by end of program', 50, 290);





        ctx.fillText('Return', window.innerWidth-135 , window.innerHeight-155);
    }


    if(currentSystem=='Contact Me'){
        ctx.fillText('Contact Me',50 , 450);
        ctx.fillText('Return', window.innerWidth-135 , window.innerHeight-155);    
    }






    //Loading small stars
    ctx.shadowBlur = 1;
    for (var i = 1, j = 1; j<canvas.height; i+=100, i > canvas.width && (i=1, j+=100), circle(ctx, i, j, 1));

    //loading medium stars
    ctx.shadowBlur = 2;
    for (var i = 1, j = 1; j<canvas.height; i+=150, i > canvas.width && (i=1, j+=150), circle(ctx, i, j, 2));

    //loading larger stars
    ctx.shadowBlur = 3;
    for (var i = 1, j = 1; j<canvas.height; i+=225, i > canvas.width && (i=1, j+=225), circle(ctx, i, j, 3));

    // tick all objects
    spaceObjects.forEach(spaceObject => spaceObject.tick());

    // Repeats
    requestAnimationFrame(draw);
}

// Event Listeners
document.addEventListener('keydown', handleKeyInput);
document.addEventListener('keyup', handleKeyInput);
// Start the game
jump({dest: 'main'});
draw();

到目前为止,我对它的外观相当满意,只是文本和窗口大小等内容的格式看起来很不错。

这是在我的浏览器中打开网站后的样子。 Picture of what the website looks like as of now.

我的问题是,当用户调整窗口时,除非用户刷新网页,否则显示的图片不会自动实时调整。有没有办法解决这个问题?同样,有没有办法让每个门户上方的文本直接出现在每个门户上方,而无需硬编码应该出现在屏幕上的哪个位置?当图片的大小发生变化时,文本会被丢弃,因为它是硬编码的,并且与门户无关。感谢您的任何反馈。

2 个答案:

答案 0 :(得分:2)

要调整大小,请使用事件侦听器。您可以在此处放置任何需要再次调用的函数。这只会调整画布的大小。

window.addEventListener('resize', (e) => {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
})

为了使您的文本与门户对齐,请将门户的位置用作文本的 x 和 y。我从 y 中减去 50 以将其放置在门户上方。也使用 ctx.textAlign = "center";

if(currentSystem=='main'){
        ctx.font ='bolder 20px Courier New';
        ctx.textAlign = "center";
        ctx.fillText('Education Portal', Systems['main'].holes[0].x, Systems['main'].holes[0].y - 50);
        ctx.fillText('Technical Skills Portal', Systems['main'].holes[1].x, Systems['main'].holes[1].y - 50);
        ctx.fillText('Experience Portal', Systems['main'].holes[2].x, Systems['main'].holes[2].y - 50);
        ctx.fillText('Experience Portal', Systems['main'].holes[3].x, Systems['main'].holes[3].y - 50);
        ctx.fillText('Contact Me', Systems['main'].holes[4].x, Systems['main'].holes[4].y - 50);

答案 1 :(得分:0)

所以看起来您需要的是媒体查询和 css,使您的网站能够响应不同的“屏幕”尺寸。

关于在谷歌中查找 flex-box 或 grid 的文本,css 解决方案应该很容易找到类似 https://www.w3.org/Style/Examples/007/center.en.html 的内容

相关问题