html холст статические объекты исчезают при перетаскивании другого

0

Я следил за tuturial на этом сайте, который был возобновлен, для создания перетаскиваемых объектов. Вот код сам по себе. Моя цель - создать игру с перетаскиваемым элементом (элементом, используемым для принятия решения) и тремя неперетачиваемыми фигурами (выбор).

Я не уверен, как сделать три объекта без перетаскивания. Я попытался сделать три квадрата с отдельными функциями (например, fillSquare), чтобы они не перетаскивались, но они исчезают, когда я перемещаю перетаскиваемый предмет, поражающий цель моей игры. Я уверен, что мне нужно использовать некоторые состояния холста, чтобы сохранить элементы на экране, но я все время путаюсь о том, как это сделать. Код ниже - это просто сокращенная версия того, что находится в ссылках, опубликованных выше. Любая помощь приветствуется.

function Shape(x, y, w, h, fill) {
    this.x = x || 0;
    this.y = y || 0;
    this.w = w || 1;
    this.h = h || 1;
    this.fill = fill || '#AAAAAA';
}

// Draws this shape to a given context
Shape.prototype.draw = function (ctx) {
    ctx.fillStyle = this.fill;
    ctx.fillRect(this.x, this.y, this.w, this.h);
}

// Determine if a point is inside the shape bounds
Shape.prototype.contains = function (mx, my) {
    // All we have to do is make sure the Mouse X,Y fall in the area between
    // the shape X and (X + Height) and its Y and (Y + Height)
    return (this.x <= mx) && (this.x + this.w >= mx) && (this.y <= my) && (this.y + this.h >= my);
}

function CanvasState(canvas) {
    // **** First some setup! ****
    this.canvas = canvas;
    this.width = canvas.width;
    this.height = canvas.height;
    this.ctx = canvas.getContext('2d');

    // fixes mouse co-ordinate problems  when there a border or padding. 
    var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop;
    if (document.defaultView && document.defaultView.getComputedStyle) {
        this.stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
        this.stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
        this.styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
        this.styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
    }

    //helps protect mouse coordinates for pages with fixed-position bars
    var html = document.body.parentNode;
    this.htmlTop = html.offsetTop;
    this.htmlLeft = html.offsetLeft;

    // **** Keep track of state! ****
    this.valid = false; // when set to false, the canvas will redraw everything
    this.shapes = []; // the collection of things to be drawn
    this.dragging = false; // Keep track of when we are dragging

    // the current selected object. In the future we could turn this into an array for multiple selection
    this.selection = null;
    this.dragoffx = 0; // See mousedown and mousemove events for explanation
    this.dragoffy = 0;

    // **** Then events! ****
    //saves a reference to CanvasState so we can use it in events
    var myState = this;

    // Up, down, and move are for dragging
    canvas.addEventListener('mousedown', function (e) {
        var mouse = myState.getMouse(e);
        var mx = mouse.x;
        var my = mouse.y;
        var shapes = myState.shapes;
        var l = shapes.length;
        for (var i = l - 1; i >= 0; i--) {
            if (shapes[i].contains(mx, my)) {
                var mySel = shapes[i];
                // Keep track of where in the object we clicked
                // so we can move it smoothly (see mousemove)
                myState.dragoffx = mx - mySel.x;
                myState.dragoffy = my - mySel.y;
                myState.dragging = true;
                myState.selection = mySel;
                myState.valid = false;
                return;
            }
        }
        // If there was an object selected, we deselect it
        if (myState.selection) {
            myState.selection = null;
            myState.valid = false; // Need to clear the old selection border
        }
    }, true);
    canvas.addEventListener('mousemove', function (e) {
        if (myState.dragging) {
            var mouse = myState.getMouse(e);
            // We don't want to drag the object by its top-left corner, we want to drag it
            // from where we clicked. Thats why we saved the offset and use it here
            myState.selection.x = mouse.x - myState.dragoffx;
            myState.selection.y = mouse.y - myState.dragoffy;
            myState.valid = false; // Something dragging so we must redraw
        }
    }, true);
    canvas.addEventListener('mouseup', function (e) {
        myState.dragging = false;
    }, true);

    // **** Options! ****
    this.selectionColor = '#CC0000';
    this.selectionWidth = 2;
    this.interval = 30;
    setInterval(function () {
        myState.draw();
    }, myState.interval);
}

CanvasState.prototype.addShape = function (shape) {
    this.shapes.push(shape);
    this.valid = false;
}

CanvasState.prototype.clear = function () {
    this.ctx.clearRect(0, 0, this.width, this.height);
}

// While draw is called as often as the INTERVAL variable demands,
// It only ever does something if the canvas gets invalidated by our code
CanvasState.prototype.draw = function () {
    // if our state is invalid, redraw and validate!
    if (!this.valid) {
        var ctx = this.ctx;
        var shapes = this.shapes;
        this.clear();

        // draw all shapes
        var l = shapes.length;
        for (var i = 0; i < l; i++) {
            var shape = shapes[i];
            // We can skip the drawing of elements that have moved off the screen:
            if (shape.x > this.width || shape.y > this.height || shape.x + shape.w < 0 || shape.y + shape.h < 0) continue;
            shapes[i].draw(ctx);
        }

        // draw selection
        if (this.selection != null) {
            ctx.strokeStyle = this.selectionColor;
            ctx.lineWidth = this.selectionWidth;
            var mySel = this.selection;
            ctx.strokeRect(mySel.x, mySel.y, mySel.w, mySel.h);
        }

        this.valid = true;
    }
}


// Creates an object with x and y defined, set to the mouse position relative to the state canvas
CanvasState.prototype.getMouse = function (e) {
    var element = this.canvas,
        offsetX = 0,
        offsetY = 0,
        mx, my;

    // Compute the total offset
    if (element.offsetParent !== undefined) {
        do {
            offsetX += element.offsetLeft;
            offsetY += element.offsetTop;
        } while ((element = element.offsetParent));
    }

    // Add padding and border style widths to offset
    // Also add the <html> offsets in case there a position:fixed bar
    offsetX += this.stylePaddingLeft + this.styleBorderLeft + this.htmlLeft;
    offsetY += this.stylePaddingTop + this.styleBorderTop + this.htmlTop;

    mx = e.pageX - offsetX;
    my = e.pageY - offsetY;

    // We return a simple javascript object (a hash) with x and y defined
    return {
        x: mx,
        y: my
    };
}

function init() {
    var s = new CanvasState(document.getElementById('canvas'));
    s.addShape(new Shape(40, 40, 50, 50)); // The default is gray
}
Теги:
canvas
html5-canvas
html5-draggable

1 ответ

0

Похоже, вам нужно использовать addShape() (см. Пример в функции init() в конце кода, который вы указали).

Почему не fillRect()? Поскольку каждый раз вызывается draw(), он вызывает clear(), а затем рисует фигуры, которые были добавлены через addShape().

Другими словами, холст ERASED перед каждым кадром рисуется... и затем формы, которые были добавлены через addShape() являются REDRAWN. Опять же, для акцента: весь этот рисунок происходит КАЖДОЙ РАМ. Ничего из предыдущего кадра не осталось!

Я бы предложил добавить свойство isDraggable для каждой фигуры, которую вы можете протестировать (и выйти раньше) в обработчиках событий мыши. Я бы начал с добавления его в качестве параметра функции addShape(), а затем сохранил его в свойстве созданной формы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню