0
var canv = document.getElementById('canvas');
    ctx  = canv.getContext('2d');
canv.width  = window.innerWidth;
canv.height = window.innerHeight;     

class Element {
    constructor(props) {
        this.type = props.type || null;
        if (this.type == 'rect') {
            this.x = props.x;
            this.y = props.y;
            this.width = props.width || props.w;
            this.height = props.height || props.h;
            this.center = {x: this.x + this.width/2, y: this.y + this.height/2};
            this.text = props.text || null;
            this.color = props.color || 'red';
            this.clickable = props.clickable || false;
            this.draw = (context) => {
                context.fillStyle = this.color;
                context.fillRect(this.x, this.y, this.width, this.height);
                if (this.text != null) {
                    context.font = `bold ${this.text.font_size}px Arial`;
                    context.fillStyle = this.text.color;
                    context.fillText(this.text.content, this.center.x - this.text.content.length * this.text.font_size / 3, this.center.y + this.text.font_size / 2);
                }
            }
            var onclick = props.onclick || null; // Здесь (строка 27)
            this.onclick = (context = null) => { // Здесь (строка 28)
                if (this.clickable == true && onclick) {
                    console.log(this);
                    console.log(onclick);
                    onclick(context); // Здесь (строка 32)
                }
            }
        }
    }
}

var elements = {
    startButton: new Element({
        type: 'rect',
        x: 20,
        y: 20,
        width: 200,
        height: 110,
        color: 'rgba(61, 184, 97, .7)',
        text: {
            content: 'START',
            color: 'rgba(0, 28, 5, 1)',
            font_size: 30
        },
        clickable: true,
        onclick: (context) => {this.color = 'rgba(0,0,0,0)'} // Здесь (строка 54)
    })
}

var play = () => {
    ctx.drawImage(background, 0, 0, canv.width, canv.height);
    for (element in elements) {
        elements[element].draw(ctx);
    }
    requestAnimationFrame(play);
}

canv.onclick = (e) => {
    let click = {x: e.clientX, y: e.clientY};
    for (element in elements) {
        if (Math.abs(elements[element].center.x - click.x) <= elements[element].width / 2
            && Math.abs(elements[element].center.y - click.y) <= elements[element].height / 2) elements[element].onclick(ctx);
    } 
}

requestAnimationFrame(play);

Код длинный, но для понимания, я думаю, стоит видеть всё. Самые важные части, в которых заключается суть вопроса - я выделил комментариями в конце строк.

Я понимаю, что в строке 54 - this будет представлять собой window.

Я бы мог выражение this.color заменить на elements.startButton.color, но это выглядит топорно и неправильно.

Я бы мог в глобальную область видимости добавить функцию setColor, и вызывать её с помощью bind / call... Звучит уже лучше, но я бы всё-таки хотел узнать, можно ли без функций, с помощью this, присвоить свойству color новое значение.

Don2Quixote
  • 1,705
  • это нарушение инкапсуляции, не стоит так делать, Ваш вариант с методом setColor лучше – Stranger in the Q Mar 10 '19 at 11:01
  • @StrangerintheQ, Я изменил вопрос. Я же и метод setColor не могу достать через this. Так что этот метод должен висеть в window. – Don2Quixote Mar 10 '19 at 11:10
  • ну так то ссылку на экземпляр можно передать через тот же контекст, или вот так: onclick(context, this) – Stranger in the Q Mar 10 '19 at 11:13

0 Answers0