canvas造火箭

·  阅读 2293

canvas.png

canvas造火箭

有句话说,面试造火箭,工作拧螺钉。这天,我带着从入门到放弃的心境默默的翻出了我多年前买的却尘封已久的canvas书籍,想着某天我也能在面试时硬气的说我会造火箭。 总结了下造火箭需要以下几个步骤:

1、创建canvas画布

<div id="contain">
      <canvas  id="canvas"></canvas>
</div>

<script>
    let ctx = document.getElementById('canvas'),
        content = ctx.getContext('2d'),
        WIDTH,
        HEIGHT;
        ctx.width = WIDTH = document.documentElement.clientWidth,
        ctx.height = HEIGHT = document.documentElement.clientHeight;
</script>
复制代码

2、每个火箭都是一个Class对象实例

每个class对象实例都包含火箭id,x轴y轴坐标,火箭的主干的长宽,一个size控制大小

class Rocket{
        ...
        constructor(id,x,y,size = 1){
            this.id = id
            this.x = x
            this.y = y
            this.size = size
            this.bodyWidth = 200 * this.size
            this.bodyHeight = 300 * this.size
        }
        ...
  }
复制代码

3、添加火箭的主干

drawRocketBody(){
            content.beginPath()
            content.fillStyle = Rocket.RocketColor
            content.fillRect(this.x,this.y,this.bodyWidth,this.bodyHeight)
            content.ellipse(this.x+this.bodyWidth/2,this.y,this.bodyWidth/2,150,0,0,Math.PI,true)
            content.ellipse(this.x+this.bodyWidth/2,this.y+this.bodyHeight,this.bodyWidth/2,30*this.size,0,0,Math.PI,false)
            content.fill()
  }
复制代码

4、添加火箭主干的logo

       drawRocketBodyLogo(){
            //绘制火箭主体logo
            const outterCircleR = 60
            const innerCircleR = 50
            content.beginPath()
            content.fillStyle = Rocket.RocketBodyLogoColor
            content.arc(this.x+this.bodyWidth/2,this.y,outterCircleR*this.size,0,Math.PI * 2,true)
            content.fill()

            content.beginPath()
            const grd = content.createRadialGradient(this.x+this.bodyWidth/2,this.y,outterCircleR * this.size,this.x,this.y,0)
            grd.addColorStop(0,Rocket.RocketColor)
            grd.addColorStop(1,Rocket.RocketBodyLogoColor)
            content.fillStyle = grd
            content.arc(this.x+this.bodyWidth/2,this.y,innerCircleR*this.size,0,Math.PI * 2,true)
            content.fill()
        }
复制代码

5、添加火箭翅膀

drawRocketWings(){
            content.beginPath()
            const wingsWidth = 60 * this.size
            const wingsHeight = 200 * this.size
            const leftWingOffSet = wingsWidth
            const RightWingOffSet = this.bodyWidth
            content.fillStyle = Rocket.RocketColor
            content.fillRect(this.x-leftWingOffSet,this.y,wingsWidth,wingsHeight)
            content.fillRect(this.x+RightWingOffSet,this.y,wingsWidth,wingsHeight)
            content.ellipse(this.x-leftWingOffSet+wingsWidth/2,this.y+wingsHeight,wingsWidth/2,20,0,0,Math.PI,false)
            content.ellipse(this.x+RightWingOffSet+wingsWidth/2,this.y+wingsHeight,wingsWidth/2,20,0,0,Math.PI,false)
            content.fill()
            //绘制火箭翼颜色
            content.beginPath()
            content.ellipse(this.x-leftWingOffSet+wingsWidth/2,this.y,wingsWidth/2,50,0,0,Math.PI,true)
            content.ellipse(this.x-leftWingOffSet+wingsWidth/2,this.y,wingsWidth/2,20,0,0,Math.PI,false)
            content.ellipse(this.x+RightWingOffSet+wingsWidth/2,this.y,wingsWidth/2,50,0,0,Math.PI,true)
            content.ellipse(this.x+RightWingOffSet+wingsWidth/2,this.y,wingsWidth/2,20,0,0,Math.PI,false)
            content.fillStyle = Rocket.WingsHeadColor
            content.fill()

            // //绘制助推器
            content.beginPath()
            content.fillStyle = Rocket.WingsBoosterColor
            const xleftRocketPusherOffSet = wingsWidth
            const yRocketPusherOffSet = wingsHeight + 50/2
            const xRightRocketPusherOffSet = this.bodyWidth
            const pusherWidth = 90 * this.size
            const pusherHeight = 100 * this.size
            content.ellipse(this.x-xleftRocketPusherOffSet+xleftRocketPusherOffSet,this.y+yRocketPusherOffSet,pusherWidth,pusherHeight,0,Math.PI * 1.5,Math.PI,true)
            content.strokeStyle = Rocket.WingsBoosterColor
            content.lineTo(this.x,this.y+yRocketPusherOffSet)
            content.lineTo(this.x,this.y+yRocketPusherOffSet-pusherHeight)
            content.fill()

            content.beginPath()
            content.ellipse(this.x+xRightRocketPusherOffSet,this.y+yRocketPusherOffSet,pusherWidth,pusherHeight,0,Math.PI * 1.5,0,false)
            content.lineTo(this.x+xRightRocketPusherOffSet,this.y+yRocketPusherOffSet)
            content.lineTo(this.x+xRightRocketPusherOffSet,this.y+yRocketPusherOffSet-pusherHeight)
            content.fillStyle = Rocket.WingsBoosterColor
            content.fill()
            
        }
