有没有办法从画布上清除一个元素而不消除其他元素? [英] Is there a way to clear an element from a canvas without eliminating the others?

查看:63
本文介绍了有没有办法从画布上清除一个元素而不消除其他元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用画布构建页面加载器,并使用es6类...尽管目前无法使其正常工作..原因之一是我找不到清除方法.进行中的画布.

I' m building a page loader with canvas, and using the es6 classes... ALthough at the moment I can't make it work properly.. one of the reason is that I can't find a way to clear the canvas in progression.

到目前为止,这是我的代码:

This is my code so far :

class Loader {

 constructor (width, height) {
    this.width = width
    this.height = height
}


_init() {
    this._createCanvas()
    this._bindEvents()
}
// create canvas
_createCanvas () {
    this.canvas = document.createElement("canvas")
    document.body.appendChild(this.canvas)
    this.canvas.id = "canvas"
    this.canvas.width = loader.width
    this.canvas.height = loader.height
}

_throttle (callback, delay) {
    let last
    let timer
    return function () {
        let context = this
        let now = +new Date()
        let args = arguments
        if (last && now < last + delay) {
            clearTimeout(timer)
            timer = setTimeout(function () {
                last = now
                callback.apply(context, args)
            }, delay)
        } else {
            last = now
            callback.apply(context, args)
        }
    }
}

// resize canvas
_resizeCanvas () {
    // resize canvas
    var canvasRatio = this.canvas.height / this.canvas.width;
    var windowRatio = window.innerHeight / window.innerWidth;
    var width;
    var height;

    if (windowRatio < canvasRatio) {
        height = window.innerHeight;
        width = height / canvasRatio;
    } else {
        width = window.innerWidth;
        height = width * canvasRatio;
    }

    this.canvas.width = width
    this.canvas.height = height
}

_bindEvents () {
// create events listeners
    this.resizeCanvas = this._throttle(function (event) {
        this._resizeCanvas()
    }.bind(this), 250)

    window.addEventListener('resize', this.resizeCanvas, false)
}

_unbindEvents () {
// remove events listeners
    window.removeEventListener('resize', this.resizeCanvas, false)
}


}



 class Snake {
   constructor( options = {} ) {
    this.options = {
        x: options.x,
        y: options.y,
        height: options.height,
        width: options.width,
        isMoving: options.isMoving || false,
        hasDispatched: options.hasDispatched || false,
        nextSnakeCallback: options.nextSnakeCallback || null,
        speed: options.speed || 4
    }
}

_init() {
    this._drawSnake()
}
start () {
    this.options.isMoving = true;
}

reset () {
    this.options.hasDispatched = false;
}

setNextSnakeCallback (callback) {
    this.options.nextSnakeCallback = callback;
}

_drawSnake() {
    this.canvas = document.getElementById("canvas")
    this.ctx = this.canvas.getContext("2d")
    this.ctx.beginPath()
    this.ctx.rect(
        this.options.x,
        this.options.y,
        this.options.width,
        this.options.height)
    this.ctx.fillStyle = "#f44242"
    this.ctx.fill()


}

_clearSnake () {
    this.ctx.clearRect(this.options.x, this.options.y, this.options.width, this.options.height);

}

}

 class SnakeTop extends Snake {

   constructor (options) {
    super(options)
  }

_init () {
    super._drawSnake()
    this._moveSnakeToRight()
    super._clearSnake()
}

reset () {
    this.options.x = this.options.height;
}

_moveSnakeToRight () {
    if(this.options.isMoving){

        this._clearSnake()
        this._drawSnake()

        if(this.options.x > loader.width - this.options.width && !this.options.hasDispatched){
            this.options.hasDispatched = true;
            if(this.options.nextSnakeCallback) {
                this.setNextSnakeCallback()
            }
        } else if(this.options.x >= loader.width){
            this.options.isMoving = false;
        }

        this.options.x += this.options.speed


    }

    window.requestAnimationFrame(this._moveSnakeToRight.bind(this));
   }

  }


class SnakeRight extends Snake {