复制代码

6、添加火箭尾部

        drawRocketBooster(){
            content.beginPath()
            content.fillStyle = Rocket.RocketBoosterColor
            const boosterWidht = 140
            const boosterHeight = 40
            const boosterBottom = boosterWidht / 2
            const rectXOffSet = 30
            const circleXOffSet = rectXOffSet + boosterWidht/2
            content.fillRect(this.x+rectXOffSet*this.size,this.y+this.bodyHeight,boosterWidht * this.size, boosterHeight * this.size)
            content.fill()

            content.beginPath()
            content.fillStyle = Rocket.RocketBoosterColor
            content.ellipse(this.x+circleXOffSet*this.size,this.y+this.bodyHeight+boosterHeight * this.size,boosterBottom * this.size,20,0,0,Math.PI,false )
            content.fill()

        }
复制代码

7、添加火箭喷射火焰

     drawRocketFire(){
            content.beginPath()
            const fireXOffSet = this.bodyWidth/2 - (140 * this.size /2)+10
            const fireYOffSet = this.bodyHeight
            const fireWidth = 120 * this.size
            const fireHeight = this.bodyHeight/2 * this.size
            let grd = content.createLinearGradient(this.x+fireXOffSet, this.y+fireYOffSet, this.x+fireXOffSet, this.y+this.bodyHeight+fireHeight-this.fireYOffSet);
            grd.addColorStop(0,Rocket.RocketFireColor)
            grd.addColorStop(0.5,Rocket.RocketFireColor)
            grd.addColorStop(1,canvasBackgroundColor)
            content.fillStyle = grd
            content.fillRect(this.x+fireXOffSet,this.y+fireYOffSet,fireWidth,fireHeight+this.fireYOffSet)
            content.fill()
        }
复制代码

8、给个方法输出整个火箭

drawRocket(){
            this.drawRocketFire()
            this.drawRocketBooster()
            this.drawRocketBody()
            this.drawRocketBodyLogo()
            this.drawRocketWings()
        }
复制代码

9、创建火箭实例

    function init() {
        const rocket = new Rocket(1,900,300,1)
        rocket.drawRocket()
        return rocket
    }

    const rocket = init()
复制代码

基本效果是这样的

image.png

10、写个启动按钮给喷射火焰添加动效

animateFire(){
            this.fireYOffSet += 10
            const fireXOffSet = this.bodyWidth/2 - (140 * this.size /2)+10
            const fireYOffSet = this.bodyHeight
            const fireWidth = 120 * this.size
            const fireHeight = this.bodyHeight/2 * this.size
            content.clearRect(this.x+fireXOffSet,this.y+fireYOffSet,fireWidth,fireHeight+this.fireYOffSet)
            if (this.fireYOffSet >= 50 ) {
                this.fireYOffSet = 0
            }
            this.drawRocketFire()
            this.drawRocketBooster()
            this.drawRocketBody()
            this.drawRocketBodyLogo()
            this.drawRocketWings()
            Rocket.interval =  requestAnimationFrame(() => {
              this.animateFire()
            })
        }
复制代码

动起来是这样的

canvas-rocket2.gif

11、写个发射按钮发射火箭

launch(){
            const xStart = this.x - 90 * this.size
            const yStart = this.y - 150
            const xEnd =( 90*2+this.bodyWidth) * this.size
            const yEnd = 150 + this.bodyHeight + this.bodyHeight/2 * this.size
            content.clearRect(xStart,yStart,xEnd,yEnd)
            this.y -= this.launchSpeed
            if(this.y < -yEnd){
                this.y = HEIGHT
            }
            Rocket.interval =  requestAnimationFrame(() => {
                this.launch()
                this.drawRocket()
            })
        }
复制代码

发射是这样的

canvas-rocket2 (1).gif

12、写个停止按钮停止火箭

stop(){
        cancelAnimationFrame(Rocket.interval)
        Rocket.interval = null
   }
复制代码

效果图长这样

canvas-rocket2 (2).gif

完整代码参考

结语

至此,以后再也不用担心面试官问你会不会造火箭了。

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改