   constructor (options = {}) {
       super(options)
   }

_init() {
    super._drawSnake()
    this._moveSnakeDown()
    super._clearSnake()
}

_moveSnakeDown () {
    if(this.options.isMoving) {
        this._clearSnake()
        this._drawSnake()

        if(this.options.y > loader.height - this.options.height && !this.options.hasDispatched){
            this.options.hasDispatched = true;
            if(this.options.nextSnakeCallback) {
                this.setNextSnakeCallback()
            }

        } else if (this.options.y > loader.height) {
            this.options.isMoving = false
        }
            this.options.y += this.options.speed
    }
    window.requestAnimationFrame(this._moveSnakeDown.bind(this));

     }
  }


class SnakeBottom extends Snake {

    constructor (options = {} ) {
      super(options)
}
_init() {
    super._drawSnake()
    this._moveSnakeToLeft()
    super._clearSnake()
}

_moveSnakeToLeft () {
    if (this.options.isMoving) {

        this._clearSnake()
        this._drawSnake()

        if(this.options.x < 0 && !this.options.hasDispatched){
            this.options.hasDispatched = true
            if(this.options.nextSnakeCallback) {
                this.setNextSnakeCallback()
            }
        } else if (this.options.x < this.options.width) {
            this.options.isMoving = false
        }
        this.options.x -= this.options.speed

    }

        window.requestAnimationFrame(this._moveSnakeToLeft.bind(this));
     }

  }


  class SnakeLeft extends Snake {
     constructor(options = {}) {
        super(options)
  }

_init() {
    super._drawSnake()
    this._moveSnakeUp()
    super._clearSnake()
}

_moveSnakeUp () {
    if(this.options.isMoving) {

        this._clearSnake()
        this._drawSnake()

        if(this.options.y < 0 && !this.options.hasDispatched) {
            this.options.hasDispatched = true
            if(this.options.nextSnakeCallback) {
                this.setNextSnakeCallback()
            }

        } else if ( this.options.y >  - this.canvas.height) {
            this.options.isMoving = false
        }
        this.options.y -= this.options.speed
    }
        window.requestAnimationFrame(this._moveSnakeUp.bind(this));
     }
  }




 // defining the elements on the DOM

   let loader = new Loader (600, 600)
    loader._init()

 //CREATE SNAKES
    let snakeT = new SnakeTop ({
     x: - 300,
     y: 0,
     height: 20,
     width: 300
    })
  snakeT._init()


 //ASSIGN NEXT SNAKE callback
   snakeT.setNextSnakeCallback (()=>{
    snakeR.reset();
    snakeR.start();
   });

  //START FIRST SNAKE
   snakeT.start();


以此类推,以构建其他3个元素.


and so on building the other 3 elements.

从jsfiddle中可以看到,我的函数drawSnake()继续在另一个之后绘制矩形

As you can see from the jsfiddle, my function drawSnake() keeps drawning a rectangle after the other

     https://jsfiddle.net/ombqfzjq/

在研究过程中,我发现可以清除矩形,而不是使用

During my research I found that to clear a rectangle, instead of using

ctx.clearRect(0,0,canvasWidth,canvasHeight);

可以清洁画布,我可以使用

that cleans the canvas, I can use

ctx.clearRect(square.x,square.y,square.w,square.h);

应该清除每个矩形...因此,在我的Snake类中,我构建了_clearSnake()函数,然后在需要时将其调用到我的子类中.

that should clean instead each single rectangle... So in my class Snake I built the _clearSnake() function, and then call it to my subclasses when needed it.

我的逻辑有什么问题?如何改善我的代码?

What's wrong in my logic? How can I improve my code?

推荐答案

一旦在画布上绘制了东西,就不能简单地删除该对象.

Once you've painted something onto a canvas you cannot simply remove that object.

画布"并不像HTML元素那样分层,因此删除对象不会在下面显示对象.

Canvas' aren't layered like HTML elements, so removing an object wouldn't show the objects beneath.

最干净的方法是重画之前的状态.

The cleanest way would be to re-paint the state before.

这篇关于有没有办法从画布上清除一个元素而不消除其他元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